AspectJ Integration

AOP provides a powerful solution to many of the common problems that arise with OOP-based applications. When using Spring AOP, you can take advantage of a select subset of AOP functionality that, in most cases, allows you to solve problems you encounter in your application. However, in some cases, you may wish to use some AOP features that are outside the scope of Spring AOP. In this case, you need to look at an AOP implementation with a fuller feature set. Our preference, in this case, is to use AspectJ, and because you can now configure AspectJ aspects using Spring, AspectJ forms the perfect complement to Spring AOP.

About AspectJ

AspectJ is a fully featured AOP implementation that uses a compile-time weaving process to introduce aspects into your code. In AspectJ, aspects and pointcuts are built using a Java-like syntax, which reduces the learning curve for Java developers. We are not going to spend too much time looking at AspectJ and how it works because that is way beyond the scope of this book. Instead, we present some simple AspectJ examples and show you how to configure them using Spring. For more information on AspectJ, you should definitely read AspectJ in Action by Raminvas Laddad (Manning, 2003).

Note 

We are not going to cover how to compile and weave AspectJ aspects into your application. Refer to the AspectJ documentation for details on how to achieve this. Alternatively, Eclipse users can download the AspectJ integration package and take advantage of full IDE integration and auto-compilation.

Using Singleton Aspects

By default, AspectJ aspects are singletons, in that you get a single instance per classloader. The problem Spring faces with any AspectJ aspect is that it cannot create the aspect instance because that is handled by AspectJ itself. However, each aspect exposes a method, aspectOf(), which can be used to access the aspect instance. Using the aspectOf() method and a special feature of Spring configuration, you can have Spring configure the aspect for you. The benefits of this cannot be understated. You can take full advantage of AspectJ's powerful AOP feature set without losing out on Spring's excellent DI and configuration abilities. This also means that you do not need two separate configuration methods for your application; you can use the same Spring ApplicationContext approach for all your Spring-managed beans and for your AspectJ aspects.

There is actually nothing particularly special or difficult about configuring AspectJ aspects using Spring, as the following example shows. In Listing 7-25, you can see a basic class, MessageWriter, that we will advise using AspectJ.

Listing 7-25: The MessageWriter Class

image from book
package com.apress.prospring.ch7.aspectj;      public class MessageWriter {          public void writeMessage() {         System.out.println("foobar!");     }          public void foo() {         System.out.println("foo");     } }
image from book

For this example, we are going to use AspectJ to advise the writeMessage() method and write out a message before and after the method invocation. These messages will be configurable using Spring.

Listing 7-26 shows the MessageWrapper aspect.

Listing 7-26: MessageWrapper Aspect

image from book
package com.apress.prospring.ch7.aspectj;      public aspect MessageWrapper {          private String prefix;     private String suffix;          public void setPrefix(String prefix) {         this.prefix = prefix;     }          public void setSuffix(String suffix) {         this.suffix = suffix;     }             pointcut doWriting() :          execution(*             com.apress.prospring.ch7.aspectj.MessageWriter.writeMessage());          before() : doWriting() {         System.out.println(prefix);     }          after() : doWriting() {         System.out.println(suffix);     } }
image from book

Much of this code should look familiar. Essentially we create an aspect called MessageWrapper and, just like a normal Java class, we give the aspect two properties, suffix and prefix, which we will use when advising the writeMessage() method. Next, we define a named pointcut, doWriting(), for a single joinpoint, in this case, the execution of the writeMessage() method. (AspectJ has a huge number of joinpoints, but coverage of those is outside the scope of this example.) Finally, we define two lots of advice: one that executes before the doWriting() pointcut and one that executes after it. The before advice writes a line containing the prefix and the after advice writes a line containing the suffix. Listing 7-27 shows how this aspect is configured in Spring.

Listing 7-27: Configuring an AspectJ Aspect

image from book
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"  "http://www.springframework.org/dtd/spring-beans.dtd"> <beans>    <bean                         factory-method="aspectOf">     <property name="prefix">         <value>Ha Ha!</value>     </property>       <property name="suffix">         <value>Ho Ho!</value>     </property>   </bean> </beans> 
image from book

As you can see, much of the configuration of the aspect bean is very similar to standard bean configuration. The only difference is the use of the factory-method attribute of the <bean> tag. The factory-method attribute is intended to allow classes that follow a traditional Factory pattern to be integrated seamlessly into Spring. For instance, if you have a class Foo with a private constructor and then a static factory method, getInstance(), using factory-method allows a bean of this class to be managed by Spring. The aspectOf() method exposed by every AspectJ aspect allows you to access the instance of the aspect and thus allows Spring to set the properties of the aspect. Listing 7-28 shows a simple driver application for this example.

Listing 7-28: AspectJ Configuration in Action

image from book
package com.apress.prospring.ch7.aspectj;      import org.springframework.context.ApplicationContext; import org.springframework.context.support.FileSystemXmlApplicationContext;      public class AspectJExample {          public static void main(String[] args) {         ApplicationContext ctx = new FileSystemXmlApplicationContext(                 "./ch7/src/conf/aspectj.xml");         MessageWriter writer = new MessageWriter();         writer.writeMessage();         writer.foo();     } }
image from book

Notice that first we load the ApplicationContext to allow Spring to configure the aspect. Next we create an instance of MessageWriter and then invoke the writeMessage() and foo() methods. The output from this example is as follows:

Ha Ha! foobar! Ho Ho! foo

As you can see, the advice in the MessageWrapper aspect was applied to the writeMessage() method and the prefix and suffix values specified in the ApplicationContext configuration were used by the advice when writing out the before and after messages.

Features Coming Soon

Currently the only feature implemented in the Spring/AspectJ integration is the ability to configure singleton aspects. Because this is the most important feature required, it was the feature that was placed at the top of the list. For the 1.2 release, expect to see support for perthis, pertarget, and percflow aspects as well as the current support for singleton aspects. Also planned for 1.2 is an AspectJ-style pointcut expression language for Spring, which will allow a greater range of pointcuts to be defined in Spring.



Pro Spring
Pro Spring
ISBN: 1590594614
EAN: 2147483647
Year: 2006
Pages: 189

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