Integration with Other AOP Frameworks


Spring AOP provides a good, simple solution to typical crosscutting concerns in J2EE applications. However, if you want to make more adventurous use of AOP — for example, to advise fine-grained objects created using new, to advise domain objects, or to advise fields — or when you absolutely need to minimize the overhead of advice, you may need a more powerful AOP solution.

To address such requirements, Spring integrates well with specialized AOP frameworks.

Goals

It's important to note here that integrating Spring with a more powerful AOP framework benefits the AOP framework as much as Spring.

The use of Dependency Injection brings as many benefits to aspects as it does to objects. Aspects can also depend on a range of objects — infrastructure objects as well as application objects — and, as with objects, it's better for those dependencies to be resolved through pushing than pulling. It's also often useful to be able to pass in simple parameterization to objects. For example, AspectJ doesn't let us add or remove advice at runtime; however, we can enable or disable an aspect using Dependency Injection, using configuration properties or interaction with injected collaborators.

AspectJ Integration

AspectJ is an extension to the Java language that elevates aspects and pointcuts to language-level constructs. AspectJ is mature and powerful. It is more difficult to use effectively for simple AOP tasks than Spring AOP. However, its capabilities far exceed those of Spring or other proxy-based frameworks where we need to make more advanced use of AOP.

This is not the place for a full discussion of AspectJ's capabilities. Please refer to the "References" section near the end of this chapter to help find more material on AspectJ. For the moment, let's note some key points:

  • AspectJ expresses pointcuts in source code, not XML or another metadata format. A common idiom uses an abstract base aspect to define the advice, leaving subclasses to implement abstract pointcuts.

  • Although compile-time weaving is not intrinsic to the AspectJ model, it's normal to use the AspectJ compiler rather than javac to compile AspectJ code. This changes the build process. There may also be performance implications if using AspectJ IDE integration. (However, the Eclipse integration, AJDT, offers an impressive feature set for working with aspects.)

  • Advice is compiled into classes. It's not added by runtime weaving as with Spring. Thus it's impossible to add or remove advice.

  • Unlike Spring, AspectJ implicitly uses singletons. Most advice is scoped per class loader.

  • AspectJ does not use interception as an implementation strategy.

To use AspectJ best, you'll need to think about AOP at a higher, more conceptual level than method interception. While you can get a fair (if incomplete) grasp of the capabilities of Spring AOP by thinking of it as a sophisticated means of targeted method interception, this type of thinking is inappropriate where AspectJ is concerned.

Using Dependency Injection to Configure AspectJ Aspects

Despite the difference of the model, it's possible to integrate AspectJ aspects into a Spring context using Dependency Injection almost as smoothly as Spring AOP classes such as pointcuts and advice.

The approach will vary depending on the scope of the aspect — "aspect association" in AspectJ terminology — but it's based on defining AspectJ aspects as beans in a Spring context.

Singleton Aspects

In the most common case, aspects are singletons that can advise multiple objects. Thus by configuring an aspect instance using Dependency Injection, we can affect the advice applying to many objects.

Let's look at an example. The following AspectJ aspect applies a security check on every change to the value of the balance instance variable in the Account class. Such a field-level check cannot be performed using Spring's own AOP framework, although it would be possible to apply the security check to every method that might result in a change to the value of the field. But the key capability here that cannot easily be replicated using a proxy-based AOP framework is that all Account instances will be advised, regardless of how they are created. We don't need to manage instances of the Account class using Spring AOP to leverage this advice.

The code in the aspect is pure AspectJ, with the only difference from conventional AspectJ usage being the use of Setter Injection to populate the value of the securityManager instance variable before the aspect is used. The pointcut is defined in AspectJ code as usual, meaning that it is checked at compile time:

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 must now configure the aspect using Setter Injection, as though it was any other object:

<bean         factory-method="aspectOf" >   <property name="securityManager">      <ref local="securityManager"/>   </property> </bean>

The magic parameter is the factory-method parameter. It's impossible to instantiate AspectJ aspects using constructors, as we can instantiate classes. So Spring cannot instantiate aspects using a no-arg constructor, in the case of JavaBean conventions, and it's impossible to use Constructor Injection. What we can do is use a feature introduced in Spring 1.1 — partly for AspectJ integration — in which Spring uses a factory method to obtain the object to configure.

