Objective:
There are two important differences between Spring's surround notification and pre-notification, and the post-notification:
1) The invocation of the target method is determined by the surround notification, that is, you can decide whether to invoke the target method, and the pre-and post-notification is not determined, they just execute the notification before and after the method's call, that is, the target method is definitely to be executed.
2) surround notification controls the return object, which means you can return a completely different return value from the target object, although it is dangerous, but you can do it. The latter method cannot be done because it is called after the target method returns a value
Here is an example of my own testing that uses face-to-surface to handle some common questions, such as permissions management, the delegation of a transaction
The following example is the use of surround notification, when the program is an exception, repeated submission of the request, the number of repetitions can be set
When we develop an enterprise application, we typically want to refer to a set of modular applications and specific operations from a few facets, and here is a typical general section that might look like this (which is also in the spring documentation)
Package test.prefer.aspect;
Import Org.aspectj.lang.annotation.Aspect;
Import Org.aspectj.lang.annotation.Pointcut;
@Aspect
public class Systemarchitecture {
/**
* A join point was in the Web layer if the method is defined
* In a type in the Com.xyz.someapp.web package or any sub-package
* under that.
*/
@Pointcut ("Within (com.xyz.someapp.web. *)")
public void Inweblayer () {}
/**
* A join point was in the service layer if the method is defined
* In a type in the Com.xyz.someapp.service package or any sub-package
* under that.
*/
@Pointcut ("Within (com.xyz.someapp.service. *)")
public void Inservicelayer () {}
/**
* A join point was in the data access layer if the method is defined
* In a type in the Com.xyz.someapp.dao package or any sub-package
* under that.
*/
@Pointcut ("Within (Com.xyz.someapp.dao. *)")
public void Indataaccesslayer () {}
/**
* A business service was the execution of any method defined on A service
* interface. This definition assumes that interfaces is placed in the
* "Service" package, and that implementation types is in Sub-packages.
*
* If you group service Interfaces by functional area (for example,
* In Packages Com.xyz.someapp.abc.service and Com.xyz.def.service) then
* The Pointcut expression "execution (* com.xyz.someapp). Service.*.* (.. ))"
* could be used instead.
*
* Alternatively, you can write the expression using the ' bean '
* PCD, like so "Bean (*service)". (This assumes
* Named your Spring service beans in a consistent fashion.)
*/
@Pointcut ("Execution (* test.prefer.aspect.*.* (..))")
public void Businessservice () {}
/**
* A data access operation is the execution of any method defined on A
* DAO interface. This definition assumes that interfaces is placed in the
* "DAO" package, and that implementation types is in Sub-packages.
*/
@Pointcut ("Execution (* com.xyz.someapp.dao.*.* (..))")
public void Dataaccessoperation () {}
}
I. Define one of your own facets
/*
* File name: Concurrentoperationexecutor.java
* Description:< Description >
* Modified by: Administrator
*/
Package test.prefer.aspect;
Import Org.aspectj.lang.ProceedingJoinPoint;
Import Org.aspectj.lang.annotation.Around;
Import Org.aspectj.lang.annotation.Aspect;
Import org.springframework.core.Ordered;
/**
* @author
* @date 2010-6-1
*/
@Aspect
public class Concurrentoperationexecutor implements Ordered {
private static final int default_max_retries = 2;
private int maxretries = default_max_retries;
private int order = 1;
public void setmaxretries (int maxretries) {
This.maxretries = maxretries;
}
public int GetOrder () {
return this.order;
}
public void Setorder (int order) {
This.order = order;
}
@Around ("Test.prefer.aspect.SystemArchitecture.businessService ()")
Public Object doconcurrentoperation (Proceedingjoinpoint pjp) throws Throwable {
Surround Notification processing methods
int numattempts = 0;
Exception lockfailureexception;
do {
numattempts++;
try {
SYSTEM.OUT.PRINTLN ("Surround notification method [Doconcurrentoperation (Proceedingjoinpoint PJP)] ...");;
return Pjp.proceed ();
}
catch (Exception ex) {
Lockfailureexception = ex;
}
}
while (numattempts <= this.maxretries);
Throw lockfailureexception;
}
}
Description
Note that the facets implement the Ordered interface so that we can prioritize the tangent to the transaction notification (we want to do it in a completely new transaction each time we try again). Both the maxretries and the order properties can be configured in spring. The main action takes place in Doconcurrentoperation, the wrapping notification method. Please note that all of our businessservice () methods will use this retry policy at this time. We'll try to deal with it first, and if we get a exception exception, we'll just retry until we run out of all the preset retries (Spring development documentation)
Second, configure the section in the configuration file.
<aop:aspectj-autoproxy/>
<bean id= "Concurrentoperationexecutor"
class= "Test.prefer.aspect.ConcurrentOperationExecutor" >
<property name= "Maxretries" value= "3"/>
<property name= "order" value= "/>"
</bean>
All right, let's try the results here.
Third, the test effect
1) Create a new test Bean:mytestaspect with the following code:
Package test.prefer.aspect;
/**
* This is a slice class
*/
Import Org.aspectj.lang.annotation.Aspect;
public class Mytestaspect {
int k=0;
public void Test (String args) throws exception{
System.out.println ("Here is [target] method Test ()" + ++k);
if (k<2) {
throw new Exception ();
}
}
}
This class must be under the package or sub-package of the connection point,
There's a definition in systemarchitecture.
@Pointcut ("Execution (* test.prefer.aspect.*.* (..))")
public void Businessservice () {}
2) applicationcontext.xml Configuration Mytestaspect
<bean id= "test" class= "Test.prefer.aspect.MyTestAspect"/>
3) All right, look at the effect.
Package test;
Import Org.springframework.context.ApplicationContext;
Import Org.springframework.context.support.ClassPathXmlApplicationContext;
Import Test.prefer.aspect.MyTestAspect;
public class Example {
public static void Main (String args[]) {
ApplicationContext CTX = new Classpathxmlapplicationcontext ("Applicationcontext.xml");
Mytestaspect t = (mytestaspect) ctx.getbean ("test");
try{
T.test ("");
}catch (Exception e) {
System.out.println ("main () Handles exception" +e);
}
}
}
The output is:
The surround notification method [Doconcurrentoperation (Proceedingjoinpoint PJP)] .....
Here is the [target] method test () 1
The surround notification method [Doconcurrentoperation (Proceedingjoinpoint PJP)] .....
Here is the [target] method Test ()