3

Maybe some people here know me. Usually I am the guy answering AspectJ questions. I consider myself kind of an expert there. In many cases I also answer Spring AOP questions even though I am not a Spring user.

There are two things, though, which always remained mysterious to me:

  1. Many sources here on SO and elsewhere on the web claim that it is easy to combine Spring AOP with AspectJ, more precisely with load-time weaving (LTW). As long as AspectJ is applied via compile-time weaving (CTW) I have no objections because one (AspectJ) was already applied before the Spring application was even started, so there are no issues in this case. But as soon as I am trying to configure Spring to use Spring AOP and at the same time start the application with -javaagent:/path/to/aspectjweaver.jar on the Java command line I can only get load-time weaving (LTW) working and no longer Spring AOP, no matter what combinations of @EnableAspectJAutoProxy and @EnableLoadTimeWeaving I have tried.

  2. As a side show, I also wonder why AspectJ LTW never works as advertised by the Spring manual by only using -javaagent:/path/to/spring-instrument.jar or even by not applying any agent. The manual says that Spring can detect aop.xml and then activate LTW automatically on the fly. This never works for me. To be precise, with the spring-instrument agent Spring does detect my aspects and register them, but only after target classes classes to be woven by AspectJ and used directly in my application's main class were already loaded. I.e. the AspectJ weaver gets initialised too late.

Who can enlighten me here and tell me how to set this up correctly? This question is related to my answer here, so you can conveniently clone the sample GitHub project mentioned there, switch to the aspectj-ltw branch and take it from there in order to configure the application so as to only use TaskAspects via AspectJ LTW (because it intercepts other aspects, which is impossible in Spring AOP) and the other aspects via Spring AOP. I really want to see if and how this can be combined.

kriegaex
  • 63,017
  • 15
  • 111
  • 202
  • I've never done it by myself, but I know that there is @EnableLoadTimeWeaving annotation that can be used for this purpose. Found the example here. https://www.concretepage.com/spring/enableloadtimeweaving-spring-example. Hope it helps somehow :) – Mark Bramnik Sep 12 '19 at 05:25
  • It would be nice to read my question and the linked resources first before answering. I know how to activate LTW, I even mentioned `@EnableLoadTimeWeaving` here in this question. The question is about how to **combine** Spring AOP aspects with AspectJ aspects, i.e. use both at the same time. The Spring manual claims it is possible but does not comprehensively explain how. – kriegaex Sep 12 '19 at 06:50
  • I wasn't even aware that spring had an option to auto-enable LTW like that. I've always used the agent definition manually. But to be honest, once I've decided to add full AJ into a Spring project, I don't find the value of using the limited support by SpringAOP and stick with AJ altogether. – Eric B. Sep 19 '19 at 11:24
  • I am just curious, that's all. The documentation and other sources say you can combine it, so I like to know how. It can actually make sense to use Spring's infrastructure with component configuration, dependency injection etc. if you work in that environment anyway and just add extra stuff where needed. I am beginning to suspect that nobody really knows how to do it or has tried in the last few years, which would explain the unavailability of examples. But I have not given up just yet. – kriegaex Sep 19 '19 at 12:04
  • I am really wondering what the downvote was for. What is wrong or bad about this question? – kriegaex Dec 01 '19 at 08:20
  • I upvoted it again. I am also curios to know how this works. I am the lead developer of Codekvast, which uses LTW. In the Codekvast server I have some Spring aspects that works fine until I try to dogfood and attach aspectjweaver.jar (via codekvast-agent.jar). It starts working again when I add to aop.xml – Olle Hallin Dec 19 '19 at 16:47
  • Olle, what is it you are excluding in aop.xml? You can use `exclude within` both in the `` and the `` sections. The former affects the aspects being used by LTW, the latter the target classes to be woven. Please elaborate a bit, then I can try for myself. And what does "starts working again" mean? You can use Spring AOP + LTW aspects at the same time? Or does your exclusion effectively disable LTW altogether in favour of Spring AOP? – kriegaex Dec 22 '19 at 03:33
  • @OlleHallin, can you please answer my question? Maybe we can solve the problem together if I know where to start. I would like to take it from your current configuration and see if I can find out more. – kriegaex Jan 17 '20 at 05:26

1 Answers1

0

The problem seems to be the configuration scanning process of Spring Boot, so not the Spring Framework itself. It evaluates the conditions from the various autoconfiguration classes and ends up loading JobProcessImpl, because is annotated with @Component, before the LoadTimeWeaver gets enabled.

The way I found to make it work is to remove the @Component annotation from the class and create the bean by hand in ApplicationConfig:

@Bean
public JobProcess jobProcess() {
    return new JobProcessImpl();
}

