• Spring AOP:Java动态代理和CGlib


    JDK动态代理设计模式

    核心类:InvocationHandlerProxy。只能代理接口。

    Java动态代理核心代码

    /**
     * Java动态代理
     *
     * @Author YangXuyue
     * @Date 2018/09/17 23:46
     */
    public class MyInvocationHandler implements InvocationHandler {
    
        /**
         * 执行方法的对象实例
         */
        private Object target;
    
        public MyInvocationHandler(Object target) {
            this.target = target;
        }
        
        // proxy是最终生成的代理类,一般不会用到
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            long start = System.currentTimeMillis();
    
            Object object = method.invoke(target, args);
    
            System.out.println("方法:" + method.getName() + "执行了:" + (System.currentTimeMillis() - start) + " ms");
    
            return object;
        }
    
        // 获取代理实例
        public static Object proxy(Object target) {
            return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                    target.getClass().getInterfaces(), new MyInvocationHandler(target));
        }
    }

    测试

            Waiter waiter = new NaiveWaiter();
            Waiter proxy = (Waiter) MyInvocationHandler.proxy(waiter);
            // 在执行以下方法的时候,这些方法都已经被增强了!
            proxy.sayHello("yangxuyue");
            proxy.sayBye("yangxuyue");

    在动态代理的invoke方法里边,在原有方法的调用前后“织入”了我们的代码。其实这就是AOP中横切的过程,代理对象中在方法调用前后“植入”自己写的通用代码其实就是AOP中织入的过程!这个织入的代码也就是横切逻辑,织入代码的过程其实就是在原有的方法前后增强原方法的过程!这种技术手段就是AOP

    CGLib

    CGLib采用底层的字节码技术,可以为一个类创建子类,在子类中采用方法拦截的技术拦截所有父类方法的调用并顺势的织入横切逻辑。

    pom.xml

            <dependency>
                <groupId>cglib</groupId>
                <artifactId>cglib</artifactId>
                <version>3.2.8</version>
            </dependency>

    核心类

    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    public class CglibProxy implements MethodInterceptor {
        private Enhancer enhancer = new Enhancer();
    
        public Object getProxy(Class clazz) {
            enhancer.setSuperclass(clazz);
            enhancer.setCallback(this);
            return enhancer.create();
        }
    
        // object:目标类的实例 method:目标类方法的反射对象 args:方法的动态参数 proxy:代理类实例
        // intercept(Object, Method, Object[], MethodProxy) 拦截所有目标类的调用
        @Override
        public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            long start = System.currentTimeMillis();
    
            Object result = proxy.invokeSuper(object, args);
    
            System.out.println(result);
    
            System.out.println("方法:" + method.getName() + "执行了:" + (System.currentTimeMillis() - start) + " ms");
    
            return object;
        }
    }

    测试

            CglibProxy proxy = new CglibProxy();
            VoiceBean bean = (VoiceBean) proxy.getProxy(VoiceBean.class);
            bean.saySomething();

    代理类的类名字

     VoiceBean$$EnhancerByCGLIB$$a8907e36
  • 相关阅读:
    03-Spring默认标签解析
    想要写出好味道的代码,你需要养成这些好习惯!
    IDEA 缺少Springboot启动图标 如何添加
    echarts的canvas大小
    JS控制div上下滚动内容
    2020新的一年开始了
    2019年第一个工作日!
    关于.net项目前后端分离框架(一)
    MongoDB学习一:安装及简单使用
    spring默认标签与自定义标签学习
  • 原文地址:https://www.cnblogs.com/yang21/p/9970199.html
Copyright © 2020-2023  润新知