javaspring-bootaopaspectjload-time-weaving

AspectJ + Spring Boot not weaving included classes within aop.xml


I'm having quite a few problems integrating AspectJ with SpringBoot using the LoadTimeWeaving strategy (due Spring AOP doesn't fit my case).

I configured following many guides AspectJ. Here are the dependencies I added on my pom AspectJ related

    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
        <version>${ascpectj.version}</version>
    </dependency>

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-instrument</artifactId>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>${ascpectj.version}</version>
    </dependency>

Here is my aop.xml

<aspectj>


    <weaver options="-showWeaveInfo -debug -Xlintfile:pathToAResource -verbose">
        <include within="foo.*"/>
    </weaver>


    <aspects>
        <aspect name="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect"/>
        <aspect name="org.springframework.scheduling.aspectj.AnnotationAsyncExecutionAspect"/>
        <aspect name="org.springframework.transaction.aspectj.AnnotationTransactionAspect"/>
        <aspect name="org.springframework.cache.aspectj.AnnotationCacheAspect"/>
        <aspect name="it.poste.energy.aspects.TaskAspect"/>
    </aspects>

</aspectj>

And I'm sure it's correctly positioned within the project structure due to the fact that it's actually reading the options in pass in the weaver tag (I know that the xlintoption isn't obviously correct, but I don't think it really matters for now)java

I configured the custom LoadTimeWeaver on a basic config class as so:

@Configuration
@EnableLoadTimeWeaving(aspectjWeaving = AspectJWeaving.ENABLED)
public class CustomLoadTimeWeaverConfig implements LoadTimeWeavingConfigurer {

    @Override
    @NonNull
    public LoadTimeWeaver getLoadTimeWeaver() {
        return new TomcatLoadTimeWeaver();
    }

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

}

I then launch the spring app passing these 2 vm arguments as for java agents -javaagent:C:\Users\foo-user.m2\repository\org\aspectj\aspectjweaver\1.9.6\aspectjweaver-1.9.6.jar -javaagent:C:\Users\foo-user.m2\repository\org\springframework\spring-instrument\5.2.10.RELEASE\spring-instrument-5.2.10.RELEASE.jar

(I tried removing spring-instruments as somewhere suggested and EnableLoadTimeWeaving annotation, but nothing changed)

The app starts fine but it does not weave a single class of the included packages within aop.xml. This is an example of the debug logs of the weaver

    [URLClassLoader@1efee8e7] debug not weaving 'foo.energy.domain.client.crmu.Foo1'
    [URLClassLoader@1efee8e7] debug not weaving 'foo.energy.domain.client.crmu.Foo2'
    [URLClassLoader@1efee8e7] debug not weaving 'foo.energy.domain.client.Foo3'
    [URLClassLoader@1efee8e7] debug not weaving 'fooo.energy.domain.client.Foo4'

One thing that bugs me is the fact it registers all aspects correctly as so:

[InspectionClassLoader@3db65c0d] info AspectJ Weaver Version 1.9.6 built on Tuesday Jul 21, 2020 at 13:30:08 PDT
[InspectionClassLoader@3db65c0d] info register classloader org.springframework.data.jpa.repository.config.InspectionClassLoader@3db65c0d
[InspectionClassLoader@3db65c0d] info using configuration /C:/Work/Workspaces/foo-project/target/classes/META-INF/aop.xml
[InspectionClassLoader@3db65c0d] info using configuration file:/C:/Users/foo-user/.m2/repository/org/springframework/spring-aspects/5.2.10.RELEASE/spring-aspects-5.2.10.RELEASE.jar!/META-INF/aop.xml
[InspectionClassLoader@3db65c0d] warning Cannot access resource for -Xlintfile:pathToAResource
[InspectionClassLoader@3db65c0d] info register aspect org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect
[InspectionClassLoader@3db65c0d] info register aspect org.springframework.scheduling.aspectj.AnnotationAsyncExecutionAspect
[InspectionClassLoader@3db65c0d] info register aspect org.springframework.transaction.aspectj.AnnotationTransactionAspect
[InspectionClassLoader@3db65c0d] info register aspect org.springframework.cache.aspectj.AnnotationCacheAspect
[InspectionClassLoader@3db65c0d] info register aspect foo.energy.aspects.TaskAspect
[InspectionClassLoader@3db65c0d] info register aspect org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect
[InspectionClassLoader@3db65c0d] info register aspect org.springframework.scheduling.aspectj.AnnotationAsyncExecutionAspect
[InspectionClassLoader@3db65c0d] info register aspect org.springframework.transaction.aspectj.AnnotationTransactionAspect
[InspectionClassLoader@3db65c0d] info register aspect org.springframework.transaction.aspectj.JtaAnnotationTransactionAspect
[InspectionClassLoader@3db65c0d] info register aspect org.springframework.cache.aspectj.AnnotationCacheAspect
[InspectionClassLoader@3db65c0d] info register aspect org.springframework.cache.aspectj.JCacheCacheAspect
[InspectionClassLoader@3db65c0d] info deactivating aspect 'org.springframework.cache.aspectj.JCacheCacheAspect' as it requires type 'org.springframework.cache.jcache.interceptor.JCacheAspectSupport' which cannot be found on the classpath
[InspectionClassLoader@3db65c0d] info deactivating aspect 'org.springframework.cache.aspectj.JCacheCacheAspect' as it requires type 'javax.cache.annotation.CacheResult' which cannot be found on the classpath

Problem is that these last line of logs (the registering of the aspects) get called like 3/4 times and I don't know whether it's abnormal or what

Am I missing something here?

SN: I'm using Spring Boot v2.3.5.RELEASE, Spring v5.2.10.RELEASE and tomcat 9.0.39 and 1.9.6 for both aspectjrt and aspectjweaver


Solution

  • Please note that foo.* only matches classes directly in the foo package, not those in subpackages. For that you need foo..*. Therefore, you ought to replace

    <include within="foo.*"/>
    

    by

    <include within="foo..*"/>
    

    I wonder why so many guides use com.* to weave also subpackages.

    I call this phenomenon "copy & paste programming". Some lazy people might want to attract other people to their respective blogs, but not do their own research or programming, simply reproducing existing stuff. It might all have started with a simple typo somewhere, but then it was copied and copied again.