Could anyone please tell me why the aspect won't fire when using spring boot? I am trying to setup load time weaving with aspectj so that I can have private methods advised.
Here is the link to the barebones project - https://github.com/satb/spring_aop_test_project.git
Run the "App" class with "-javaagent:path/to/spring-instrument-4.1.0.RELEASE.jar" (or some other version of the lib on your computer) and run the curl command
curl -i http://localhost:8080/test-app/motd
The MyAspect class has an advice that should execute when the private method of MyService is called. But in this case, nothing happens.
When the application starts though, I see a message like this:
[AppClassLoader@58644d46] warning javax.* types are not being woven because the weaver option '-Xset:weaveJavaxPackages=true' has not been specified.
I tried following the suggestion from here to get it to work but that didn't help - Using @Autowired with AspectJ and Springboot
Okay, I took a quick look at your GitHub project. The POM is pretty weird, e.g. it does not contain any dependency on spring-instrument. Furthermore, you depend on aspectjweaver 1.8.2, but on aspectjrt 1.5.4. You should really use the same version for both.
Anyway, I experimented with different Java agents on the command line, and it seems that it is not enough to just use AspectJ weaver (result: exception) or just Spring Instrument (result: aspects do not work, just as you described). You need to use both:
java -javaagent:path/to/aspectjweaver-1.8.2.jar -javaagent:path/to/spring-instrument-4.1.0.RELEASE.jar ...
This works for me with your code and yields the following on the console when using Curl according to your description:
[AppClassLoader@58644d46] warning javax.* types are not being woven because the weaver option '-Xset:weaveJavaxPackages=true' has not been specified
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v1.1.6.RELEASE)
2014-09-08 13:09:54.489 INFO 1464 --- [ main] App : Starting App on Xander-PC with PID 1464 (C:\Users\Alexander\Documents\java-src\SO_AJ_SpringBootPrivilegedAspect\target\classes started by Alexander in C:\Users\Alexander\Documents\java-src\SO_AJ_SpringBootPrivilegedAspect)
2014-09-08 13:09:54.513 INFO 1464 --- [ main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@6771beb3: startup date [Mon Sep 08 13:09:54 CEST 2014]; root of context hierarchy
(...)
2014-09-08 13:09:56.257 INFO 1464 --- [ main] o.s.c.w.DefaultContextLoadTimeWeaver : Found Spring's JVM agent for instrumentation
2014-09-08 13:09:56.259 INFO 1464 --- [ main] o.s.c.w.DefaultContextLoadTimeWeaver : Found Spring's JVM agent for instrumentation
Aspect of called
(...)
2014-09-08 13:09:56.779 INFO 1464 --- [ main] App : Started App in 2.531 seconds (JVM running for 3.067)
2014-09-08 13:09:59.115 INFO 1464 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet 'dispatcherServlet'
2014-09-08 13:09:59.115 INFO 1464 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started
2014-09-08 13:09:59.122 INFO 1464 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 7 ms
Aspect of called
Advising getter
Try declaring an InstrumentationLoadTimeWeaver bean instead of explicitly using -javaagent:/path/to/org.springframework.instrument-{version}.jar. As per the documentation
To use it, you must start the virtual machine with the Spring agent, by supplying the following JVM options:
-javaagent:/path/to/org.springframework.instrument-{version}.jar
Note that this requires modification of the VM launch script which may prevent you from using this in application server environments (depending on your operation policies). Additionally, the JDK agent will instrument the entire VM which can prove expensive.
I am hoping doing the way below would be better I guess.
@Bean
public InstrumentationLoadTimeWeaver loadTimeWeaver() throws Throwable {
InstrumentationLoadTimeWeaver loadTimeWeaver = new InstrumentationLoadTimeWeaver();
return loadTimeWeaver;
}
The same can be done in xml configuration.
Found a new library that just solves to dynamically setup spring InstrumentationLoadTimeWeaver to enable support for aspects without having to start the JVM with an explicit java agent
<dependency>
<groupId>de.invesdwin</groupId>
<artifactId>invesdwin-instrument</artifactId>
<version>1.0.2</version>
</dependency>
Spring boot config
@SpringBootApplication
/**
* Make @Configurable work via @EnableLoadTimeWeaving.
* If it does not work, alternatively you can try:
* @ImportResource(locations = "classpath:/META-INF/ctx.spring.weaving.xml")
*/
@EnableLoadTimeWeaving
public class MySpringBootApplication {
public static void main(final String[] args) {
DynamicInstrumentationLoader.waitForInitialized(); //dynamically attach java agent to jvm if not already present
DynamicInstrumentationLoader.initLoadTimeWeavingContext(); //weave all classes before they are loaded as beans
SpringApplication.run(MySpringBootApplication.class, args); //start application, load some classes
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With