Java手写实现AOP

什么是AOP?

当然AOP的概念网上一查一大堆,我就不在这贴概念了,大家可以自己看看,在这我就说说自己理解的AOP。
AOP(Aspect Oriented Programming)面向切面编程,即在不影响原有功能的情况下,进行的一次横向扩展。
面向切面和横向扩展我们可以这么理解:有一个分装好的类,我们需要在类的方法执行前后插入额外的代码,要求是不破坏原始类,一种方法是我们可以去继承这个类每个方法前面去增强,但是若是多个方法,每个方法前都去写同样的增强代码不符合我们程序人的身份,所以我们使用AOP的方法,将方法(切入点)和通知(增强功能)组成一个切面再去加入这个对象(使用代理)。

代理,大家可以看看博主另一篇关于代理

模拟AOP代码思路

在这里插入图片描述
思路如下:

  • 抽象类: Interceptor 这个类中的两个成员,决定了该拦截器是拦截哪个类的哪个方法的。给出三种拦截的抽象方法。
  • 类: InterceptorAdpter 这个类继承了上面的抽象方法,给出默认拦截处理,以后由工具使用者来决定要覆盖哪种方法。
  • 类:Proxy 这个类负责将代理对象,原对象,还有他自己的拦截器链联系起来。我这里实现的AOP较粗糙,每个代理对象拥有一套自己的拦截器链。对拦截器的增加和删除也在这其中完成。
  • 类:ProxyFactory 这个类主要是用来生成代理对象(JDK和CGLIB方式)。
  • 类:FactoryProxyBean 这个类用来将类名和Proxy联系起来,以及处理其中拦截链的关系。

具体代码

  • 拦截器抽象方法 Interceptor
package MyIntrceptor;

import java.lang.reflect.Method;

/**
 * @author quan
 * @create 2020-06-22 10:18
 */
public abstract class Interceptor {
    private Class<?> klass;
    private Method method;

    public Interceptor() {
    }

    public Interceptor(Class<?> klass, Method method) {
        this.klass = klass;
        this.method = method;
    }

    public Class<?> getKlass() {
        return klass;
    }

    public void setKlass(Class<?> klass) {
        this.klass = klass;
    }

    public Method getMethod() {
        return method;
    }

    public void setMethod(Method method) {
        this.method = method;
    }

    public abstract boolean before(Object[] args);
    public abstract Object after(Object result);
    public abstract void dealException(Throwable th);

}
  • Proxy
package MyProxy;

import MyException.InterceptorAlReadyExistException;
import MyIntrceptor.Interceptor;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * 装着原对象 代理对象 以及拦截器链
 * @author quan
 * @create 2020-06-22 10:26
 */
public class Proxy {
    private Object proxy;
    private Object object;
    private List<Interceptor> interceptorList;

    public Proxy() {
        interceptorList = new ArrayList<>();
    }

    public Object getProxy() {
        return proxy;
    }

    public void setProxy(Object proxy) {
        this.proxy = proxy;
    }

    public Object getObject() {
        return object;
    }

    public void setObject(Object object) {
        this.object = object;
    }

    public List<Interceptor> getInterceptorList() {
        return interceptorList;
    }

    public void setInterceptorList(List<Interceptor> interceptorList) {
        this.interceptorList = interceptorList;
    }

    //前置拦截
    public boolean doBefore(Method method, Object[] args) {
        for (Interceptor interceptor : interceptorList) {
            if (!interceptor.getMethod().equals(method)) {
                continue;
            }
            if (!interceptor.before(args)) {
                return false;
            }
        }
        return true;
    }

    //后置拦截
    public Object doAfter(Method method, Object result) {
        for (int i = interceptorList.size()-1; i >= 0; i--) {
            Interceptor interceptor = interceptorList.get(i);
            if (!interceptor.getMethod().equals(method)) {
                continue;
            }
            result = interceptor.after(result);
        }
        return result;
    }

    //异常拦截
    public void doException(Method method, Throwable th) throws Throwable {
        for (Interceptor interceptor : interceptorList) {
            if (!interceptor.getMethod().equals(method)) {
                continue;
            }
            interceptor.dealException(th);
            throw th;
        }
    }

