实现简单的Aop

使用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就不会再显得懊恼了。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值