Spring AOP实现原理笔记(一) -- 简单介绍

一、动态代理技术

JDK动态代理只能对实现了接口的类生成代理,而不能针对类

CGLIB是针对类实现代理,利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理,覆盖其中的方法(继承)

1. JDK动态代理

定义一个接口及其实现类

public interface UserService {
    void add();
}
public class UserServiceImpl implements UserService {
    @Override
    public void add() {
        System.out.println("--------add--------");
    }
}

实现JDK提供的InvocationHandler

public class MyInvocationHandler implements InvocationHandler {
    private Object target;
    public MyInvocationHandler(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("------before------");
        Object result = method.invoke(target, args);
        System.out.println("------after------");
        return result;
    }
    public Object getProxy() {
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                target.getClass().getInterfaces(), this);
    }
}

测试代码:

@Test
public void proxyTest() {
    UserService userService = new UserServiceImpl();
    MyInvocationHandler handler = new MyInvocationHandler(userService);
    UserService proxy = (UserService) handler.getProxy();
    proxy.add();
}

输出

------before------
--------add--------
------after------

2. CGLib动态代理

例子如下:

public class EnhancerDemo {
  public static void main(String... args){
      Enhancer enhancer = new Enhancer();
      enhancer.setSuperclass(EnhancerDemo.class);
      enhancer.setCallback(new MethodInterceptorImpl());
      EnhancerDemo proxy = (EnhancerDemo) enhancer.create();
      proxy.test();
      System.out.println(proxy);
  }
  public void test(){
      System.out.println("hello world");
  }
  static class MethodInterceptorImpl implements MethodInterceptor{
      @Override
      public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy)
              throws Throwable {
          System.out.println("----before invoke"+method);
          Object result = methodProxy.invokeSuper(o, args);
          System.out.println("****after invoke"+method);
          return result;
      }
  }
}

输出:

----before invoke public void com.season.aop.EnhancerDemo.test()
hello world
****after invoke public void com.season.aop.EnhancerDemo.test()
----before invoke public java.lang.String java.lang.Object.toString()
----before invoke public native int java.lang.Object.hashCode()
****after invoke public native int java.lang.Object.hashCode()
****after invoke public java.lang.String java.lang.Object.toString()
com.season.aop.EnhancerDemo$$EnhancerByCGLIB$$b010a475@18e6db6
public interface Monitorable {
    void setMonitorActive(boolean active);
}

建一个类实现该接口并继承DelegatingIntroductionInterceptor

public class MonitorInterceptor extends DelegatingIntroductionInterceptor implements Monitorable {
    ThreadLocal<Boolean> active = new ThreadLocal<>();
    @Override
    public void setMonitorActive(boolean active) {
        this.active.set(active);
    }
    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        Object result;
        if (active.get() != null && active.get()) {
            System.out.println("开始计时");
            long start = System.currentTimeMillis();
            result = super.invoke(mi);
            System.out.println("计时结束,耗时:"+(System.currentTimeMillis()-start)+"ms");
        } else
            result = super.invoke(mi);
        return result;
    }
}

这个类做的事情是,当active中的值为true时会在调用方法的时候进行计时统计

再建一个类模拟操作

    public class MonitorService {
        public void run(){
            try {
                System.out.println("执行MonitorService - run方法");
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

在配置文件beans.xml中加上配置

<bean id="monitorService" class="com.season.aop.MonitorService"/>
<bean id="pMonitor" class="com.season.aop.MonitorInterceptor"/>
<bean id="myTestBeanProxy" class="org.springframework.aop.framework.ProxyFactoryBean"
      p:interceptorNames="pMonitor"
      p:proxyTargetClass="true"
      p:target-ref="monitorService"
      p:interfaces="com.season.aop.Monitorable"
/>

由于只能通过为目标类创建子类的方式生成引介增强的代理,所以必须把proxyTargetClass设置为true

测试代码

@Test
   public void introduceInterceptorTest() {
       ApplicationContext actx = new ClassPathXmlApplicationContext("beans.xml");
       MonitorService bean = (MonitorService) actx.getBean("myTestBeanProxy");
       bean.run();
       ((Monitorable)bean).setMonitorActive(true);
       bean.run();
   }

输出:

执行MonitorService - run方法
开始计时
执行MonitorService - run方法
计时结束,耗时:2000ms

三、定义一个切面

@Aspect
public class MyAspect {
    @Pointcut(value = "execution(* *.test(..))")
    public void test(){}
    @Before("test()")
    public void beforeTest(){
        System.out.println("test before");
    }
    @After("test()")
    public void afterTest(){
        System.out.println("test after");
    }
}

在beans.xml文件中加上

    <aop:aspectj-autoproxy/>
    <bean id="myAspect" class="com.season.MyAspect"/>

测试代码

@Test
public void aspectTest() {
    ApplicationContext actx = new ClassPathXmlApplicationContext("beans.xml");
    MyTestBean bean = (MyTestBean) actx.getBean("myTestBean");
    bean.test();
}

输出:

test before
Hello world
test after
    原文作者:AOP
    原文地址: https://blog.csdn.net/seasonLai/article/details/82705074
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