    // 当该类拦截器存在时无法添加新拦截器
    // 这里会抛出一个自定义异常
    public void addInterceptor(Interceptor interceptor) throws InterceptorAlReadyExistException {
        String interceptorName = interceptor.getClass().getName();
        if (interceptorList.contains(interceptor)) {
            throw new InterceptorAlReadyExistException("拦截器" + interceptorName +"已存在");
        }
        interceptorList.add(interceptor);
    }

    // 移除拦截器
    public void removeInterceptor(Interceptor interceptor) {
        if (!interceptorList.contains(interceptor)) {
            return;
        }
        interceptorList.remove(interceptor);
    }
}
  • ProxyFactory 重点类,真正实现面的织入
package MyProxy;

import MyIntrceptor.Interceptor;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
* 用JDKProxy和Cglib两种方式生成
* @author quan
* @create 2020-06-22 10:51
*/
public class ProxyFactory {
   private Proxy myProxy;

   public Proxy getMyProxy() {
       return myProxy;
   }

   public void setMyProxy(Proxy myProxy) {
       this.myProxy = myProxy;
   }

   public <T> T getCglibProxy(Class<?> klass, Object object) {
       myProxy = new Proxy();
       Object proxy = cglibProxy(myProxy, klass, object);
       myProxy.setProxy(proxy);
       myProxy.setObject(object);
       return (T) proxy;

   }

   private <T> T cglibProxy(Proxy myProxy, Class<?> klass, Object object) {
       Enhancer enhancer = new Enhancer();
       enhancer.setSuperclass(klass);
       enhancer.setCallback(new MethodInterceptor() {
           @Override
           public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
               return doInvoker(myProxy, object, method, objects);
           }
       });
       return (T) enhancer.create();
   }

   public <T> T getJdkKProxy(Class<?> klass, Object object) {
       myProxy = new Proxy();
       Object proxy = JdkProxy(myProxy, klass, object);
       myProxy.setProxy(proxy);
       myProxy.setObject(object);
       return (T) proxy;

   }

   private <T> T JdkProxy(Proxy myProxy, Class<?> klass, Object object) {
      ClassLoader classLoader = klass.getClassLoader();
      Class<?>[] interfaces = klass.getInterfaces();

      return (T) java.lang.reflect.Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {
          @Override
          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
              return doInvoker(myProxy, object, method, args);
          }
      });
   }

   private <T> T doInvoker(Proxy proxy, Object object, Method method, Object[] args) throws Throwable {
       Object result = null;

       boolean b = proxy.doBefore(method, args);
       if (!b) return null;
       try {
           result = method.invoke(object, args);
           result = proxy.doAfter(method, result);
       } catch (Throwable th) {
           proxy.doException(method, th);
       }
       return (T) result;
   }
   
  • FactoryProxyBean
package MyProxy;

import MyException.InterceptorAlReadyExistException;
import MyIntrceptor.Interceptor;

import java.util.HashMap;
import java.util.Map;

/**
 * @author quan
 * @create 2020-06-22 10:46
 */
public class FactoryProxyBean {
    /**
     * 用来存放名字和类的映射关系
     */
    private static final Map<String, Proxy> beanMap = new HashMap<>();


    public FactoryProxyBean() {
    }

    public <T> T creatCglibProxy(Object object) {
        Object proxy = cglibProxy(object.getClass(), object);
        return (T) proxy;
    }

    public <T> T creatCglibProxy(Class<?> klass) throws InstantiationException, IllegalAccessException {
        Object proxy = cglibProxy(klass, klass.newInstance());
        return (T) proxy;
    }

    public <T> T creatJdkProxy(Class<?> klass) throws InstantiationException, IllegalAccessException {
        Object proxy = jdkProxy(klass, klass.newInstance());
        return (T) proxy;
    }

    public <T> T creatJdkProxy(Object object) {
        Object proxy = jdkProxy(object.getClass(), object);
        return (T) proxy;
    }

    private <T> T jdkProxy(Class<?> klass, Object o) {
        String klassName = klass.getName();
        Proxy proxy = beanMap.get(klassName);
        if (proxy != null) {
            return (T) proxy.getProxy();
        }
        ProxyFactory proxyFactory = new ProxyFactory();
        T jdkKProxy = proxyFactory.getJdkKProxy(klass, o);
        proxy = proxyFactory.getMyProxy();
        beanMap.put(klassName, proxy);
        return jdkKProxy;
    }

