如果有代码在同一项目中同时使用带有运行时编织/代理使用的 Spring AOP 和编译时编织,Spring Boot 会做什么。例如,假设您有一个如下所示的方面:
@Aspect
@Component
public class TestAspect {
// ...
}
@Component 的存在意味着我们正在使用 Spring AOP 和代理,并且你的 pom.xml 中有这个
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.11</version>
<executions>
<execution>
<goals>
<goal>compile</goal> <!-- use this goal to weave all your main classes -->
<goal>test-compile</goal> <!-- use this goal to weave all your test classes -->
</goals>
</execution>
</executions>
</plugin>
这意味着我们正在使用编译时编织。
哪一个优先?是使用编译时编织还是代理?
嗯,你为什么不尝试一下呢?那不是比问更快吗?好的,这是我的想法:
aspectjrt.jar
。如果是这种情况,无论有没有 Spring,应用程序都应该正常运行。<aspectLibraries>
配置在 AspectJ Maven 中引用它来实现这一点。底线:您不能混合使用 Spring AOP 和 AspectJ LTW,但您应该能够使用 Spring AOP + AspectJ CTW。您应该有充分的理由这样做并了解自己在做什么。
我最近遇到了一种情况,当 AspectJ (P)CTW 启动时,Spring AOP 似乎被禁用,但不是应用程序明智的,而是类明智的。在 Spring 代码中进行一些调试后,我发现上述观察结果是有条件的
在我们的例子中,我们使用
aspectOf()
将ajc切面注册为bean,以便切面也可以注入spring bean依赖项。这使得 Spring 可以看到这些方面。
Spring AOP 将所有
@Aspect
bean 注册为 Advisor
,并在创建代理 bean 时在创建 bean 时查找它。
(代理bean,因此在创建时,已经确定了合格的方面)
测试 Advisor 是否有资格使用目标 bean 时,
AspectJExpressionPointcut.matches(Class<?> targetClass)
在调用堆栈中被调用(可能仅适用于 InstantiationModelAwarePointcutAdvisorImpl
左右)。
并且aspectOf()创建的方面的相关顾问在这一行测试失败(this.aspectCompiledByAjc && compiledByAjc(targetClass))
前者是正确的,因为我们使用了 aspectOf()
,后者实际上使用一些临时逻辑检查类定义是否有 ajc 编译的迹象。
总而言之,具有
Advisor
类型 AspectJExpressionPointcut
的 ClassFilter
不能应用于已经 ajc 编织的类
(@Transactional
的顾问使用TransactionAttributeSourcePointcut
并且不检查ajc编译是否发生,因此基于spring代理的@Transactional甚至可以在ajc编译的类上工作)