在阅读本文前首先请确保会java的动态代理技术
springAOP大家都知道使用的动态·代理技术,当然这个技术是根本,其实在Spring在处理AOP的时候还使用了链式处理
举个例子 例如一个类 有多个前置增强 (即全都在代理目标类方法前执行)又有多个后置增强(全都在方法目标类的后面执行) 如何确保前置增强执行完后再执行代理目标类方法 最后在执行后置增强呢,答案是使用链式处理,先理解下链式处理 应为实现AOP正式围绕链式处理和动态代理 的 具体例子链式处理看下代码
首先定义一个这样的接口 public interface Proxy { public void doProxy(proxyChain proxyChain) throws Exception; }
public class ProxyChain
{
private int currentIndex = -1;
private List<Proxy> proxyList;//每一个代理链都表示 一个拦截的方法
//普通方式链式处理 的确能按顺序执行完,
public void Todo() throws Exception{
if(currentIndex < proxyList.size()-1){
proxyList.get(++currentIndex).doProxy(this);
}else{ 添加判断 防止递归完后每个方法都回到这 也算终止条件
System.out.print("原来方法调用"); //调用原先方法 method.invoke(),可以通过参数获得
}
}
}
public class ProxyImp implements Proxy {
private Method method; //表示再起其执行之前 添加的方法
@Override
public void doProxy(ProxyChain proxyChain) throws Exception{
System.out.print("before"); 注意这里 //发现没有如果这一段在前面 总是执行在我们 我们原先方法的前面
//todo原来
proxyChain.Todo(); //递归调用
System.out.print("after"); 注意这里 //发现没有如果这一段在后面 总是执行在我们 我们原先方法的后面
}
}
发现没有在doProxy中会调用proxyChain.Todo方法;然后在proxyChain.Todo又递归调用每个proxy的doProxy方法正是通过这种链式处理方式来确保前置增强执行完后再执行代理目标类方法 最后在执行后置增强。其实Spring中在实现AOP也正是用到这一技术来确保前置方法拦截器执行完后再执行目标方法在执行后置拦截器方法
接下来我们自己实现得AOP功能也正是基于这两个思想:链式处理,动态代理 话不多接下来直接上代码
//接口 所有增强都实现该接口以便我们进行链式处理 public interface Proxy { public Object doProxy(ProxyChain proxyChain); }
//执行链 public class ProxyChain { private Method method; //目标方法 被代理的方法 private Object target; //代理对象 private Object[] arguments; //代理对象的参数 private int currentIndex = -1; private List<Proxy> proxyList;//每一个代理链都表示 一个拦截的方法 public ProxyChain(Method method, Object target, Object[] arguments, List<Proxy> proxyList) { this.method = method; this.target = target; this.arguments = arguments; this.proxyList = proxyList; } /链式处理 的确能按顺序执行完, public Object Todo() { Object methodResult; if (currentIndex < proxyList.size() - 1) { methodResult = proxyList.get(++currentIndex).doProxy(this); } else { try { methodResult = method.invoke(target, arguments); //调用原先方法 method.invoke(),可以通过参数获得 } catch (Exception e) { e.printStackTrace(); methodResult = e; } finally { } } return methodResult; } public Method getMethod() { return method; } public Object getTarget() { return target; } public Object[] getArguments() { return arguments; } }
** * 前置增强接口 用于增强到方法中 需要自己覆盖before或者after方法 */ public abstract class BeforeProxy implements Proxy { @Override public Object doProxy(ProxyChain proxyChain) { Object[] arguments = proxyChain.getArguments(); Object target = proxyChain.getTarget(); Method method = proxyChain.getMethod(); Object result; before(target,method,arguments); result = proxyChain.Todo(); return result; } public abstract void before(Object target,Method method ,Object[] arguments); }
//后置增强接口 其实前置增强接口和后置增强接口可以统一 在一起 这个就留给大家自行思考 package com.lin.AOP1; import java.lang.reflect.Method; public abstract class AfterProxy implements Proxy { @Override public Object doProxy(ProxyChain proxyChain) { Object[] arguments = proxyChain.getArguments(); Object target = proxyChain.getTarget(); Method method = proxyChain.getMethod(); Object result; result = proxyChain.Todo(); after(target,method,arguments); return result; } public abstract void after(Object target,Method method ,Object[] arguments); }
//产生动态代理 package com.lin.AOP1; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; public class JDKProxyBeanFactory implements InvocationHandler { private Object target;//代理类 private ProxyChain proxyChain; //一个ProxyChain代表着一个代理对象 private Class<?>[] intefaces; //接口代理人为配置 private List<Proxy> proxyList ; //增强类接口人为配置 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { proxyChain = new ProxyChain(method,target,args, proxyList); return proxyChain.Todo(); } public Object getRealProxy(){ return java.lang.reflect.Proxy.newProxyInstance(this.getClass().getClassLoader(),intefaces,this); } public void setIntefaces(Class<?> [] intefaces){ this.intefaces =intefaces; } public void setTarget(Object target){ this.target = target; } public void setProxyChain(ProxyChain proxyChain) { this.proxyChain = proxyChain; } public void setProxyList(List<Proxy> proxyList) { this.proxyList = proxyList; } }
接下来我们多我们写的东西进行测试 ,在这里为了方便快捷 就不模仿spring那样通过xml配置来实现自动注入了 我们认为的来设计
package com.lin.AOP1;
//代理接口
public interface Hello { void say(); }
package com.lin.AOP1; //接口实现类 public class HelloImp implements Hello{ @Override public void say() { System.out.print("hello"); } }
//自己的前置增强 package com.lin.AOP1; import java.lang.reflect.Method; public class MyBeforeProxy extends BeforeProxy{ @Override public void before(Object target, Method method, Object[] arguments) { System.out.println("before hello"); } }
//自己后置增强 package com.lin.AOP1; import java.lang.reflect.Method; import java.util.ArrayList; public class MyAfterProxy extends AfterProxy { @Override public void after(Object target, Method method, Object[] arguments) { System.out.println("after Hello"); } }
接下来就到了我们激动人心的时候来看看我们写的是否正确
package com.lin.AOP1; import java.util.ArrayList; import java.util.List; public class test { public static void main(String[] args){ JDKProxyBeanFactory jdkProxyBeanFactory = new JDKProxyBeanFactory(); HelloImp helloImp = new HelloImp(); List<Proxy> list = new ArrayList<>(); list.add(new MyAfterProxy()); list.add(new MyBeforeProxy()); //模拟spring自动注入功能 jdkProxyBeanFactory.setProxyList(list); jdkProxyBeanFactory.setTarget(helloImp); jdkProxyBeanFactory.setIntefaces(new Class[]{Hello.class}); Hello hello =(Hello) jdkProxyBeanFactory.getRealProxy(); hello.say(); } }
运行后悔得到如下结果
before hello
hello
after Hello
完全正确 有木有!
当然了该方法也有一定的缺陷就是会对所有的方法都会拦截 但对你理解springAOP源码会有很大的帮助应为spring中处理
AOP中链式处理技术的对象缩小了 是对方法进行处理,观看过spring源码的一定会知道spring中有个对象有(MethodInvocation)proceed() 方法 这正是使用了链式处理技术 最后希望本文能够帮助到你,看过的朋友希望能点个赞。