Every singleton aspect has a static method called aspectOf(). We specify this factory method in the bean definition we've just seen. We can then configure the aspect using JavaBean properties, as though it was any object.

Configuration using Dependency Injection has important benefits when using AspectJ. Traditionally, it was difficult to configure aspects in a consistent way. Also, it could be difficult to integrate aspects into an application — for example, by giving them access to application objects or services such as the security manager in the example just shown. I, and no doubt others, considered these serious objections to usage of ApsectJ.

Configuring aspects using Dependency Injection gives them access to all the services Spring IoC offers — and taps into a powerful, consistent approach to application configuration.

You may be wondering: what happens if the construction of an aspect advises the creation of another singleton bean in the factory? As by default Spring doesn't guarantee the order in which singleton beans are instantiated, this could pose a problem.

By default, Spring eagerly instantiates singleton beans. It's possible to turn this off, or to control ordering. Thus there are three ways to address this:

  • Use the optional depends-on attribute of beans whose construction may be advised, specifying the names of relevant aspects. This works, but has the disadvantage that advised object configurations need knowledge of the aspects that will affect them. The Spring configuration duplicates some of what is expressed in AspectJ code, and of course the two definitions may be out of synch.

  • Mark beans that may be advised as lazy-init, but ensure that aspects are always eagerly instantiated (the default).

  • Define your aspects in an ancestor factory. This uses the fact that Spring will always instantiate beans in an ancestor factory before descendant factories.

All these approaches work, but the third is probably the best in most cases. It clarifies exactly what's happening, encouraging the collection of aspects in one place. It's also a natural idiom once you begin.

This doesn't apply to our aspect, as balance changes are made only after the aspect is configured.

Note 

What if we had an aspect that added every object that was created to a tracker? In this case, we could write a pointcut to advise the new operator.

More Advanced Usages

This simple example demonstrates the advantages of Spring/AspectJ integration. However, there are a number of subtle issues to consider.

Scoping Issues

When we configured the BalanceChangeAspect, we configured it across the entire class loader, not just this application context. This differs from the norm in Spring. In Spring, nothing is ever per-class loader level. Spring aims to free developers from the use of the singleton design pattern — often an antipattern, used for lookup rather than because the number of instances needs to be limited to one. In AspectJ, most aspects are per class loader.

This means that should multiple Spring IoC containers attempt to configure the same aspect in the same class loader, the results will be undefined. Whichever of the contexts is instantiated last will win and reconfigure the singleton aspect that has already been configured by other contexts. This consideration is particularly important if the aspect holds a reference to the "owning" application context — for example, by implementing the BeanFactoryAware interface.

Thus, if another application context also constructs Account objects, those objects will also be advised by the aspect we configured earlier. This might be desirable, but it might not be. (Consider if the aspect depended on its context, or if there should be a different security policy within each context.)

We have a choice in how to approach this issue:

  • Avoid it in practice. Recognize that advice has global scope, and accept the implications.

  • Use the class loader scope to separate differently advised objects. The downside of this approach is that it complicates build and deployment, and may reduce portability between application servers.

Essentially, we're dealing with the downside of AOP based on class weaving, rather than proxying as in Spring's own framework, and the flip side of the added power. This is one reason that we recommend using Spring's own AOP framework if there's a choice of AOP technologies to meet a particular requirement.

"Singleton" aspects probably account for 90 percent of typical usage of AspectJ. As we've seen, singleton aspects are easy to configure using Spring 1.1 and above.

Understanding Aspect Association

AspectJ provides other aspect scopes — called aspect association types — besides singleton aspects. The complete range of options is:

  • Per virtual machine: Singleton aspect. The default, as discussed above.

  • Per object: An aspect instance is created for each advised object when the specified pointcut first matches at runtime. The aspect survives thereafter.

  • Per control flow: The aspect scope is that of the control flow associated with the association specification. The aspect instance is released at the end of the control flow.

Aspects using association types other than per JVM need to be defined with an association specifier, like this:

 aspect MyAspect perthis(pointcutName()) 

Presently there is no out-of-the-box support for configuring such aspects using Spring. However, it is possible, and this may have changed by the time you read this. The Spring and AspectJ communities are working together to improve integration between the two products. If you are interested in this advanced feature, you may want to check the AspectJ section of the Spring Reference Manual for an update.

Choosing Between Spring AOP and AspectJ