2019-09-20 12:10:26.985  INFO 1 --- [           main] AspectJ Weaver                           : [AspectJ] register aspect com.spring.aspect.dynamicflow.aspect.TaskAspects
2019-09-20 12:10:27.155  INFO 1 --- [           main] AspectJ Weaver                           : [AspectJ] register aspect com.spring.aspect.dynamicflow.activity.AnnotationTask
2019-09-20 12:10:27.166  INFO 1 --- [           main] AspectJ Weaver                           : [AspectJ] register aspect com.spring.aspect.dynamicflow.activity.ReviewTask
2019-09-20 12:10:27.257  INFO 1 --- [           main] AspectJ Weaver                           : [AspectJ] Join point 'method-execution(java.lang.Object com.spring.aspect.dynamicflow.process.JobProcessImpl.process(com.spring.aspect.dynamicflow.entity.JobContext))' in Type 'com.spring.aspect.dynamicflow.process.JobProcessImpl' (JobProcessImpl.java:16) advised by around advice from 'com.spring.aspect.dynamicflow.activity.ReviewTask' (Task.java)
2019-09-20 12:10:27.263  INFO 1 --- [           main] AspectJ Weaver                           : [AspectJ] Join point 'method-execution(java.lang.Object com.spring.aspect.dynamicflow.process.JobProcessImpl.process(com.spring.aspect.dynamicflow.entity.JobContext))' in Type 'com.spring.aspect.dynamicflow.process.JobProcessImpl' (JobProcessImpl.java:16) advised by around advice from 'com.spring.aspect.dynamicflow.activity.AnnotationTask' (Task.java)
2019-09-20 12:10:27.378  INFO 1 --- [           main] AspectJ Weaver                           : [AspectJ] Join point 'method-execution(java.lang.Object com.spring.aspect.dynamicflow.activity.AnnotationTask.task(org.aspectj.lang.ProceedingJoinPoint, com.spring.aspect.dynamicflow.entity.JobContext))' in Type 'com.spring.aspect.dynamicflow.activity.AnnotationTask' (AnnotationTask.java:16) advised by around advice from 'com.spring.aspect.dynamicflow.aspect.TaskAspects' (TaskAspects.java)
2019-09-20 12:10:27.390  INFO 1 --- [           main] AspectJ Weaver                           : [AspectJ] Join point 'method-execution(java.lang.Object com.spring.aspect.dynamicflow.activity.ReviewTask.task(org.aspectj.lang.ProceedingJoinPoint, com.spring.aspect.dynamicflow.entity.JobContext))' in Type 'com.spring.aspect.dynamicflow.activity.ReviewTask' (ReviewTask.java:16) advised by around advice from 'com.spring.aspect.dynamicflow.aspect.TaskAspects' (TaskAspects.java)
2019-09-20 12:10:27.412  INFO 1 --- [           main] c.s.a.d.process.JobProcessImpl           : JobProcessImpl class was loaded
2019-09-20 12:10:27.500  WARN 1 --- [           main] AspectJ Weaver                           : [AspectJ] javax.* types are not being woven because the weaver option '-Xset:weaveJavaxPackages=true' has not been specified
2019-09-20 12:10:27.871  INFO 1 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2019-09-20 12:10:28.368  INFO 1 --- [           main] c.spring.aspect.dynamicflow.Application  : jobProcess = com.spring.aspect.dynamicflow.process.JobProcessImpl@4627a09d
2019-09-20 12:10:28.379  INFO 1 --- [           main] c.s.a.dynamicflow.aspect.TaskAspects     : Handling the task aspects.
2019-09-20 12:10:28.382  INFO 1 --- [           main] c.s.a.dynamicflow.aspect.TaskAspects     :   execution(Object com.spring.aspect.dynamicflow.activity.AnnotationTask.task(ProceedingJoinPoint, JobContext))
2019-09-20 12:10:28.382  INFO 1 --- [           main] c.s.a.d.activity.AnnotationTask          : AnnotationTask's task
2019-09-20 12:10:28.382  INFO 1 --- [           main] c.s.a.d.activity.AnnotationTask          :   Setting that the annotation is done.
2019-09-20 12:10:28.395  INFO 1 --- [           main] c.s.a.dynamicflow.aspect.TaskAspects     : Handling the task aspects.
2019-09-20 12:10:28.395  INFO 1 --- [           main] c.s.a.dynamicflow.aspect.TaskAspects     :   execution(Object com.spring.aspect.dynamicflow.activity.ReviewTask.task(ProceedingJoinPoint, JobContext))
2019-09-20 12:10:28.395  INFO 1 --- [           main] c.s.a.dynamicflow.activity.ReviewTask    : ReviewTask's task
2019-09-20 12:10:28.395  INFO 1 --- [           main] c.s.a.dynamicflow.activity.ReviewTask    :   Setting that the review is done.
2019-09-20 12:10:28.395  INFO 1 --- [           main] c.s.a.d.process.JobProcessImpl           : Processing the job with jobid 11
kriegaex
  • 63,017
  • 15
  • 111
  • 202
Shadow
  • 222
  • 1
  • 3
  • 13
  • This makes a lot of sense based on how I remember spring processing annotations and bean discovery. However I would also see this as a significant bug in Spring Boot; it essentially disables LTW by AJ in that case for the vast majority of code/libs that depend upon annotation scanning. I wonder if anyone has opened a bug on the Boot project to indicate as much – Eric B. Sep 20 '19 at 13:26
  • This is not working for me. How exactly did you configure Spring (via `ApplicationConfig` class), AspectJ (via _aop.xml_) and how did you run the application (`-javaagent` parameters) in order to **mix** Spring AOP and AspectJ? Remember, only `TaskAspects` is meant to be run via AspectJ, the other aspects via Spring AOP. For me as soon as AspectJ is detected by Spring Boot, proxy-based Spring AOP is completely deactivated. – kriegaex Sep 22 '19 at 04:23
  • I can confirm that your workaround solves problem 2 (the side show), i.e. AspectJ LTW is applied correctly for all 3 aspects with only `-javaagent:/my/path/spring-instrument.jar` in combination with `@EnableLoadTimeWeaving(aspectjWeaving = ENABLED)` (annotation parameter is mandatory or else it won't work). – kriegaex Sep 22 '19 at 04:40