我克隆了你的 GitHub 项目,然后添加了
implementation 'org.springframework:spring-instrument'
您还应该将 Spring(事务)方面的范围限制为仅编织您自己的应用程序类,以避免在尝试编织 Spring 自己的类时出现大量 [Xlint:cantFindType] 消息。您可以通过提供自己的src/main/resources/org/aspectj/aop.xml 文件来做到这一点,如下所示:
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<!-- You can also add -Xlint:ignore in order to avoid lots of '[Xlint:cantFindType]' warnings -->
<weaver options="-verbose -showWeaveInfo">
<!-- Only weave classes in our application-specific packages -->
<include within="com.example.aspectj..*"/>
</weaver>
</aspectj>
编织器选项还可以更轻松地查看哪些方面被编织到哪些连接点中,例如在启动过程中您会看到
[AppClassLoader@77556fd] weaveinfo Join point 'method-execution(void com.example.aspectj.services.FooService.m2())' in Type 'com.example.aspectj.services.FooService' (FooService.java:27) advised by around advice from 'org.springframework.transaction.aspectj.JtaAnnotationTransactionAspect' (AbstractTransactionAspect.aj:67)
这证明FooService.m2()实际上正在被编织。
对于不太“嘈杂”的 AspectJ 编织器,只需使用 <weaver options="-showWeaveInfo -Xlint:ignore"> - 不再有警告或有关注册哪些方面的信息,但仍然是有关编织连接点的信息,这很重要,IMO。
然后我使用 Spring 工具和 AspectJ 编织器代理启动应用程序。只有前者不足以启动仪器,我需要两个代理。因为在 JDK 16+ 上,您需要将 java.lang 包打开到未命名的模块才能应用 LTW,并且我正在最近的 JDK 上进行测试,所以我还添加了相应的 --add-opens 选项(在 JDK 15 之前不需要):
--add-opens java.base/java.lang=ALL-UNNAMED
-javaagent:.../aspectjweaver-1.9.7.jar
-javaagent:.../spring-instrument-5.3.12.jar
然后一切正常:
o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
com.example.aspectj.AspectjApplication : Started AspectjApplication in 7.339 seconds (JVM running for 10.046)
com.example.aspectj.AspectjApplication : running ..
com.example.aspectj.services.FooService : m1 : called
o.s.orm.jpa.JpaTransactionManager : Creating new transaction with name [com.example.aspectj.services.BooService.m3]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
o.s.orm.jpa.JpaTransactionManager : Opened new EntityManager [SessionImpl(1516190088<open>)] for JPA transaction
o.s.orm.jpa.JpaTransactionManager : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@543f6ccb]
com.example.aspectj.services.BooService : m3 : called
o.s.orm.jpa.JpaTransactionManager : Initiating transaction commit
o.s.orm.jpa.JpaTransactionManager : Committing JPA transaction on EntityManager [SessionImpl(1516190088<open>)]
o.s.orm.jpa.JpaTransactionManager : Closing JPA EntityManager [SessionImpl(1516190088<open>)] after transaction
o.s.orm.jpa.JpaTransactionManager : Creating new transaction with name [com.example.aspectj.services.FooService.m2]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
o.s.orm.jpa.JpaTransactionManager : Opened new EntityManager [SessionImpl(45178615<open>)] for JPA transaction
o.s.orm.jpa.JpaTransactionManager : Exposing JPA transaction as JDBC [org.springframework.orm.jpa.vendor.HibernateJpaDialect$HibernateConnectionHandle@20e4fce0]
com.example.aspectj.services.FooService : m2 : called
o.s.orm.jpa.JpaTransactionManager : Initiating transaction commit
o.s.orm.jpa.JpaTransactionManager : Committing JPA transaction on EntityManager [SessionImpl(45178615<open>)]
o.s.orm.jpa.JpaTransactionManager : Closing JPA EntityManager [SessionImpl(45178615<open>)] after transaction
更新:对于开箱即用的 Spring (Boot) 带来的问题,我深表歉意,但现在,您要么必须忍受 AspectJ 核心转储文件 ajdump.*.txt - 交易方面的编织仍然有效,就像我之前说的 - 或者使用你自己的 aop.xml 文件(见上文)。作为包含您自己的应用程序基础包以进行方面编织的替代方法,您还可以采取相反的方向,即排除导致核心转储的类或包。在 Spring Boot 2.5.6 中,您只需添加
<exclude within="org.springframework.boot.jdbc.DataSourceBuilder.OraclePoolDataSourceProperties"/>
在 Spring Boot 2.3.3 中,AspectJ 抱怨这个类:
<exclude within="org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer"/>
我认为这需要在 Spring Boot 或 Spring Core、Spring-TX 或 Spring-Aspects 中修复,无论这些方面位于何处。
更新 2: 我创建了 Spring Core issue #27650 以跟踪 AspectJ 核心转储问题。这不是您最初问题的根本原因,因为事务方面编织无论如何都可以工作,但无论如何都需要在 Spring(并且可能在 AspectJ 中)解决它。