楼主最近在学 Spring,按照《 Spring in Action 》上面的运行时注入 AspectJ 切面的 demo 敲,发现了一个目前找不到解决办法的问题,代码运行时提示 找不到引用( Java/Kotlin )、ClassNotFoundException ( XML 文件),Google 了半天,在 StackOverflow 上看到了相似的情况,同样没有找到解决办法,自己也琢磨不出,只能向有经验的 V 友求助
demo 大致思路:一个表演类“ MyPerformance ”,其中定义方法 perform
,也就是切点。一个 AspectJ 类
CriticAspect
,定义在同名 aj 文件中,在其中定义通知。表演结束之后打印一段字符串。具体代码如下
@Component
open class MyPerformance: Performance {
override fun perform() {
println("Start perform")
}
}
AspectJ 文件 CriticAspect.aj
public aspect CriticAspect {
public CriticAspect() { }
pointcut performance(): execution(* concert.MyPerformance.perform(..));
after(): performance() {
System.out.println("something");
}
}
下面是 XML 配置文件 concert.xml 。根据书上所说,Spring 不能负责创建 CriticAspect,需要由 AspectJ 运行期创建,因此得为 Spring 获得已经由 AspectJ 创建好的实例的引用。书上的例子采用的是 XML 的方式,通过切面的静态方法 aspectOf 返回实例
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="concert" />
<aop:aspectj-autoproxy />
<bean class="concert.CriticAspect" factory-method="aspectOf" />
</beans>
下面是测试代码
@RunWith(SpringJUnit4ClassRunner::class)
@ContextConfiguration(locations = ["classpath:concert.xml"])
class PerformTest {
@Autowired
lateinit var performance: Performance
@Test
fun perform() {
performance.perform()
}
}
运行失败,报错信息摘录如下
......
严重: Caught exception while allowing TestExecutionListener
[org.springframework.test.context.support.DependencyInjectionTestExecutionListener@491cc5c9] to prepare test instance [concert.PerformTest@74c79fa2]
java.lang.IllegalStateException: Failed to load ApplicationContext
......
Caused by: org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [concert.CriticAspect] for bean with name 'concert.CriticAspect#0' defined in class path resource [concert.xml]; nested exception is java.lang.ClassNotFoundException: concert.CriticAspect
......
Caused by: java.lang.ClassNotFoundException: concert.CriticAspect
......
如果以 JavaConfig 的方式配置,按照 StackOverflow 上一个回答 我找到了 aspectOf 的接口,以下为 Kotlin 代码
@Configuration
@EnableAspectJAutoProxy
@ComponentScan
open class ConcertConfig {
@Bean
open fun criticAspect(): CriticAspect = org.aspectj.lang.Aspects.aspectOf(CriticAspect::class.java)
}
运行之后 IEDA 报错
Error:(13, 30) Kotlin: Unresolved reference: CriticAspect
Java 形式我也试过,一样的报错信息:"找不到引用: CriticAspect"。在 StackOverflow 上看到了相同的问题How to resolve the following AspectJ aspect ClassNotFoundException? ,两个回答都没有解决办法
除了使用 aj 文件动态织入之外的代码都是正确运行的,包括使用 Spring 支持的 AOP 注解,错误只有在引入了 AspectJ 文件之后才出现。比如将 XML 配置文件中声明 bean 的那行删去,demo 正常工作,将 JavaConfig 中那个 bean 方法去掉其他部分也能正常工作。
开发环境为 Win10 + IDEA + JDK 11 + Kotlin,感谢你看到这里,希望能得到建设性意见,谢谢。
并不愿意在这上面花费过多时间和精力,目的还是在于理解 Spring AOP 的知识并完成博客的学习笔记:Spring 学习笔记(三):面向切面 | ReBE。
楼主将不再纠结 AspectJ 的问题,留着日后有空解决吧
1
Allianzcortex 2019-06-03 01:51:15 +08:00
1. 《 Spring In Action 》第五版已经出来,集成了 Spring Boot,并且取消了 AspectJ 这部分内容(专门再搜了下,整本书没有出现 "AspectJ" 这个关键词),楼主考虑换成这个版本的?
2. 不知道为什么会出现这种情况,已经好久没有看过 XML 配置文件了...我当时用注解实现的 AspectJ 代码在这里 https://github.com/Allianzcortex/LaraForum/blob/master/src/main/java/com/laraforum/authorization/RolesAndPermissionsChecker.java#L52,调用时就像 Python @Decorator 一样调用: https://github.com/Allianzcortex/LaraForum/blob/104b16fcd8847aa84bb9f5947d57f8c848fb3e5a/src/main/java/com/laraforum/controller/OtherController.java#L86 |
2
Febers OP @Allianzcortex 其实我是准备重点学习 Spring Boot,但是绕不过 Spring,所以准备快速过一遍,但是没想到遇到问题了。
我看了你的代码了,其实我也不喜欢 XML 文件,所以一直用的注解配置,然后也没出问题,直到遇到了 aj 文件。出问题了才用 XML 过一遍好定位原因。 感谢你的回复。 |
3
Febers OP 整个问题可以概括为: 为什么 Spring 无法识别 aspect 类型的类文件
|
4
Allianzcortex 2019-06-03 02:09:32 +08:00
@Febers 不知道为什么会有 .aj 这种文件,一开始就是在 .java 里定义切面。官网和博客资料会好很多,那本书太大而全了,真要跑起来还要学 thymeleaf 模板🙄
|
5
Febers OP @Allianzcortex 对的,我也很无语╯﹏╰
|
6
lil460982475 2019-06-03 08:55:57 +08:00
以前看过相关概念,但没有实践过。.aj 文件并不是 Java 类,你虽然有这个文件,xml 也定义了,但应该不能直接识别,需要将 .aj 通过专门的编译器编译成 class 文件。
看下这篇文章,看有没有帮助。https://blog.csdn.net/javazejian/article/details/56267036 |
7
lil460982475 2019-06-03 08:58:10 +08:00
对了,spring 你要使用切面技术,并不需要使用 apectj 框架的语法去定义,spring aop 已经能让你使用 java+spring 代码去实现了,没必要
|
8
Febers OP @lil460982475 对的,目前的进展就到这一步,需要 ajc 编译器,等会查阅相关资料试试
|
9
Febers OP @lil460982475 应该就是这篇文章所讲:https://m.w3cschool.cn/intellij_idea_doc/intellij_idea_doc-woks2nde.html
Spring aop 确实已经满足要求,不过我是一边学下边做笔记,遇到这种情况跳不过去 |
10
gz911122 2019-06-03 11:01:46 +08:00
AspectJ 和 spring 没有什么关系的
AspectJ 插件装了吗? ajc 设置了吗? |
11
gz911122 2019-06-03 11:04:27 +08:00
@gz911122 再概括一下,spring aop 和 aspectJ 一毛钱关系也没有
只不过 spring 借用了 aspectJ 的注解而已 |
12
Febers OP @gz911122 #10 AspectJ 插件一开始就装了。按照[ Mojo's AspectJ Maven Plugin]( https://www.mojohaus.org/aspectj-maven-plugin/usage.html)这个插件设置了 ajc,IDE Compiler 也没问题。但是又遇到问题了,这回是 ajc 的
Error:ajc: can't find critical required type java.io.Serializable Error:ajc: can't find critical required type java.lang.Cloneable Google 只找到几条零碎的信息 |