zoukankan      html  css  js  c++  java
  • 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);

      }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      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 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 getInterceptorList() {

      return interceptorList;

      }

      public void setInterceptorList(List 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);

      }

      }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      61

      62

      63

      64

      65

      66

      67

      68

      69

      70

      71

      72

      73

      74

      75

      76

      77

      78

      79

      80

      81

      82

      83

      84

      85

      86

      87

      88

      89

      90

      91

      92

      93

      94

      95

      96

      97

      98

      99

      100

      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 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 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 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 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 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;

      }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      61

      62

      63

      64

      65

      66

      67

      68

      69

      70

      71

      72

      73

      74

      75

      76

      77

      78

      79

      80

      81

      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 creatCglibProxy(Object object) {

      Object proxy = cglibProxy(object.getClass(), object);

      return (T) proxy;

      }

      public T creatCglibProxy(Class klass) throws InstantiationException, IllegalAccessException {

      Object proxy = cglibProxy(klass, klass.newInstance());

      return (T) proxy;

      }

      public T creatJdkProxy(Class klass) throws InstantiationException, IllegalAccessException {

      Object proxy = jdkProxy(klass, klass.newInstance());

      return (T) proxy;

      }

      public T creatJdkProxy(Object object) {

      Object proxy = jdkProxy(object.getClass(), object);

      return (T) proxy;

      }

      private 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 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);

      }

      }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      61

      62

      63

      64

      65

      66

      67

      68

      69

      70

      71

      72

      73

      74

      75

      76

      77

      78

      79

      80

      81

      82

      83

      84

      以上就是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;

      }郑州妇科医院哪家好:http://www.zztjfk.com/郑州看妇科哪家医院好:http://www.zztjfk.com/郑州哪里的妇科医院好:http://www.zztjfk.com/

      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();

      }

      }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      61

      62

      63

      测试的类:

      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());

      }

      }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      package test;

      /**

      * @author quan

      * @create 2020-06-22 11:38

      */

      public class TsetObject {

      public Integer div(Integer a, Integer b) {

      return a/b;

      }

      }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      结果展示

      图太长没贴完。

  • 相关阅读:
    关于数据库,程序员应该了解的那些事
    Kafka实战宝典:如何跨机房传输数据
    数据挖掘从入门到放弃(三):朴素贝叶斯
    面试官:数据库自增ID用完了会怎么样?
    《我想进大厂》之网络篇夺命连环12问
    面试官:缓存一致性问题怎么解决?
    空指针的传说
    淘宝|蚂蚁|菜鸟|盒马|嘀嘀|饿了么面经(已拿多个offer)
    苦修月余,斩获bigo、腾讯offer,面经奉上!
    《我想进大厂》之Spring夺命连环10问
  • 原文地址:https://www.cnblogs.com/sushine1/p/13187893.html
Copyright © 2011-2022 走看看