【发布时间】:2018-05-28 14:09:02
【问题描述】:
在启用了 LoadTimeWeaving 的 Spring Boot 和 Embedded tomcat 的运行时,缓存方面没有任何影响,但我们在日志中看到编织运行良好。
下面是配置,LoadTimeWeaving开启,模式为AspectJ for Caching
@Configuration
@EnableConfigurationProperties
@EnableSpringConfigured
@EnableAspectJAutoProxy(proxyTargetClass = true)
@EnableLoadTimeWeaving
@EnableTransactionManagement
@EnableAsync
@EnableCaching(mode = AdviceMode.ASPECTJ)
public class AppConfig {
}
弹簧代理 -javaagent:../../../spring-instrument-4.3.3.RELEASE.jar
日志
[RestartClassLoader@2aaae670] debug weaving 'uk.co.loyalty.iss.newpro.reporting.domain.refdata.gateway.RestReferenceDataGateway'
[RestartClassLoader@2aaae670] weaveinfo Join point 'method-execution(java.util.List uk.co.loyalty.iss.newpro.reporting.domain.refdata.gateway.RestReferenceDataGateway.getHierarchyLevelDefns())' in Type 'uk.co.loyalty.iss.newpro.reporting.domain.refdata.gateway.RestReferenceDataGateway' (RestReferenceDataGateway.java:118) advised by around advice from 'org.springframework.cache.aspectj.AnnotationCacheAspect' (AbstractCacheAspect.aj:64)
[RestartClassLoader@2aaae670] weaveinfo Join point 'method-execution(java.util.Map uk.co.loyalty.iss.newpro.reporting.domain.refdata.gateway.RestReferenceDataGateway.getHierarchyLevelDefinitionMap())' in Type 'uk.co.loyalty.iss.newpro.reporting.domain.refdata.gateway.RestReferenceDataGateway' (RestReferenceDataGateway.java:129) advised by around advice from '**org.springframework.cache.aspectj.AnnotationCacheAspect**' (AbstractCacheAspect.aj:64)
[RestartClassLoader@2aaae670] **debug generating class** 'uk.co.loyalty.iss.newpro.reporting.domain.refdata.gateway.RestReferenceDataGateway$AjcClosure1'
[RestartClassLoader@2aaae670] debug generating class 'uk.co.loyalty.iss.newpro.reporting.domain.refdata.gateway.RestReferenceDataGateway$AjcClosure3'
围绕这个有很多讨论。编织发生在 RestartClassLoader 上,不确定它是否与类加载器有关。也尝试添加以下内容,
@Bean
public LoadTimeWeaver loadTimeWeaver() throws Throwable {
InstrumentationLoadTimeWeaver loadTimeWeaver = new InstrumentationLoadTimeWeaver();
return loadTimeWeaver;
}
请提供您的建议。
编辑 我们需要 Aspectj 模式,因为我们在私有方法上使用缓存。我删除了 EnableAspectJAutoProxy 但仍然没有帮助。
在进一步分析加载时间编织时,我注意到以下行为。 我分析了应用程序并在类加载器上进行了调查,以查看编织是否正确以使缓存注释正常工作(类被转换)。我注意到类加载器中的某些类,我们有一个带有后缀的类($AjcClosure,这些是编织完成后的转换类)。因此,如果缓存注释是这些编织类的一部分,那么它可以正常工作。 然后我仔细研究了为什么有些类被正确编织而有些则不正确的类。然后我注意到,如果在编织发生之前已经将类加载到类加载器中,那么这就是编织没有发生的地方。
@Bean
public IAService aService(){
return new AServiceImpl();
}
在上述情况下,类是 AServiceImpl 仅在需要此实例时才加载到类加载器(加载时编织和缓存工作完美之后)。 但是如果使用@Component 初始化同一个类,那么它就不会被编织。
@Service
public class AServiceImpl{
}
我认为,在上述情况下,类 AServiceImpl 被加载到类加载器中,而 spring 容器初始化并且加载时间编织试图在此之后编织)。
我也在类加载器中再次验证了这种行为。那么,如果 aspectj 试图编织一个已经加载的类,这是否是一个问题。 Spring Jira 中也出现了同样的问题,下面的链接中也出现了同样的问题。
https://jira.spring.io/browse/SPR-13786
正如上面链接中提到的,如果我像下面这样将 aspectj 编织器作为 java 代理传递,那么所有类都被正确编织。那么,是否需要有两个代理,或者我们是否有其他选择。
-javaagent:../../../aspectjweaver-1.6.1.jar
-javaagent:../../../spring-instrument-4.3.3.RELEASE.jar
【问题讨论】:
-
你的问题让我很困惑。真的是关于 AspectJ 还是关于基于代理的 Spring AOP?因为您同时配置了
@EnableAspectJAutoProxy(Spring AOP)和@EnableLoadTimeWeaving(AspectJ)。您应该只使用其中之一。为什么你认为你仍然需要完整的 AspectJ?您是否使用了 Spring AOP 中不存在的特性,例如私有方法拦截、Spring AOP 中不支持的切入点类型或类似的?或者,也许您想跟踪目标类发出的内部调用,例如this.myMethod()?后者是您的注释@EnableCaching(mode = AdviceMode.ASPECTJ)建议的内容。 -
感谢@kriegaex。我已经按照类加载器在我的问题中添加详细信息进行了进一步调查。请建议
标签: spring spring-boot aspectj spring-aop load-time-weaving