Home > Mobile >  NoSuchMethodException aspectOf in aspectj load time weaving in spring boot
NoSuchMethodException aspectOf in aspectj load time weaving in spring boot

Time:01-05

I used spring ltw documentation to configure load time weaving in my spring boot app. below dependencies are in pom file:

    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
    </dependency>
     <dependency>
         <groupId>org.springframework</groupId>
         <artifactId>spring-instrument</artifactId>
     </dependency>

aop.xml is configured as below and have placed in resources/META-INF

<!DOCTYPE aspectj PUBLIC
    "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
    <weaver options="-verbose -showWeaveInfo">
        <include within="com.tosan.http.server.starter.logger.ServiceLogger"/>
    </weaver>
<aspects>
    <aspect name="com.sample.demo.aspect.TestAspect"/>
</aspects>

I also enabled aspectj load time weaving with spring boot configuration:

@Configuration
@EnableLoadTimeWeaving()
public class DemoConfig {

   @Bean
   public TestAspect testAspect() {
       TestAspect testAspect = Aspects.aspectOf(TestAspect.class);
       return testAspect;
   }
}

on running program javaagent is passed as below:

-javaagent:\aspectjweaver.jar 
-javaagent:\spring-instrument-5.3.23.jar

app give noSuchMethodException on start up:

[AppClassLoader@368239c8] weaveinfo Join point 'method-execution(java.lang.Object 
com.tosan.http.server.starter.logger.ServiceLogger.log(org.aspectj.lang.ProceedingJoinPoint))' 
in Type 'com.tosan.http.server.starter.logger.ServiceLogger' (ServiceLogger.java:17) advised 
by around advice from 'com.sample.demo.aspect.TestAspect' (TestAspect.java)
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 
'testAspect' defined in class path resource [com/sample/demo/DemoConfig.class]: Bean 
instantiation via factory method failed; nested exception is 
org.springframework.beans.BeanInstantiationException: Failed to instantiate 
[com.sample.demo.aspect.TestAspect]: Factory method 'testAspect' threw exception; nested 
exception is org.aspectj.lang.NoAspectBoundException: Exception while initializing 
com.sample.demo.aspect.TestAspect: java.lang.NoSuchMethodException: 
com.sample.demo.aspect.TestAspect.aspectOf()
at 

I should also mention that when i add ajc compiler(with com.nickwongdev plugin) app starts fine but the aspect execute twice. also tried ajc compiler and only aspectjWeaver as agent and it gives error for not finding spring specific weaver classes and tried ajc compiler with only spring weaver agent that doesn't give any error but aspect is not executed. any help would be appreciated.

Complete code sample on github.

upadate: problem solved by adding the path of aspect in weaver:

<include within="com.sample.demo.aspect.TestAspect"/>

I also noticed by removing @EnableLoadTimeWeaving() nothing happen and ltw is done in presence or absence of this annotation. This annotation only force the presence of spring weaver as javaagent in runtime.

correct code is updated on github.

CodePudding user response:

Thanks for the GitHub repo. It was easy to fix the problem like this, you did yourself a great favour by preparing it.

Firstly, the pointcut and weaver configuration does not fit the example class name. Please change

@Pointcut("execution(public * com.tosan.http.server.starter.logger.ServiceLogger.log(..))")

to

@Pointcut("execution(* *(..)) && @annotation(com.sample.demo.TestAnnotation)")

because I guess you want to intercept methods with marker annotations.

In aop.xml, remove line

<include within="com.tosan.http.server.starter.logger.ServiceLogger"/>

or replace it by something like

<include within="com.sample.demo..*"/>

Next, get rid of factory method @Bean TestAspect testAspect(). You do not need it. Instead, in order to test the aspect, simply change the main method to:

  public static void main(String[] args) {
    try (ConfigurableApplicationContext appContext = SpringApplication.run(DemoApplication.class, args)) {
      appContext.getBean(TestController.class).test();
    }
  }

If now you run your application like before, the console log says:

(...)
[AppClassLoader@4d7e1886] info register aspect com.sample.demo.aspect.TestAspect
(...)
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.7.5)

(...)
[AppClassLoader@4d7e1886] weaveinfo Join point 'method-execution(void com.sample.demo.controller.TestController.test())' in Type 'com.sample.demo.controller.TestController' (TestController.java:17) advised by around advice from 'com.sample.demo.aspect.TestAspect' (TestAspect.java)
(...)
2023-01-04 20:25:47.599  INFO 20208 --- [           main] c.sample.demo.controller.TestController  : {
  "service" : "test",
  "request" : { }
}
aspect invocation
test
2023-01-04 20:25:47.611  INFO 20208 --- [           main] c.sample.demo.controller.TestController  : {
  "service" : "test",
  "duration" : "0.026s",
  "response" : { }
}
(...)

Please note aspect invocation printed by the aspect.

  • Related