楼主最近在学 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,感谢你看到这里,希望能得到建设性意见,谢谢。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.