Advice defines both the what and the when of an aspect.
A joinpoint is a point in the execution of the application where an aspect can be plugged in.
If advice defines the what and when of aspects then
pointcuts define the where. A pointcut definition matches one or more joinpoints at which advice should be woven.
An
aspect is the merger of advice and pointcuts.
An introduction allows you to add new methods or attributes to existing classes.
A target is the object that is being advised.
A proxy is the object created after applying advice to the target object.
Weaving is the process of applying aspects to a target object to create a new, proxied object.
Compile time—Aspects are woven in when the target class is compiled. This requires a special compiler. AspectJ’s weaving compiler weaves aspects this way.
Classload time—Aspects are woven in when the target class is loaded into the JVM. This requires a special ClassLoader that enhances that target class’s bytecode before the class is introduced into the application. AspectJ 5’s load-time weaving (LTW) support weaves aspects in this way.
Runtime—Aspects are woven in sometime during the execution of the application. Typically, an AOP container will dynamically generate a proxy object that will delegate to the target object while weaving in the aspects. This is how Spring AOP aspects are woven.
Spring does not create a proxied object until that proxied bean is needed by the application.
If you are using an ApplicationContext, the proxied objects will be created when it loads all of the beans from the BeanFactory. Because Spring creates proxies at runtime, you do not need a special compiler to weave aspects in Spring’s AOP.
Spring generates proxied classes in two ways.
If your target object
implements an interface(s) that exposes the required methods, Spring will use the
JDK’s java.lang.reflect.Proxy class. This class allows Spring to dynamically generate a new class that implements the necessary interfaces, weave in any advice, and proxy any calls to these interfaces to your target class.
If your target class
does not implement an interface, Spring uses the
CGLIB library to generate a subclass to your target class. When creating this subclass, Spring weaves in advice and delegates calls to the subclass to your target class.
Spring only supports method joinpoints.
AspectJ and JBoss, which provide field and constructor joinpoints in addition to method pointcuts.
Advice type -- Interface
Before -- org.springframework.aop.MethodBeforeAdvice
After-returning -- org.springframework.aop.AfterReturningAdvice
After-throwing -- org.springframework.aop.ThrowsAdvice
Around -- org.aopalliance.intercept.MethodInterceptor
Introduction -- org.springframework.aop.IntroductionInterceptor
Around advice also offers you the opportunity to inspect and alter the value returned from the advised method. This makes it possible to write advice that performs some postprocessing on a method’s return value before returning the value to the caller. AfterReturningAdvice only allows you to inspect the returned value—you can’t change it.
<bean id="audienceAdvisor"
class="org.springframework.aop.aspectj.
➥ AspectJExpressionPointcutAdvisor">
<property name="advice" ref="audienceAdvice" />
<property name="expression" value="execution(* *.perform(..))" />
</bean>
<bean id="duke"
class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="dukeTarget" />
<property name="interceptorNames" value="audienceAdvisor" />
<property name="proxyInterfaces"
value="com.springinaction.springidol.Performer" />
</bean>
Spring comes with a handy implementation of
BeanPostProcessor called
DefaultAdvisorAutoProxyCreator, which automatically checks to see whether an advisor’s pointcut matches a bean’s methods and replaces that bean’s definition with a proxy that applies the advice. In a nutshell, it automatically proxies beans with matching advisors.
<bean class="org.springframework.aop.framework.autoproxy.
➥ DefaultAdvisorAutoProxyCreator" />
Autoproxying @AspectJ aspects
<aop:aspectj-autoproxy/> will create an AnnotationAwareAspectJAutoProxy- Creator in the Spring context and will automatically proxy beans whose methods match the pointcuts defined with @Pointcut annotations in @Aspectannotated beans.
Declaring a
pure-POJO to aspects
<aop:config>
<aop:aspect ref="audience">
<aop:before
method="takeSeats"
pointcut="execution(* *.perform(..))" />
<aop:before
method="turnOffCellPhones"
pointcut="execution(* *.perform(..))" />
<aop:after-returning
method="applaud"
pointcut="execution(* *.perform(..))" />
<aop:after-throwing
method="demandRefund"
pointcut="execution(* *.perform(..))" />
</aop:aspect>
</aop:config>
Injecting AspectJ aspects
public aspect JudgeAspect {
public JudgeAspect() {}
pointcut performance() : execution(* perform(..));
after() returning() : performance() {
System.out.println(criticismEngine.getCriticism());
}
....
}
<bean class="com.springinaction.springidol.JudgeAspect"
factory-method="aspectOf">
<property name="criticismEngine" ref="criticismEngine" />
</bean>
Spring doesn’t use the <bean> declaration from earlier to create an instance of the JudgeAspect—it has already been created by the AspectJ runtime. Instead, Spring retrieves a reference to the aspect through the
aspectOf() factory method.