Class 拦截具有字段访问的方法调用的切入点
Class pointcut that intercepts a method call with field access
我正在编写一些方面,以使我的 gradle pugin 开发更清晰一些。在gradle里面有一个界面,像这样
interface Plugin {
def apply(Project project);
}
应用于插件
class MyPlugin implements Plugin<Project> {
def apply(Project project) {
do stuff
}
}
现在,我希望能够像这样注释 class
@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'方法的时候检查,不能在实例化的时候检查。
这是一个完整的示例,但在 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)
我正在编写一些方面,以使我的 gradle pugin 开发更清晰一些。在gradle里面有一个界面,像这样
interface Plugin {
def apply(Project project);
}
应用于插件
class MyPlugin implements Plugin<Project> {
def apply(Project project) {
do stuff
}
}
现在,我希望能够像这样注释 class
@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'方法的时候检查,不能在实例化的时候检查。
这是一个完整的示例,但在 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)