欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring By example -- aop

程序员文章站 2022-07-14 13:40:26
...

Spring AOP essentials

1. ProxyFactoryBean is used for declaring AOP

2. ProxyFactory is for programming AOP

3. AspectJFactoryBean is for AspectJ integration

4. For interface, JDK proxy is used

5. For class, CGLib is used

6. Ref InvocationHandler

 

Defining AOP terminology 

ADVICE 

In AOP terms, the job of an aspect is called advice.

Spring aspects can work with five kinds of advice:

Before—The advice functionality takes place before the advised method is invoked.

After—The advice functionality takes place after the advised method completes, regardless of the outcome.

After-returning—The advice functionality takes place after the advised method successfully completes.

After-throwing—The advice functionality takes place after the advised method throws an exception.

Around—The advice wraps the advised method, providing some functionality before and after the advised method is invoked.

 

JOIN POINTS

A join point is a point in the execution of the application where an aspect can be plugged in. This point could

be a method being called, an exception being thrown, or even a field being modified.

These are the points where your aspect’s code can be inserted into the normal flow of

your application to add new behavior.

 

POINTCUTS

Pointcuts help narrow down the join points advised by an aspect.

If advice defines the what and when of aspects, then pointcuts define the where. A pointcut definition matches one or more join points at which advice should be woven.

 

ASPECTS

An aspect is the merger of advice and pointcuts. Taken together, advice and point-cuts define everything there is to know about an aspect—what it does and where and when it does it.

 

INTRODUCTIONS

An introduction allows you to add new methods or attributes to existing classesv

 

WEAVING

Weaving is the process of applying aspects to a target object to create a new proxied object. The aspects are woven into the target object at the specified join points. The weaving can take place at several points in the target object’s lifetime:

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 byte-code 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’s AOP support

SPRING ADVICE IS WRITTEN IN JAVA

SPRING ADVISES OBJECTS AT RUNTIME

SPRING ONLY SUPPORTS METHOD JOIN POINTS

 

Selecting join points with pointcuts

In Spring AOP, pointcuts are defined using AspectJ’s pointcut expression language.

Spring leverages AspectJ’s pointcut expression language for defining Spring aspects.

args() Limits join point matches to the execution of methods whose arguments are instances of the given types

@args() Limits join point matches to the execution of methods whose arguments are annotated with the given annotation types

execution() Matches join points that are method executions

this() Limits join point matches to those where the bean reference of the AOP proxy is of a given type

target() Limits join point matches to those where the target object is of a given type

@target() Limits matching to join points where the class of the executing object has an annotation of the given type

within() Limits matching to join points within certain types

@within() Limits matching to join points within types that have the given annotation (the execution of methods declared in types with the given annotation when using Spring AOP)

@annotation Limits join point matches to those where the subject of the join point has the

given annotation

 

Writing pointcuts

Selecting the Instrument’s play() method with an AspectJ pointcut expression

 

 

Spring By example -- aop

 

Spring By example -- aop

 execution(*com.springinaction.springidol.Instrument.play()) and bean(eddie)

 

execution(*com.springinaction.springidol.Instrument.play()) and !bean(eddie)

 

Declaring aspects in XML

Spring’s AOP configuration elements simplify declaration of POJO-based aspects.

<aop:advisor> Defines an AOP advisor.

<aop:after> Defines an AOP after advice (regardless of whether the advised method returns  successfully).

<aop:after-returning> Defines an AOP after-returning advice.

<aop:after-throwing> Defines an AOP after-throwing advice.

<aop:around> Defines an AOP around advice.

<aop:aspect> Defines an aspect.

<aop:aspectj-autoproxy> Enables annotation-driven aspects using @AspectJ.

<aop:before> Defines an AOP before advice.

<aop:config> The top-level AOP element. Most <aop:*> elements must be contained within <aop:config>.

<aop:declare-parents> Introduces additional interfaces to advised objects that are transparently implemented.

<aop:pointcut> Defines a pointcut.

 

public classAudience{
public voidtakeSeats(){
System.out.println("Theaudienceistakingtheirseats.");
}
public voidturnOffCellPhones(){
System.out.println("Theaudienceisturningofftheircellphones");
}
public voidapplaud(){
System.out.println("CLAPCLAPCLAPCLAPCLAP");
}
public voiddemandRefund(){
System.out.println("Boo!Wewantourmoneyback!");
}
}
 

 

 

<bean id="audience"
class="com.springinaction.springidol.Audience"/>
 

 

<aop:config>
<aop:aspect ref="audience">
<aop:before pointcut=
"execution(* com.springinaction.springidol.Performer.perform(..))"
method="takeSeats"/>
<aop:before pointcut=
"execution(* com.springinaction.springidol.Performer.perform(..))"
method="turnOffCellPhones"/>
<aop:after-returning pointcut=
"execution(* com.springinaction.springidol.Performer.perform(..))"
method="applaud"/>
<aop:after-throwing pointcut=
"execution(* com.springinaction.springidol.Performer.perform(..))"
method="demandRefund"/>
</aop:aspect>
</aop:config>

 Spring By example -- aop

 

 

 

 Defining a named pointcut to eliminate redundant pointcut definitions

 