    private <T> T cglibProxy(Class<?> klass, Object o) {
        String klassName = klass.getName();
        Proxy proxy = beanMap.get(klassName);
        if (proxy != null) {
            return (T) proxy.getProxy();
        }
        ProxyFactory proxyFactory = new ProxyFactory();
        T cglibProxy = proxyFactory.getCglibProxy(klass, o);
        proxy = proxyFactory.getMyProxy();
        beanMap.put(klassName, proxy);
        return cglibProxy;
    }

    // 这里是面向使用者
    // 对某类添加拦截器
    public void addInterceptor(Class<?> klass, Interceptor interceptor) throws  InterceptorAlReadyExistException {
        if (!interceptor.getKlass().equals(klass)) {
            return;
        }
        beanMap.get(klass.getName()).addInterceptor(interceptor);
    }

    public void removeInterceptor(Class<?> klass, Interceptor interceptor) {
        if (!interceptor.getKlass().equals(klass)) {
            return;
        }
        beanMap.get(klass.getName()).removeInterceptor(interceptor);
    }
}

以上就是AOP面向切面编程的思想,其实本质上还是代理模式和反射机制,在不破坏这个类代码的同时对这个类进行横向扩展(例如拦截或添加日志的操作),实现了松耦合!
当然我这个是简单版的AOP,仅仅为了阐述其内部基本原理,但AOP思想就是这么回事。

最后来做个测试:

package test;

import MyException.InterceptorAlReadyExistException;
import MyProxy.FactoryProxyBean;

import java.lang.reflect.Method;
import java.util.concurrent.CountDownLatch;

/**
 * @author quan
 * @create 2020-06-22 11:35
 */
public class Test implements Runnable {
    private static CountDownLatch countDownLatch = new CountDownLatch(10);


    private int a;
    private int b;

    public Test(int a, int b) {
        this.a = a;
        this.b = b;
    }

    public static void main(String[] args) throws NoSuchMethodException, InterceptorAlReadyExistException, InterruptedException {
        for (int i = 1; i <= 10; i++) {
            Test test = new Test(50, i);
            Thread thread = new Thread(test);
            thread.start();
        }
        countDownLatch.await();
        System.out.println("allfinished");
    }

    @Override
    public void run() {
        Class<?> klass = TsetObject.class;
        Method method = null;
        try {
            method = klass.getDeclaredMethod("div", new Class<?>[]{Integer.class, Integer.class});
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        TestInterceptor testInterceptor = new TestInterceptor(klass, method);

        FactoryProxyBean factoryProxyBean = new FactoryProxyBean();
        try {
            TsetObject o = factoryProxyBean.creatCglibProxy(klass);
            factoryProxyBean.addInterceptor(klass, testInterceptor);

            Integer div = o.div(a, b);
            System.out.println(div);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InterceptorAlReadyExistException e) {
            e.printStackTrace();
        }

        countDownLatch.countDown();
    }
}

测试的类:

package test;

import MyIntrceptor.InterceptorAdpter;

import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * @author quan
 * @create 2020-06-22 11:38
 */
public class TestInterceptor extends InterceptorAdpter{

    public TestInterceptor(Class<?> klass, Method method) {
        super(klass, method);
    }

    @Override
    public boolean before(Object[] args) {
        System.out.println("日志信息:before");
        System.out.println("拦截到的方法参数是:" + Arrays.toString(args));
        return true;
    }

    @Override
    public Object after(Object result) {
        System.out.println("日志信息:after");
        return result;
    }

    @Override
    public void dealException(Throwable th) {
        System.out.println("日志信息:exception // " + th.getCause());
    }
}
package test;

/**
 * @author quan
 * @create 2020-06-22 11:38
 */
public class TsetObject {
    public Integer div(Integer a, Integer b) {
        return a/b;
    }
}

结果展示
在这里插入图片描述
图太长没贴完。

猜你喜欢

转载自blog.csdn.net/baidu_41922630/article/details/106899705