Spring's proxy-based AOP framework is well suited for handling many generic middleware and application-specific problems. However, there are times when a more powerful AOP solution is required: for example, if we need to add additional fields to a class, or advise fine-grained objects that aren't created by the Spring IoC container.
We recommend the use of AspectJ in such cases. Accordingly, as of version 1.1, Spring provides a powerful integration with AspectJ.
The most important part of the Spring/AspectJ integration allows Spring to configure AspectJ aspects using Dependency Injection. This brings similar benefits to aspects as to objects. For example:
There is no need for aspects to use ad hoc configuration mechanisms; they can be configured in the same, consistent, approach used for the entire application.
Aspects can depend on application objects. For example, a security aspect can depend on a security manager, as we'll see in an example shortly.
It's possible to obtain a reference to an aspect through the relevant Spring context. This can allow for dynamic reconfiguration of the aspect.
AspectJ aspects can expose JavaBean properties for Setter Injection, and even implement Spring lifecycle interfaces such as BeanFactoryAware.
Note that AspectJ aspects cannot use Constructor Injection or Method Injection. This limitation is due to the fact that aspects do not have constructors that can be invoked like constructors of objects.In most cases, AspectJ aspects are singletons, with one instance per class loader. This single instance is responsible for advising multiple object instances.
A Spring IoC container cannot instantiate an aspect, as aspects don't have callable constructors. But it can obtain a reference to an aspect using the static aspectOf() method that AspectJ defines for all aspects, and it can inject dependencies into that aspect.
Consider a security aspect, which depends on a security manager. This aspects applies to all changes in the value of the balance instance variable in the Account class. (We couldn't do this in the same way using Spring AOP.)
The AspectJ code for the aspect (one of the Spring/AspectJ samples), is shown below. Note that the dependency on the SecurityManager interface is expressed in a JavaBean property:
public aspect BalanceChangeSecurityAspect { private SecurityManager securityManager; public void setSecurityManager(SecurityManager securityManager) { this.securityManager = securityManager; } private pointcut balanceChanged() : set(int Account.balance); before() : balanceChanged() { this.securityManager.checkAuthorizedToModify(); } }
We configure this aspect in the same way as an ordinary class. Note that the way in which we set the property reference is identical. Note that we must use the factory-method attribute to specify that we want the aspect "created" using the aspectOf() static method. In fact, this is locating, rather than, creating, the aspect, but the Spring container doesn't care:
<bean id="securityAspect" class="org.springframework.samples.aspectj.bank.BalanceChangeSecurityAspect" factory-method="aspectOf" > <property name="securityManager" ref="securityManager"/> </bean>
We don't need to do anything in Spring configuration to target this aspect. It contains the pointcut information in AspectJ code that controls where it applies. Thus it can apply even to objects not managed by the Spring IoC container.
In a future release of Spring, we plan to provide the ability for AspectJ pointcut expressions to be used in Spring XML or other bean definition files, to target Spring advice. This will allow some of the power of the AspectJ pointcut model to be applied to Spring's proxy-based AOP framework. This will work in pure Java, and will not require the AspectJ compiler. Only the subset of AspectJ pointcuts relating to method invocation will be usable.
This feature replaces our previous plan to create a pointcut expression language for Spring.
In a future release of Spring, we will package some Spring services, such as the declarative transaction management service, as AspectJ aspects. This will enable them to be used by AspectJ users without dependence on the Spring AOP framework--potentially, even without dependence on the Spring IoC container.
This feature is probably of more interest to AspectJ users than Spring users.