<aop:config>
<aop:aspect ref="audience">
<aop:point cutid="performance"expression=
"execution(* com.springinaction.springidol.Performer.perform(..))"
/>
<aop:before
pointcut-ref="performance"
method="takeSeats" />
<aop:before
pointcut-ref="performance"
method="turnOffCellPhones"/>
<aop:after-returning
pointcut-ref="performance"
method="applaud" />
<aop:after-throwing
pointcut-ref="performance"
method="demandRefund" />
</aop:aspect>
</aop:config>

 

Declaring around advice

public voidwatchPerformance(ProceedingJoinPointjoinpoint){
try {
System.out.println("Theaudienceistakingtheirseats.");
System.out.println("Theaudienceisturningofftheircellphones");
longstart=System.currentTimeMillis();
joinpoint.proceed();
longend=System.currentTimeMillis(); System.out.println("CLAPCLAPCLAPCLAPCLAP");
System.out.println("Theperformancetook"+(end-start)
+ "milliseconds.");
} catch(Throwablet){
System.out.println("Boo!Wewantourmoneyback!");
}
}

 

 

<aop:config>
<aop:aspectref="audience">
<aop:pointcutid="performance2"expression=
"execution(* com.springinaction.springidol.Performer.perform(..))"
/>
<aop:around
pointcut-ref="performance2"
method="watchPerformance()"/>
</aop:aspect>
</aop:config>

 

Passing parameters to advice

package com.springinaction.springidol;
public interface MindReader{
void interceptThoughts(Stringthoughts);
String getThoughts();
}

 

package com.springinaction.springidol;
public class Magician implements MindReader{
privateStringthoughts;
public voidinterceptThoughts(Stringthoughts){
System.out.println("Interceptingvolunteer'sthoughts");
this.thoughts=thoughts;
}
public StringgetThoughts(){
returnthoughts;
}
}

 

package com.springinaction.springidol;
public interface Thinker{
void thinkOfSomething(Stringthoughts);
}

 

package com.springinaction.springidol;
public class Volunteer implements Thinker{
privateStringthoughts;
public voidthinkOfSomething(Stringthoughts){
this.thoughts=thoughts;
}
public StringgetThoughts(){
returnthoughts;
}
}

 

<aop:config>
<aop:aspect ref="magician">
<aop:pointcut id="thinking"
expression="execution(*
com.springinaction.springidol.Thinker.thinkOfSomething(String))
and args(thoughts)"/>
<aop:before 
pointcut-ref="thinking"
method="interceptThoughts"
arg-names="thoughts" />
</aop:aspect>
</aop:config>

 

@Test
public voidmagicianShouldReadVolunteersMind(){
volunteer.thinkOfSomething("QueenofHearts");
assertEquals("QueenofHearts",magician.getThoughts());
}

 

Introducing new functionality with aspects

Spring By example -- aop

 Annotating aspects

A key feature introduced in AspectJ 5 is the ability to use annotations to create aspects.

Prior to AspectJ 5, writing AspectJ aspects involved learning a Java language extension.

But AspectJ’s annotation-oriented model makes it simple to turn any class into an

aspect by sprinkling a few annotations around. This new feature is commonly referred

to as @AspectJ.

package com.springinaction.springidol;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public classAudience{
@Pointcut(
"execution(* com.springinaction.springidol.Performer.perform(..))")
public voidperformance(){
}
@Before("performance()")
public voidtakeSeats(){
System.out.println("Theaudienceistakingtheirseats.");
}
@Before("performance()")
public voidturnOffCellPhones(){
System.out.println("Theaudienceisturningofftheircellphones");
}
@AfterReturning("performance()")
public voidapplaud(){
System.out.println("CLAPCLAPCLAPCLAPCLAP");
}
@AfterThrowing("performance()")
public voiddemandRefund(){
System.out.println("Boo!Wewantourmoneyback!");
}
}

 

<aop:aspectj-autoproxy/>
<aop:aspectj-autoproxy/>

 

Annotating around advice

@Around("performance()")
public voidwatchPerformance(ProceedingJoinPointjoinpoint){
try {
System.out.println("Theaudienceistakingtheirseats.");
System.out.println("Theaudienceisturningofftheircellphones");
longstart=System.currentTimeMillis();
joinpoint.proceed();
longend=System.currentTimeMillis();
System.out.println("CLAPCLAPCLAPCLAPCLAP");
System.out.println("Theperformancetook"+(end-start)
+ "milliseconds.");
} catch(Throwablet){
System.out.println("Boo!Wewantourmoneyback!");
}
}

 Passing arguments to annotated advice

package com.springinaction.springidol;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public classMagicianimplementsMindReader{
privateStringthoughts;
@Pointcut("execution(*com.springinaction.springidol."
+ "Thinker.thinkOfSomething(String))&&args(thoughts)")
public voidthinking(Stringthoughts){
}
@Before("thinking(thoughts)")
public voidinterceptThoughts(Stringthoughts){
System.out.println("Interceptingvolunteer'sthoughts:"+thoughts);
this.thoughts=thoughts;
}
public StringgetThoughts(){
returnthoughts;
}
}

 

Annotating introductions

package com.springinaction.springidol;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;
@Aspect
public classContestantIntroducer{
@DeclareParents(
value="com.springinaction.springidol.Performer+",
defaultImpl=GraciousContestant.class)
public staticContestantcontestant;
}

 

 

 Injecting AspectJ aspects