Spring AOP integrates well with AspectJ. There is no conflict between the two approaches. We can use both in the same application.

Nevertheless, sometimes we will have the choice between using Spring AOP and AspectJ for the same ends. How do we then choose between the two approaches?

Using AspectJ brings much more of a paradigm shift than using Spring AOP. Not only is using such a capable AOP solution likely to change how you think about code, there are some clashes between AspectJ and Spring concepts that you should be aware of.

AspectJ has some significant potential advantages:

  • Negligible performance overhead. AspectJ imposes no overhead itself; it should offer performance as good as writing the crosscutting code manually. Nevertheless, it's important to recognize that the interception overhead is insignificant in recommended use of Spring AOP.

  • It is particularly good for introduction. Introduction in a proxy-based framework such as Spring requires usually maintaining a distinct object instance for each introduction, as well as the target, because the introduction is holding part of the state. With AspectJ, the additional fields and method implementations can be added to the byte code of the advised class.

  • It's well suited to advising fine-grained objects. Not only is overhead low, but objects can be constructed using new, unlike with a proxy-based approach. The fact that objects don't need to be managed by the Spring IoC container to be advised is probably the biggest advantage of a"full-blown" AOP framework.

  • Non-public methods can be advised.

  • Fields can be advised.

  • AspectJ is well suited to type-safe advice. If your advice needs to work directly with the types of objects it is advising, AspectJ is likely to prove more economical to code and less error-prone than AOP Alliance-style code. (Such aspects tend to be application-specific. Middleware aspects, such as transaction management aspects, do not normally benefit from type safety. In fact, they are often easier to code using AOP Alliance method interception than AspectJ pointcuts and advice.)

However, there are some costs and complexities associated with AspectJ that mean the decision is not straightforward:

  • Using AspectJ complicates the build process. It will have a noticeable effect on build time.

  • AspectJ syntax is not particularly intuitive. If you or your project team are already skilled with AspectJ, this is not a concern. Once the learning curve is surmounted, AspectJ is uniquely powerful.

  • You will require tool support, and this may constrain your choice of IDE. AspectJ tools are still not perfect, although they are improving rapidly.

  • AspectJ does not presently allow externalizing pointcuts into configuration files, which may be appropriate when working with generic middleware aspects.

It's possible to use both Spring's own AOP framework and AspectJ in the same application. They do not conflict, and this is perfectly legitimate. Consider the case where we address transaction management using Spring's TransactionProxyFactoryBean, but need to apply advice to fine-grained objects such as objects persisted with JDO. Spring provides the simplest solution for transaction management. But no proxy-based framework is well suited to advising fine-grained objects, and AspectJ is simply a better fit in such cases. The Spring/AspectJ integration means that it's possible to apply AOP incrementally, turning to the more powerful and complex solution — AspectJ — only when there is no good alternative.

Note 

Of course, many of these advantages and disadvantages apply to other AOP frameworks as well, such as AspectWerkz.

Important 

We believe that AOP will become increasingly important, and that Spring's AspectJ integration will also become increasingly important.

AspectWerkz

Because of the flexibility of its IoC framework, which enables a variety of approaches to instantiating objects, Spring can easily integrate with other AOP frameworks besides AspectJ.

Besides AspectJ, the most important dedicated AOP framework is AspectWerkz (http://aspectwerkz.codehaus.org/).

AspectWerkz differs from AspectJ in that it does not extend the Java language but uses XML metadata to bind aspects at runtime.

AspectWerkz offers a flexible approach to aspect instantiation, which means that it integrates well with Spring. As with AspectJ, both products gain by the combination.

As a starting point, please see "Spring and AspectWerkz — A Happy Marriage" (http://blogs.codehaus.org/people/jboner/archives/ 000826_spring_and_aspectwerkz_a_happy_marriage.html) by Jonas Boner, the creator of AspectWerkz.

Important 

It was announced in early 2005 that AspectJ and AspectWerkz are merging to form AspectJ 5.0. We believe that this is good news for the AOP community as a whole, and expect that AspectJ 5.0 will become the definitive full-featured AOP technology. Both the Spring and AspectJ teams are committed to delivering the best possible integration between the two products, and believe that this is important to both communities.



Professional Java Development with the Spring Framework
Professional Java Development with the Spring Framework
ISBN: 0764574833
EAN: 2147483647
Year: 2003
Pages: 188

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net