使用jdk的动态代理
创建Custom接口和实现类
public interface Custom {
public void NeedApple();
public void NeedPen();
}
public class CustomImpl implements Custom {
@Override
public void NeedApple() {
System.out.println("我需要苹果");
}
@Override
public void NeedPen() {
System.out.println("我需要钢笔");
}
}
创建通知接口和是实现类
public interface DoSomething {
public void before();
public void after();
}
public class DoSomethingImpl implements DoSomething {
@Override
public void before() {
System.out.println("...before...");
}
@Override
public void after() {
System.out.println("...after...");
}
}
创建代理类
import TestSimpleAop.NeedToProxyed.CustomImpl;
import TestSimpleAop.ProxyClass.DoSomethingImpl;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ExcuteProxy implements InvocationHandler {
CustomImpl custom;//需要在这里讲类导入进来,一边下面的invoke的方法里使用。
DoSomethingImpl doSomething;
//相当于这里实现了注入的方法
public Object getProxy(CustomImpl custom,DoSomethingImpl doSomething){
this.custom = custom;
this.doSomething = doSomething;
return Proxy.newProxyInstance(this.custom.getClass().getClassLoader(),
this.custom.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//通过反射机制来得到方法
Class clazz = this.doSomething.getClass();
//这里的class..参数需要协商newClass{},但是在{}里不写任何的东西,不然会出错
//之前在这里写上了Method.class经过调试发现在源码的
//public final class Class<T> implements java.io.Serializable,
// GenericDeclaration,
// Type,
// AnnotatedElement
//这个类中的private static boolean arrayContentsEq(Object[] a1, Object[] a2)方法中
//回去判断a1.length != a2.length 如果在newClass{}里添加东西会导致其判断为正确而返回
//false而报错
Method beforemethod = clazz.getDeclaredMethod("before",new Class[]{});
//这里的第二个参数也是不要写成this.doSomething.getclass(),这样也会出错,写成args
beforemethod.invoke(this.doSomething,args);
Object obj = method.invoke(this.custom,args);
Method aftermethod = clazz.getDeclaredMethod("after",new Class[]{});
aftermethod.invoke(this.doSomething,args);
return obj;
}
}
编写testRun类
public class TestRun {
public static void main(String[] args) {
ExcuteProxy ep = new ExcuteProxy();
//将其返回给Custom的接口
Custom custom = (Custom) ep.getProxy(new CustomImpl(),new DoSomethingImpl());
custom.NeedApple();
}
}
参考的连接
参考链接中的关于自动的实现aop那一块有错误,本文已经给与纠正。
总结
通过这种方法可以进一步的理解Spring对aop的实现。在Spring中是由一条拦截链来实现对于各种前置后置、Exception、huanrao或者是returnafter。在完成了拦截链的创建之后就会去执行链中的每一个拦截器。在执行拦截器的时候很像上面的执行过程。不过不一样的地方是在Spring中不需要在代理类中写死被代理对象和通知对象。Spring在创建aop的时候使用了代理对象,先不管是jdk的还是cglib的。总之在执行真正的方法比如 custom.NeedApple();的时候,执行的就不是我们定义的Custom的NeedApple()方法了。通过对其代理对象的class的查看可以知道在其代理对象的NeedApple()方法中其实已经将我们设计的模式写进去了。比如我们需要在方法的前后放置方法来实现各种功能,那么再其代理对象的class的方法中就已经写好了,只不过这个过程是被掩盖的。所以在ExcuteProxy 类中的invoke方法其实就是代理对象中的NeedApple()的这个是模样。所以当在testRun类中执行方法custom.NeedApple();的时候不要去看原本的Custom类中的方法。需要去查看其代理对象中的方法。这样就一目了然。所以可以说这个其实是对原本的类中的方法进行了改写。所以如果原本的方法中的修饰符为final那么使用cglib就会出问题,因为cglib其实是使用类的子类来实现代理的。而Spring拿取通知(advice)和被代理对象都应该是在ico的容器里拿取。所以aop其实是对ioc容器里的bean的二次代理。知道了底层的原理,再看Spring的aop就不会再显得懊恼了。