Spring AOP - Runtime - Using Proxy
Steps
1.Spring Application Context - Bean Declarations
For enabling this proxy approach add
<aop:aspectj-autoproxy />
Note :
Do not be misled by the name of the
element: using it will result in the creation of Spring AOP proxies. The @AspectJ style of aspect declaration is just being used here, but the AspectJ runtime is not involved
Aspect Declaration
<bean id="myAspect" class="com.test.aop.MyAspect"></bean>
Method where aspect will be applied
<bean id="test" class="com.test.aop.Test" init-method="init" />
Wrapper calling test
<bean id="testB" class="com.test.aop.Wrapper" init-method="init">
<property name="test" ref="test"></property>
</bean>
2. Classes
- Aspect Class
@Aspect
public class MyAspect {
@Before("execution(* com.test.aop.Test.*())")
public void myMethod()
{
System.out.println("calling my before aspect");
}
}
- public class Test {
public void init()
{
System.out.println("init in test method");
}
}
- public class Wrapper {
private Test test;
public void setTest(Test test) {
this.test = test;
}
public void init() {
test.init();
}
}
3. OutPut(In Spring DM)
System.out I init in test method
System.out I calling my before aspect
System.out I init in test method
Only when the init method is called through testB bean ,the aspect is bound.
Now when init method of test bean is called , the aspect is still not bound.(init methods cannot be proxied).
This is because the way spring life cycle works :
Spring life cycle
Phase 1 - Validate bean definitions
Phase 2 - Bean definition post processor(replacing property values)
Phase 3 - Bean Instantiation
Phase 4 - Bean post initialization(setters and init methods -in order) & Proxy creation
In the above example bean 'test' first cycles through phase 1,2,3 and 4. Hence after the init method is called, the proxy is created.But when testB is created in its init(phase) call to bean test will call teh aspect (as bean test lifecycle is complete)
One more important thing to note is that Cg lib will be used to create proxy here as teh class doesnt implement any interface.(Else jdk dyanmic proxies would have been used)
Aspect-J Load Time Weaving
(This may have issues with Spring DM
http://forum.springsource.org/showthread.php?t=80504
)
Same code as above except some change in the configurations.
1. Replace <aop:aspectj-autoproxy /> with <context:load-time-weaver/>.
2. Add aop.xml in META-INF directory
<!DOCTYPE aspectj PUBLIC
"-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<!--works without this -->
<weaver>
<include within="com.test.aop.*" />
</weaver>
<aspects>
<!-- weave in just this aspect -->
<aspect name="com.test.aop.MyAspect" />
</aspects>
</aspectj>
3. Class to test the application in standlone mode
public class StandAloneLoadTimeWeaving {
public static void main(String args[])
{
ApplicationContext ctx = new ClassPathXmlApplicationContext("config.xml",StandAloneLoadTimeWeaving.class);
Test t =(Test)ctx.getBean("test");
t.init();
}
}
Ref: http://www.springbyexample.org/examples/aspectj-ltw.html
http://static.springsource.org/spring/docs/2.5.x/reference/aop.html#aop-aj-ltw
4. Add the following parameter when running
-javaagent:spring-agent.jar
Aspect J Compile Time Weaving(Build Time)
Same as Loadtime weaving needs aop.xml (but no need to add spring agent while running)
Command to compile the code
java org.aspectj.tools.ajc.Main –inpath <src_code_directory> -outjar <output_jarname.jar>
Ex:java -cp aspectjtools.jar;aspectjrt.jar org.aspectj.tools.ajc.Main -inpath . -outjar test.jar
The output jar will have code which is instrumented by the aspect.
You can download aspectj from this site
http://www.eclipse.org/aspectj/downloads.php