类切入点截取具有字段访问权限的方法调用

时间:2018-07-09 17:18:12

标签: aop aspectj

我正在写一些方面的内容,以使我的gradle pugin开发更加简洁。在gradle中,有一个像这样的界面

interface Plugin { 
  def apply(Project project); 
}

应用于插件

class MyPlugin implements Plugin<Project> {
  def apply(Project project) {
    do stuff
  }
}

现在,我希望能够像这样注释此类

@OnlyAllowedOnRoot
class MyPlugin implements Plugin<Project> {
  def apply(Project project) {
    do stuff
  }
}

,并具有一个切入点,该切入点在触发“ apply”方法时触发,并拾取参数。因为切入点的逻辑是

if (project.rootProject.name != project.name) {
  throw new GradleScriptExeption("This plugin can only be applied to root")
}

我该怎么做?这个例子是我想写的其他十几个切入点的基础,但是我真的不知道从哪里开始。我知道我可以直接注释apply方法,但是我担心可读性,这主要是我这样做的原因。如果可以的话我可以,但是我可以不用身份证。而且由于Gradle的生命周期,在调用“ apply”方法时必须对其进行检查,因此无法在实例化时对其进行检查。

1 个答案:

答案 0 :(得分:1)

这是一个完整的示例,但是在Java中而不是在Groovy中。但是,如果使用Groovy,则应该没有任何区别。顺便说一句,我不想​​将Gradle API作为依赖项添加到我的项目中,所以我只是使用正确的包名称和签名复制了其API的相关部分。我自己不是Gradle用户,所以我将根项目属性分层实现为直接父级,而不是绝对根。如果Gradle采取不同的方式,则只需调整方面的条件即可将异常返回给您自己的示例代码。

Gradle API:

package org.gradle.api;

public class Project {
  private String name;
  private Project rootProject;

  public Project(String name, Project rootProject) {
    this.name = name;
    this.rootProject = rootProject;
  }

  public String getName() {
    return name;
  }

  public Project getRootProject() {
    return rootProject;
  }

  @Override
  public String toString() {
    return "Project(name = " + name + ", rootProject = " + rootProject + ")";
  }
}
package org.gradle.api;

public interface Plugin<T> {
  void apply(T target);
}
package org.gradle.api;

public class GradleScriptExeption extends RuntimeException {
  private static final long serialVersionUID = 1L;

  public GradleScriptExeption(String message, Throwable cause) {
    super(message, cause);
  }
}

标记注释+插件:

package de.scrum_master.app;

import org.gradle.api.Plugin;
import org.gradle.api.Project;

class NormalPlugin implements Plugin<Project> {
  public void apply(Project project) {}
}
package de.scrum_master.app;

import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;

@Retention(RUNTIME)
public @interface OnlyAllowedOnRoot {}
package de.scrum_master.app;

import org.gradle.api.Plugin;
import org.gradle.api.Project;

@OnlyAllowedOnRoot
class RootPlugin implements Plugin<Project> {
  public void apply(Project project) {}
}

驱动程序应用程序:

package de.scrum_master.app;

import org.gradle.api.Project;

public class Application {
  public static void main(String[] args) {
    Project rootProject = new Project("root", null);
    Project childProject = new Project("child", rootProject);
    Project grandChildProject = new Project("grandchild", childProject);

    NormalPlugin normalPlugin = new NormalPlugin();
    normalPlugin.apply(rootProject);
    normalPlugin.apply(childProject);
    normalPlugin.apply(grandChildProject);

    RootPlugin rootPlugin = new RootPlugin();
    rootPlugin.apply(rootProject);
    rootPlugin.apply(childProject);
    rootPlugin.apply(grandChildProject);
  }
}

方面:

package de.scrum_master.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.gradle.api.GradleScriptExeption;
import org.gradle.api.Plugin;
import org.gradle.api.Project;

@Aspect
public class GradlePluginAspect {
  @Pointcut("execution(void apply(*)) && target(plugin) && args(project)")
  private static void pluginExecution(Plugin plugin, Project project) {}

  @Before("pluginExecution(plugin, project) && @target(de.scrum_master.app.OnlyAllowedOnRoot)")
  public void illegalRootPlugin(JoinPoint thisJoinPoint, Plugin plugin, Project project) {
    if (project.getRootProject() != null)
      throw new GradleScriptExeption("Cannot apply " + plugin.getClass().getSimpleName() + " to non-root project " + project, null); 
  }

  @Before("pluginExecution(plugin, project)")
  public void logPluginApply(JoinPoint thisJoinPoint, Plugin plugin, Project project) {
    System.out.println("Applying " + plugin.getClass().getSimpleName() + " to " + project);
  }
}

控制台日志:

Applying NormalPlugin to Project(name = root, rootProject = null)
Applying NormalPlugin to Project(name = child, rootProject = Project(name = root, rootProject = null))
Applying NormalPlugin to Project(name = grandchild, rootProject = Project(name = child, rootProject = Project(name = root, rootProject = null)))
Applying RootPlugin to Project(name = root, rootProject = null)
Exception in thread "main" org.gradle.api.GradleScriptExeption: Cannot apply RootPlugin to non-root project Project(name = child, rootProject = Project(name = root, rootProject = null))
    at de.scrum_master.aspect.GradlePluginAspect.illegalRootPlugin(GradlePluginAspect.aj:19)
    at de.scrum_master.app.RootPlugin.apply(RootPlugin.java:8)
    at de.scrum_master.app.Application.main(Application.java:18)