• jdk和cglib动态代理



    代码: https://gitee.com/xuhx615/AOPDemo.git

    🍓动态代理的作用

    增强或拦截方法的调用

    🍓切点方法

    public interface Point {
    
        /**
         * 代理方法前调用
         * @param args 代理方法的参数
         * @return true放行;false拦截
         */
        boolean before(Object[] args);
    
        /**
         * 代理方法后调用
         * @param result 代理方法返回值
         * @param e 代理方法抛出的异常
         * @param args 代理方法的参数
         */
        void after(Object result, Exception e,Object[] args);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    🍓jdk动态代理代理类(核心)

    import cn.com.jdk.point.Point;
    import org.springframework.util.CollectionUtils;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    import java.util.List;
    
    public class ActiveProxy implements InvocationHandler {
    
        /**
         * 切点
         */
        private Point point;
    
        /**
         * 代理对象
         */
        private Object obj;
    
        /**
         * 需要增强的方法
         */
        private List<String> enhanceMethodList;
    
        /**
         * 是否全部增强
         */
        private boolean isAllEnhance = true;
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            Object result = null;
            Exception exception = null;
            /**
             * 判断
             * 是否全部增强
             * 如果不是全部增强,增强方法是否属于指定的方法
             */
            if (isAllEnhance || (!isAllEnhance && !CollectionUtils.isEmpty(enhanceMethodList)
                    && enhanceMethodList.contains(method.getName()))) {
                boolean flag = point.before(args);
                if(flag){
                    try {
                        result = method.invoke(obj, args);
                    } catch (Exception e) {
                        e.printStackTrace();
                        exception = e;
                    }
                    point.after(result, exception, args);
                }
            }else{
                result = method.invoke(obj, args);
            }
            return result;
        }
    
    	/**
         * 创建代理对象
         * @param clazz 代理对象的接口类clazz
         * @param obj 代理对象实例
         * @param point 切点实例
         * @param 
         * @return
         */
        public <T> T createObj(Class<T> clazz,T obj,Point point){
            this.obj = obj;
            this.point = point;
            T t = (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, this);
            return t;
        }
    
        public <T> T createObj(Class<T> clazz,T obj,Point point,boolean isAllEnhance,List<String> enhanceMethodList){
            this.isAllEnhance = isAllEnhance;
            this.enhanceMethodList = enhanceMethodList;
            return createObj(clazz,obj,point);
        }
    }
    
    • 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

    🍓cglib动态代理代理类(核心)

    import cn.com.cglib.point.Point;
    import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;
    import org.springframework.util.CollectionUtils;
    import java.lang.reflect.Method;
    import java.util.List;
    
    public class ProxyMethodInterceptor implements MethodInterceptor {
    
        private Point point;
    
        private Object obj;
    
        private List<String> enhanceMethodList;
    
        private boolean isAllEnhance = true;
    
        @Override
        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
            Object result = null;
            Exception exception = null;
            if (isAllEnhance || (!isAllEnhance && !CollectionUtils.isEmpty(enhanceMethodList) && enhanceMethodList.contains(method.getName()))) {
                boolean flag = point.before(objects);
                if(flag){
                    try {
                        result = methodProxy.invoke(obj, objects);
                    } catch (Exception e) {
                        exception = e;
                    }
                    point.after(result,exception, objects);
                }
            }else{
                result = methodProxy.invoke(obj, objects);
            }
            return result;
        }
    
        public <T> T createObj(T obj,Point point){
            this.point = point;
            this.obj = obj;
            Enhancer enhancer = new Enhancer();
            enhancer.setSuperclass(obj.getClass());
            enhancer.setCallback(this);
            T t = (T) enhancer.create();
            return t;
        }
    
        public <T> T createObj(T obj,Point point,boolean isAllEnhance,List<String> enhanceMethodList){
            this.isAllEnhance = isAllEnhance;
            this.enhanceMethodList = enhanceMethodList;
            return createObj(obj,point);
        }
    }
    
    • 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

    🍓jdk动态代理与cglib动态代理的区别

    🍒表面区别

    1. jdk动态代理代理类实现的是java.lang.reflect.InvocationHandlercglib动态代理代理类实现的是org.springframework.cglib.proxy.MethodInterceptor
    2. jdk动态代理代理类使用的核心类是java.lang.reflect.Proxycglib动态代理使用的核心类是org.springframework.cglib.proxy.MethodProxy
    3. jdk动态代理代理对象必须有对应的接口和实现类,cglib动态代理代理对象则是针对类,不需要有对应的接口。

    🍒理论区别

    1. JDK动态代理是实现了被代理对象的接口,Cglib是继承了被代理对象。
    2. JDKCglib都是在运行期生成字节码,JDK是直接写Class字节码,Cglib使用ASM框架写Class字节码,Cglib代理实现更复杂,生成代理类比JDK效率低。
    3. JDK调用代理方法,是通过反射机制调用,Cglib是通过FastClass机制直接调用方法,Cglib执行效率更高。

    🍓Hutool动态代理

    增强类:

    import cn.hutool.aop.aspects.SimpleAspect;
    import java.lang.reflect.Method;
    
    public class TargetAspect extends SimpleAspect {
    
        @Override
        public boolean before(Object target, Method method, Object[] args) {
            System.out.println("before");
            return true;
        }
    
        @Override
        public boolean after(Object target, Method method, Object[] args, Object returnVal) {
            System.out.println("after");
            return super.after(target, method, args, returnVal);
        }
    
        @Override
        public boolean afterException(Object target, Method method, Object[] args, Throwable e) {
            System.out.println("afterException");
            return super.afterException(target, method, args, e);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    调用:

    import cn.hutool.aop.ProxyUtil;
    
    	TargetDemo proxy = ProxyUtil.proxy(new TargetDemoImpl(), new TargetAspect());
    	proxy.eat("鱼");
    
    • 1
    • 2
    • 3
    • 4

    注意: 如果项目中没有引入cglib依赖,那么ProxyUtil.proxy的返回值类型必须是代理类的接口类型,因为他走的是jdk动态代理

    🍓Spring AOP

    Spring AOP的底层实现是cglib动态代理。
    Spring AOP请点击该博客浏览:https://blog.csdn.net/qq_34191426/article/details/125223508

  • 相关阅读:
    字节面试也会问SPI机制?
    「我在淘天做技术」音视频技术及其在淘宝内容业务中的应用
    八、性能测试之磁盘分析
    【漏洞复现】​金和OA存在任意文件读取漏洞
    文件夹内文件删除如何恢复?分享四种方法,快收藏保存起来
    【Apipost】常用预(后)执行脚本方法
    MySQL:增量备份和恢复(5)
    关于初次new springboot项目
    java和python刷题的一些语法规则总结(未完成)
    【Promise】黑马vue视频笔记(十一)
  • 原文地址:https://blog.csdn.net/qq_34191426/article/details/126346774