适合有一定spring基础的人阅读。
ajc编译
此方法是再编译阶段进行的增强,大家先看效果,后面我会讲解原理及使用。
演示
首先来介绍一下大家可能会比较陌生的吧,ajc编译,大家看到这个可能不知道是个什么玩意儿,话不多说,先看看效果。
我们先来定义两个类,用来增强的类和目标类。
目标类:
java
@Service // 添加该类的bean到容器中,方便后续的测试,不加也可以增强(后续会将)
public class MyService {
// 使用日志来打印,方便观察结果,不要使用@Slf4j注解,该增强方法不兼容,编译会报错
private static final Logger log = LoggerFactory.getLogger(MyService.class);
public void foo() {
log.info("我是目标方法!");
}
}
增强类:
java
@Aspect// 不用加@Component后续会讲增强原理
public class MyAspect {
// 作用同上
private static final Logger log = LoggerFactory.getLogger(MyAspect.class);
// 通知方法,匹配我上面的目标方法,根据自身情况改变
@Before("execution(* com.huang.service.MyService.*())")
public void before() {
log.info("before");
}
}
启动类:
java
@SpringBootApplication
public class Main {
public static void main(String[] args) {
// 获取springboot的容器对象
ConfigurableApplicationContext run = SpringApplication.run(Main.class, args);
// 从容器中获得目标bean
MyService service = run.getBean(MyService.class);
// 打印查看获取到的bean类型,是原始类型还是代理
System.out.println(service.getClass());
// 运行方法,查看是否被增强
service.foo();
}
}
运行截图奉上:
从图中我们可以看到,我们的 MyService 类并没有被代理,但是foo()
方法被增强了。
其实这个是使用了Aspectj的编译器进行的增强,把我们的MyService
的类进行了改写(后续会讲怎么使用的)。
找到项目中MyService
的字节码文件打开(idea会自动进行反编译)
可以看到日志输出之前调用before()
方法
总结
我们的增强类没有加@Component
,并不是由spring进行的管理,而是由Aspectj的编译器来读到这个切面,根据这个切面来进行增强,所以我们不需要使用spring也可以达到增强的效果。
修改后的启动类:
java
public class Main {
public static void main(String[] args) {
// 直接new对象
MyService myService = new MyService();
// 调用方法
myService.foo();
}
}
运行结果:
从运行结果中可以看到, MyService
类依然被增强了
使用
我们需要在项目中添加一个编译器插件,maven代码如下:
xml
<build>
<plugins>
<!-- 编译时织入插件 -->
<plugin>
<groupId>dev.aspectj</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.14</version>
<configuration>
<complianceLevel>8</complianceLevel> <!-- Java 版本 -->
<source>8</source>
<target>8</target>
<showWeaveInfo>true</showWeaveInfo>
<forceAjcCompile>true</forceAjcCompile>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
这里我只给出了编译器插件的部分,如果需要使用其他的依赖,请自行添加依赖。
如果添加了之后运行没有被增强,可以先使用maven编译之后再运行
请不要使用@Slf4j
注解,Aspectj编译器并不支持
此方法可以增强静态方法,这是代理所不能做到