View RSS Feed

Spring Framework

How to Inject AspectJ Aspects into Spring

Rate this Entry
by , 11-29-2011 at 02:53 AM (2010 Views)
For those of you who have already worked with Spring AOP knows that it is sufficient for many of the applications of aspects that are generally done in a system. Still it is weak in certain areas of AOP solution in contrast to AspectJ that has added a number of powerful features over time. There are now many types of AspectJ pointcuts that arenít possible with Spring AOP.

For example, Springís proxy-based AOP is not able to advise on object creation. This is because constructors in Java are different from normal methods. Overall, most AspectJ aspects are independent of Spring. You can be wove them into any Java-based application, including Spring applications, but thereís little involvement on Springís part in applying AspectJ aspects.

If you are making useful aspects, any developer will know that as with regular classes, they depend on other classes to assist in its work. If you aspect depends on another class or classes, you can either instantiate these lasses yourself with the aspect or you can use Springís dependency injection to inject beans into AspectJ aspects.

Letís consider an example using around various competitions. This competition is around a lottery so letís create a lottery aspect in AspectJ.

Java Code:
package com.acme.springexamples.competition;

public aspect Lottery { 

	public Lottery() {}
	pointcut spinWheel() : execution(* startGame(..));
	after() returning() : spinWheel() { 
	    System.out.println(lotteryWheel.getChosenNumber());
}

// injected 
private LotteryWheel lotteryWheel; 
public void setLotteryWheel(LotteryWheel lotteryWheel) {
	this.lotteryWheel = lotteryWheel;
}
The main responsibility of the Lottery is to provide the selected number when the lottery wheel is spun. The spinWheel() point matches the startGame() method. As it is matched up with the after() returning() advice, at the end the aspect will provide you with the chosen number.

Note that the lottery doesnít just announce the winner on its own. It collaborates with the lottery wheel calling the getChosenNumber() method. to indicate what is the winning number for the lottery. In order to decouple the two objects for potential reuse in other competitions, the Lottery is given a reference to the LotteryWheel object through setter injection.

Below I should the interface and implementation of the LotteryWheel. Note that itís only method is to produce the chosen number.

Java Code:
package com.acme.springexamples.competition;
public class LotteryWheelImpl implements LotteryWheel { 
    public LotteryWheelImpl() {}
    public String getChosenNumber() {
	int i = MIN + (int)(Math.random() * ((MAX - MIN) + 1)); 
	return i;
    }
// injected 
    private int MIN;
    public void setMin(int min) { this.MIN = min;}
    private int MAX;
    public void setMax(int max) { this.MAX = max;}
}
LotteryWheelImpl implements the LotteryWheel interface by randomly choosing a the winning number for a range of possible choices. We now declare it as a Spring <bean>:

Java Code:
<bean id="lotteryWheel" class="com.acme.springexamples.competition.LotteryWheelImpl">
    <property name="min"> 
	<value>1</value> <value>
    </property>
    <property name=ĒmaxĒ>
	<value>50</value>
    </property>
</bean>
Now I wire LotteryWheelImpl into Lottery:

Java Code:
<bean class="com.acme.springexamples.competition.LotteryAspect" 
	factory-method="aspectOf">
    <property name="lotteryWheel" ref="lotteryWheel" /> 
</bean>
In order to inject collaborators into an AspectJ aspect, itís necessary to declare the aspect as a <bean> in Springís configuration. Youíll note that the declaration is not different from any other bean except for the factory-method attribute. Since AspectJ aspects are created by the AspectJ runtime, the aspect has already been instantiated before Spring will have an opportunity to inject the LotteryWheel into the LotteryAspect. So instead, the way for Spring to get a handle to the LotteryAspect instance is to use the static aspectOf() method that AspectJ provides for all aspects. This returns a singleton instance of the aspect. You must therefore use the factory-method to invoke aspectOf() method instead of calling the LotteryApectís constructor. Now we know that Spring retrieves a reference to the aspect through the aspectOf() factory method, and is then able to do dependency injection on the bean as defined in the <bean> element. If you want to know more, review Springís AOP documentation.

Submit "How to Inject AspectJ Aspects into Spring" to Facebook Submit "How to Inject AspectJ Aspects into Spring" to Digg Submit "How to Inject AspectJ Aspects into Spring" to del.icio.us Submit "How to Inject AspectJ Aspects into Spring" to StumbleUpon Submit "How to Inject AspectJ Aspects into Spring" to Google

Categories
AOP , Spring 3

Comments