mco98215
mco98215

Reputation: 23

Spring Boot - Compile time weaving and Spring AOP/run time weaving (proxies) in same project

What does Spring Boot do in the event that there is code to use both Spring AOP with run time weaving/use of proxies and compile time weaving in the same project. For example, say you have an aspect that looks like this:

@Aspect
@Component
public class TestAspect {
  // ...
}

where the existence of @Component would imply that we are using Spring AOP and proxies, and you have this in your pom.xml

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>aspectj-maven-plugin</artifactId>
  <version>1.11</version>
  <executions>
    <execution>
      <goals>
        <goal>compile</goal>       <!-- use this goal to weave all your main classes -->
        <goal>test-compile</goal>  <!-- use this goal to weave all your test classes -->
      </goals>
    </execution>
  </executions>
</plugin>

which would imply we are using compile time weaving.

Which one takes precedence? Is compile time weaving used, or proxies?

Upvotes: 2

Views: 2772

Answers (2)

jiyolla
jiyolla

Reputation: 27

I've recently ran into a situation where Spring AOP seems to be disabled when AspectJ (P)CTW kicks in, but not application wise but only class wise. After some debugging in spring code, I figured out that the above observation is conditionally true

In our case, we registered the ajc aspects as beans by using aspectOf(), so that the aspects can also have spring bean dependency injected. This makes the aspects visible to spring. (But we forgot to configure to weave our code with this aspect, so our aspect was actually working under spring proxy aop not ajc weaving)

Spring AOP register all the @Aspect beans as Advisor and look it up when creating beans when creating proxy beans. (Proxy beans, thus upon creation, have determined eligible aspects)

When testing whether an advisor is eligible for a target bean, AspectJExpressionPointcut.matches(Class<?> targetClass) is called down the call stack(possibly for InstantiationModelAwarePointcutAdvisorImpl ish only). And the aspectOf() created aspects' relevant advisor fails the test at this line (this.aspectCompiledByAjc && compiledByAjc(targetClass)) the former is true since we used aspectOf(), the latter actually checks the class definition for signs of ajc compilation with some adhoc logics.

To conclude, Advisors with AspectJExpressionPointcut type ClassFilter cannot be applied to already ajc weaved class (the advisor for @Transactional uses TransactionAttributeSourcePointcut and doesn't check if ajc compilation happened, so spring proxy based @Transactional works even on ajc compiled classes)

Upvotes: 0

kriegaex
kriegaex

Reputation: 67457

Hm, why didn't you just try? Wouldn't that have been faster than asking? OK, here are my thoughts:

  • AspectJ is completely independent from Spring AOP or Spring in general. You can use it without Spring or from within a Spring application, usually via load-time weaving (LTW). The Spring manual explains how to configure that.
  • If you use LTW, Spring is aware of it, either because you configure it explicitly via Spring options or simply because Spring detects the active weaving agent somehow. Either way, as soon as LTW is active, Spring deactivates its own Spring AOP.
  • Concerning compile-time weaving (CTW), Spring does not know about it, because it happens during build time, before Spring is even started. Depending on what kind of AspectJ features you use, the AspectJ-enhanced classes might look no different from regular Java classes, e.g. for simple ITD field or method definitions. In most cases however, the modifications are such that you need the AspectJ runtime library aspectjrt.jar on the classpath. If that is the case, the application should run normally, with or without Spring.
  • In case of Spring, I do not expect it to notice anything about you having used CTW before in the first place. Consequently, it will not deactivate Spring AOP. You should be able to use both in combination with each other. Just make sure not to declare your native aspect as a Spring component, otherwise Spring AOP would try to re-apply it. The results would be unpredictable. But the normal Spring AOP aspect components should just work normally. Of course, you also need to make sure that AspectJ Maven does not accidentally compile and weave your Spring AOP aspects as native aspects. You can achieve that by placing your AspectJ aspects into another module, creating an aspect library, and then referring to it in AspectJ Maven via <aspectLibraries> configuration.

Bottom line: You cannot mix Spring AOP and AspectJ LTW, but you should be able to use Spring AOP + AspectJ CTW. You just should have good reasons to do so and understand what you are doing.

Upvotes: 3

Related Questions