简体   繁体   English

如何创建要由gradle预编译运行的注释处理器以向方法添加代码?

[英]How create annotation processor to be run by gradle pre-compile to add code to methods?

We have some code that needs to be run in a lot of methods and it's tedious for our developers to have to write this over and over (and also we want to allow for the APIs called to be able to change without the need to change any code that would use it). 我们有一些代码需要在许多方法中运行,并且对于我们的开发人员而言,必须一遍又一遍地编写代码(这也是一件很乏味的事情(而且我们还希望允许所调用的API能够更改而不需要更改任何API)。使用它的代码)。

Our idea is to put a custom annotation on methods that would call this code, and we would write our own Annotation processing code that would look for that annotation and then add the code to the end of the method prior to compilation (but when they look in the IDE at the file after this, the code still wouldn't be there). 我们的想法是在调用此代码的方法上添加自定义注释,然后编写自己的注释处理代码,该代码将查找该注释,然后在编译之前将代码添加到方法的末尾(但是当它们看起来在IDE中位于此文件之后的位置,代码仍然不存在)。

How would I achieve this? 我将如何实现? What would I need to do to make something called by Gradle, able to alter the method definitions passed to the compiler/builder and able to read the annotations on the methods? 我需要做些什么来使Gradle调用它,能够更改传递给编译器/生成器的方法定义,并能够读取方法上的注释?

(We are using Spring Boot as well as Gradle, but that might not make a difference) (我们使用的是Spring Boot和Gradle,但这可能没有什么不同)

Spring AOP is good enough to accomplish your requirement. Spring AOP足以满足您的要求。

This is an small example to give you an idea: There are two classes and each one have three methods in common: play(), addPlayer() and gameover(), and each time that the play method is called the program have to call a routine to print a text, with AOP you don't need to repeat the same code. 这是一个使您有所了解的小示例:有两个类,每个类共有三个共同的方法:play(),addPlayer()和gameover(),并且每次调用play方法时,都必须调用该程序一个例程来打印文本,使用AOP,您无需重复相同的代码。

For organization order I will use an interface, it is not mandatory but it's a good practice: 对于组织顺序,我将使用一个接口,该接口不是必需的,但这是一个好习惯:

Game Interface: 游戏介面:

public interface Game {
    void play();
    void addPlayer(String name);
    void gameOver();
}

A soccer class that implements Game 实施比赛的足球课

public class Soccer implements Game {
    @Override
    public void play() {
        System.out.println("Soccer Play started");
    }

    @Override
    public void addPlayer(String name) {
        System.out.println("New Soccer Player added:" + name);
    }

    @Override
    public void gameOver() {
        System.out.println("This soccer Game is Over");
    }
}

A Baseball class that implements Game 实现游戏的棒球课

public class Baseball implements Game {
    @Override
    public void play() {
        System.out.println("Baseball game started at " + new Date());
    }

    @Override
    public void addPlayer(String name) {
        System.out.println("New Baseball Player added: " +name);
    }

    @Override
    public void gameOver() {
        System.out.println("The game is over");
    }
}

Now the Aspect configuration to catch when the play method is called 现在,当调用play方法时要捕获的Aspect配置

@Aspect
@Component
public class AspectConfiguration {

    @Before("execution(* org.boot.aop.aopapp.interfaces.Game.play(..))")
    public void callBefore(JoinPoint joinPoint){
        System.out.println("Do this allways");
        System.out.println("Method executed: " + joinPoint.getSignature().getName());
        System.out.println("******");
    }
}

The @Before annotation means that the method will be called before play method is executed. @Before注释意味着将在执行play方法之前调用该方法。 Also you need to specify a pointcut expression the tell Aspect how to match the method call that you need to trigger. 另外,您还需要指定一个切入点表达式,以告诉Aspect如何匹配您需要触发的方法调用。 For example in this case we use the play method and it is the pointcut expression: "execution(* org.boot.aop.aopapp.interfaces.Game.play(..))" 例如,在这种情况下,我们使用play方法,它是切入点表达式: "execution(* org.boot.aop.aopapp.interfaces.Game.play(..))"

And finally the Spring Boot Application Class: 最后是Spring Boot Application类:

@EnableAspectJAutoProxy
@SpringBootApplication
public class AopappApplication {

    public static void main(String[] args) {

        Game soccer=null;

        Game baseball=null;

        AnnotationConfigApplicationContext ctx = (AnnotationConfigApplicationContext) SpringApplication.run(AopappApplication.class, args);
        soccer = (Game) ctx.getBean("soccer");
        baseball = (Game) ctx.getBean("baseball");

        soccer.play();
        baseball.play();

        soccer.addPlayer("Player 1");
        soccer.addPlayer("Player 2");

        baseball.addPlayer("Player 23");

        soccer.gameOver();
        baseball.gameOver();
    }

    @Bean("soccer")
    public Game soccer(){
        return new Soccer();
    }

    @Bean("baseball")
    public Game baseball(){
        return new Baseball();
    }
}

There is a god documentation about Spring AOP plese see the following link. 有一个关于Spring AOP plese的上帝文档,请参见以下链接。 Spring AOP Doc. 春季AOP文件

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM