简体   繁体   中英

EnableLoadTimeWeaving Spring Boot Embedded Tomcat

Caching Aspects are not having any effects at runtime with Spring Boot and Embedded tomcat with LoadTimeWeaving enabled,but we are seeing the weaving is happening fine in the logs.

Below is the configuration, the LoadTimeWeaving is enabled along with the mode as AspectJ for Caching

    @Configuration
    @EnableConfigurationProperties
    @EnableSpringConfigured
    @EnableAspectJAutoProxy(proxyTargetClass = true)
    @EnableLoadTimeWeaving
    @EnableTransactionManagement
    @EnableAsync
    @EnableCaching(mode = AdviceMode.ASPECTJ)
    public class AppConfig {
    }

Spring Agent -javaagent:../../../spring-instrument-4.3.3.RELEASE.jar

Logs

[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'

there are whole bunch of discussions around this. The weaving is happening on the RestartClassLoader, not sure is it something to do with the class loader. Have also tried adding the below,

@Bean
      public LoadTimeWeaver loadTimeWeaver() throws Throwable {
          InstrumentationLoadTimeWeaver loadTimeWeaver = new InstrumentationLoadTimeWeaver();
          return loadTimeWeaver;
      }

Please provide your suggestions.

Edit We need Aspectj mode as we are using caching on private methods. I removed the EnableAspectJAutoProxy but still that does not help.

On further analysis on the load time weaving, I noticed the below behaviour. I profile the application and investigated on the class loaders to see the weaving is done correct for the caching annotation to work(classes are trasformed). I noticed for some classes in the classloader ,we have a class with suffix($AjcClosure and those are transformed classes after weaving is done). So, if cachinng annotations is part of those weaved classes, then it works fine. Then I closely looked in to the classes why some classes are weaved correctly and some are not. Then I noticed that if classes are loaded already to the class-loader before weaving happens, then that is where the weaving is not happening.

   @Bean
    public IAService aService(){
       return new AServiceImpl();
    }

In the above case, the class is AServiceImpl is loaded to the class loader only when this instance is needed (after load time weaving and caching works perfectly). But if the same class is being initialised using @Component then it is not getting weaved.

@Service
public class AServiceImpl{
}

I think, in the above case, the class AServiceImpl is loaded to the class loader while the spring container initialises and load time weaving is trying to weave after that).

I verified this behavior again in class loader as well. So, is it an issue if aspectj tries to weave a class that was already loaded. the same problem was raised in the Spring Jira as well in the below link.

https://jira.spring.io/browse/SPR-13786

As mentioned in the above link, if I pass the aspectj weaver as java agent like the below, then all the classes are being weaved correctly. So, is it required to have two agents or do we have any other option for this.

-javaagent:../../../aspectjweaver-1.6.1.jar 
-javaagent:../../../spring-instrument-4.3.3.RELEASE.jar 

Yes, the weaver needs to be active before the weaving targets are loaded by the classloader.

Now, I am an AspectJ geek but not a container geek, I mainly work with Java SE and no containers. Please try to also add

-javaagent:path/to/aspectjweaver.jar

to your command line and see if it helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM