AOP操作是我们日常开发经常使用到的操作,例如都会用到的spring事务管理.今天我们通过一个demo实现对一个类的某一个方法进行前置和后置的增强.
//被增强类
public class PetStoreService {
//被增强方法
public void placeOrder(){
System.out.println("place order");
}
}
//增强类
public class TransactionManager {
//前置方法
public void start() {
System.out.println("start");
}
//后置方法
public void end() {
System.out.println("end");
}
}
我们要做的就是在PetStoreService 中的placeOrder()执行前和执行后分别执行TransactionManager 中的start()和end()方法.下面我们将抽象出一个通知接口
//通知
public interface Advice {
//执行增强方法
public void invoke(InterceptorChain chain);
}
两个实现类,分别来执行start()和end()方法
//前置增强
public class BeforeAdvice implements Advice {
//增强方法所属实例对象
private Object object;
//增强方法
private Method method;
//增强方法的参数
private Object[] arguments;
public BeforeAdvice(Object object, Method method, Object[] arguments) {
this.object = object;
this.method = method;
this.arguments = arguments;
}
//织入方法
public void invoke(InterceptorChain chain) {
try {
//执行增强方法
method.invoke(object, arguments);
//返回
chain.proceed();
} catch (Exception e) {
System.out.println("执行after方法失败!!!!");
}
}
}
//后置增强
public class AfterAdvice implements Advice {
//增强方法所属实例对象
private Object object;
//增强方法
private Method method;
//增强方法的参数
private Object[] arguments;
public AfterAdvice(Object object, Method method, Object[] arguments) {
this.object = object;
this.method = method;
this.arguments = arguments;
}
//织入方法
public void invoke(InterceptorChain chain) {
try {
//返回
chain.proceed();
//执行增强方法
method.invoke(object, arguments);
} catch (Exception e) {
System.out.println("执行after方法失败!!!!");
}
}
}
两个方法中的构造子相同,都是给出通知类所需要的参数,而invoke()则是使用反射执行增强方法.
需要注意的是invoke()方法的参数,是一个拦截器链,两个方法都在执行自身Method方法前或者后执行了拦截器链中的方法.
下面是拦截器链
public class InterceptorChain {
//拦截器链
private List<Advice> adviceList;
//需要增强的对象
private Object object;
//需要增强的方法
private Method method;
//当前需要执行方法的参数
private Object[] arguments;
//当前要执行的拦截器指针
private int pointer = -1;
//构造子
InterceptorChain(Object obj, Method method, Object[] arguments) {
this.object = obj;
this.method = method;
this.arguments = arguments;
this.adviceList = new ArrayList<Advice>();
}
//执行拦截器链
public void proceed() {
//如果当前指针指向拦截器末尾则执行自身得方法
if (this.pointer == adviceList.size() - 1) {
invoke();
return;
}
//指针+1
pointer++;
//获取需要执行的拦截器
Advice advice = this.adviceList.get(pointer);
//执行了拦截器
advice.invoke(this);
}
//执行原方法
public void invoke() {
try {
method.invoke(object, arguments);
} catch (Exception e) {
System.out.println("执行原有方法失败!!!");
}
}
//增加拦截器
public void addAdvice(Advice advice) {
this.adviceList.add(advice);
}
}
这是一个核心类,其中的关键在于,客户端将把增强类添加到拦截器链中,在拦截器链中有一个指针pointer用来指向即将执行的增强方法.
下面是客户端调用
public class Main {
public static void main(String[] args) throws Exception {
//需要增强的对象
PetStoreService petStoreService = new PetStoreService();
//增强
TransactionManager transactionManager = new TransactionManager();
//创建拦截器
InterceptorChain interceptorChain = new InterceptorChain(petStoreService, PetStoreService.class.getMethod("placeOrder"), new Object[0]);
//增加拦截器链
interceptorChain.addAdvice(new BeforeAdvice(transactionManager, TransactionManager.class.getMethod("start"), new Object[0]));
//增加拦截器链
interceptorChain.addAdvice(new AfterAdvice(transactionManager, TransactionManager.class.getMethod("end"), new Object[0]));
//执行拦截器方法
interceptorChain.proceed();
}
}
我们分别创建需要增强的对象,还有增强对象.并把增强对象中的增强方法添加到拦截器链中.最终我们实现了,按照顺序执行完了拦截器链中的方法.感兴趣的同学可以debug试试看.
两个advice中调用拦截器的proceed()方法顺序,不一样的话,会有不同的结果哦.