aspectj编程简介

  现在java生态中spring大行其道,一般使用aspectj进行切面编程使用注解方式实现,比较少使用原生的aspectj编程,网上的资料也比较少。最近工作中需要封装redisson客户端提供统一的redis组件,主要就是实现耗时日志打印以及上报,压测支持等功能。为了避免组件依赖spring的情况,使用了aspectj原生库编程。工程基于jdk1.8。

1.aspectj介绍

  aspectj定义(来自wiki):AspectJ是在PARC为Java编程语言创建的面向方面的编程扩展。它可以在Eclipse Foundation开源项目中使用,既可以单独使用,也可以集成到Eclipse中。

  关于面向切面编程,这里不再赘述,一般用于实现通用的功能,比如日志打印,权限控制等。aspectj通过定义切面,将

2.配置以及使用

2.1配置

  aspectj依赖两个核心库(aspectjrt,aspectjweaver),所以在需要在工程pom文件中添加一下依赖

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.9</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.9</version>
        </dependency>

  要使aspectj织入功能生效还需要添加aspectj-maven-plugin插件,配置如下。

<build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>aspectj-maven-plugin</artifactId>
                <version>1.7</version>
                <configuration>
                    <complianceLevel>1.8</complianceLevel>
                    <source>1.8</source>
                    <target>1.8</target>
                    <showWeaveInfo>true</showWeaveInfo>
                    <verbose>true</verbose>
                    <Xlint>ignore</Xlint>
                    <encoding>UTF-8</encoding>
                    <weaveDependencies>
                        <weaveDependency>
                            <groupId>org.redisson</groupId>
                            <artifactId>redisson</artifactId>
                        </weaveDependency>
                    </weaveDependencies>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <!-- use this goal to weave all your main classes -->
                            <goal>compile</goal>
                            <!-- use this goal to weave all your test classes -->
                            <!--<goal>test-compile</goal>-->
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

  aspectj可以选择织入的时期,主要分为三种:编译时,编译后,运行期。编译时织入只对织入代码在本工程的情况,编译后织入除了本工程代码还包括针对织入代码在第三方jar包情况,运行时织入只有在代码运行时才做动态切面。上面这个例子是编译后的配置,其中weaveDependencies配置了第三方jar包信息,只需要编译是织入可以不用配置。运行时织入参考(https://www.baeldung.com/aspectj)

2.2 aspect编写

  切面类代码如下

/** * @date 2018/12/22
 */
public aspect CommandAspect {

    /**
     * redis命令方法切面,所有redis命令都会经过
     */
    public pointcut callSendCommand():
            execution (* org.redisson.command.CommandAsyncService.sendCommand(..));

    /**
     * RedissonExpirable的所有子类方法切面,基本包含了redisson内置的常用数据结构
     */
    public pointcut callExpireSubClassMethod():
            execution (* org.redisson.RedissonExpirable+.*(..));


    Object around(): callSendCommand() {
        //long startNs = System.nanoTime();
        Object result = proceed();
        //AspectUtil.sendMetrics(startNs, thisJoinPoint);
        return result;
    }

    Object around(): callExpireSubClassMethod(){
        Object result = proceed();
        //AspectUtil.resetExpireTime(thisJoinPoint);
        return result;
    }
}

  对于熟悉注解方式实现的同学可以发现,这种方式与注解方式十分相像,这里是实现了around,同样也支持before,after方式。在idea intellij调试时,无法在apsect类中断点,但是可以在其依赖的class类中断点,这对于我们第一次编码的时候存在一些困扰。

  编码完成后,使用mvn compile命令,实现代码织入,之后就可以进行调试了

参考文档:

http://opoo.org/aspectj-compile-time-weaving/

https://www.baeldung.com/aspectj

原文地址:https://www.cnblogs.com/blueSkyline/p/10177589.html