Aspect Ajc 编译期增强

328 阅读1分钟

image.png

Aspect Ajc 编译期增强

image.png

今天介绍如何使用 Aspect Ajc 编译器,在编译期间对代码进行增强.

切面类
@Aspect
public class MyAspect {

    private static final Logger LOG = LoggerFactory.getLogger(MyAspect.class);

    @Before("execution(* org.devx.spring.certified.professional.edu.course.a09.aopajc.MyService.*())")
    public void before() {
        LOG.info("*********************** MyAspect before ***********************");
    }
}
目标类
public class MyService {
    private static final Logger LOG = LoggerFactory.getLogger(MyService.class);

    public void hello() {
        LOG.info("{} hello" , this.getClass());
        fun0();
    }

    public void fun0() {
        LOG.info("************************ fun0 ************************");
    }

    public static void fun1() {
        LOG.info("************************ fun1 ************************");
    }

}
public class A09Application {

    private static final Logger LOG = LoggerFactory.getLogger(A09Application.class);

    public static void main(String[] args) {
    
        new MyService().hello();

        // 可以增强 static 方法
        MyService.fun1();
    }
}

运行测试代码得到如下日志输出,从测试结果上来看对 static 方法也实现了增强,对方法内部调用的同类中的方法也实现了增强,功能很强大。

21:56:15.756 [main] INFO org.devx.spring.certified.professional.edu.course.a09.aopajc.MyAspect - *********************** MyAspect before ***********************
21:56:15.759 [main] INFO org.devx.spring.certified.professional.edu.course.a09.aopajc.MyService - class org.devx.spring.certified.professional.edu.course.a09.aopajc.MyService hello
21:56:15.761 [main] INFO org.devx.spring.certified.professional.edu.course.a09.aopajc.MyAspect - *********************** MyAspect before ***********************
21:56:15.761 [main] INFO org.devx.spring.certified.professional.edu.course.a09.aopajc.MyService - ************************ fun0 ************************
21:56:15.761 [main] INFO org.devx.spring.certified.professional.edu.course.a09.aopajc.MyAspect - *********************** MyAspect before ***********************
21:56:15.761 [main] INFO org.devx.spring.certified.professional.edu.course.a09.aopajc.MyService - ************************ fun1 ************************

Ajc 编译后的目标类

编译时直接对 class 文件进行修改,所以无论是静态方法还是非静态方法都可以进行增强。

public class MyService {
    private static final Logger LOG = LoggerFactory.getLogger(MyService.class);

    public MyService() {
    }

    public void hello() {
        MyAspect.aspectOf().before();
        LOG.info("{} hello", this.getClass());
        this.fun0();
    }

    public void fun0() {
        MyAspect.aspectOf().before();
        LOG.info("************************ fun0 ************************");
    }

    public static void fun1() {
        MyAspect.aspectOf().before();
        LOG.info("************************ fun1 ************************");
    }
}

如何使用 Ajc 编译

Ajc 编译与 Lombok 存在冲突,一起使用时会存在问题。

pom.xml 中加入 aspectj-maven-plugin 插件。

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>aspectj-maven-plugin</artifactId>
    <version>1.14.0</version>
    <configuration>
        <complianceLevel>1.8</complianceLevel>
        <source>8</source>
        <target>8</target>
        <showWeaveInfo>true</showWeaveInfo>
        <verbose>true</verbose>
        <xlint>ignore</xlint>
        <encoding>UTF-8</encoding>
        <weaveDirectories>
            <weaveDirectory>${project.build.directory}/classes</weaveDirectory>
        </weaveDirectories>
    </configuration>
    <executions>
        <execution>
            <phase>process-classes</phase>
            <goals>
                <goal>compile</goal>
                <goal>test-compile</goal>
            </goals>
        </execution>
    </executions>
</plugin>

idea Java Compiler 配置中选择使用 Ajc 编译。

image.png

更多的技术干货、原理会在系列文章的后续内容中提供。该文章会同步在微信公众号 【DevXJava】, 方便在微信客户端阅读。


DevXJava 不止于技术