【问题标题】:EnableLoadTimeWeaving Spring Boot Embedded TomcatEnableLoadTimeWeaving Spring Boot 嵌入式 Tomcat
【发布时间】: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


【解决方案1】:

是的,编织器需要在类加载器加载编织目标之前处于活动状态。

现在,我是 AspectJ 极客,但不是容器极客,我主要使用 Java SE,没有容器。请尝试同时添加

-javaagent:path/to/aspectjweaver.jar

到你的命令行看看它是否有帮助。

【讨论】:

  • 谢谢@kriegaex。正如我提到的,添加 aspectjweaver-1.6.1.jar 作为 java 代理解决了这个问题。我认为这是 Spring Boot 中的唯一选择,因为当我们在 xml 中进行配置时,我没有遇到这个问题。再次感谢
  • 如果您想进一步调查此问题,我found something 为您服务,也许它会有所帮助。 :-)
猜你喜欢
  • 1970-01-01
  • 2017-03-12
  • 2018-06-27
  • 1970-01-01
  • 1970-01-01
  • 2014-09-19
  • 2015-03-23
  • 2016-08-19
  • 2016-12-28
相关资源
最近更新 更多