目录
    • 1、jdk代理
    • 2、cglib代理
    • 3、jdk代理与cglib代理对比

    一、反射

    概念:在运行状态中,对于任意的一个类,都能够知道这个类的所有字段和方法,对任意一个对象都能够通过反射机制调用一个类的任意方法

    实现方法:jvm在第一次加载某个类时会生成一个class对象,里面记录了这个类的信息

    链接:类加载机制(留坑)

    二、动态代理

    动态代理的作用:在不改变原代码的基础上增加新的功能,如日志、权限检验等

    反射在动态代理中的应用:由于知道原类的字段、方法等信息,才可以通过代理类执行被代理类的方法

    动态代理的实现有两种

    1、jdk代理

    实现方法:通过创建一个代理类,这个代理类继承于一个proxy类,proxy类中有一个invocationhandler接口,这个接口持有被代理对象和一个invoke()方法。创建好代理类对象后,对该对象调用的方法都会交由invoke方法处理。invoke方法接受3个参数:代理对象、方法、参数列表。重写invoke方法便可以在原方法的基础上添加其他逻辑

    一个jdk代理的简单实现:

    import java.lang.reflect.invocationhandler;
    import java.lang.reflect.method;
    import java.lang.reflect.proxy;
    // 定义一个接口
    interface myinterface {
        void fun();
    }
    // 用一个类去实现这个接口
    class person implements myinterface {
        @override
        public void fun() {
            system.out.println("person实现接口方法");
        }
    }
    // 用一个类实现invocationhandler接口
    class myinvocationhandler<t> implements invocationhandler {
        //invocationhandler持有的被代理对象
        t target;
        public myinvocationhandler(t target) {
            this.target = target;
        }
        /**
         * proxy:代表动态代理对象
         * method:代表正在执行的方法
         * args:代表调用目标方法时传入的实参
         */
        @override
        public object invoke(object proxy, method method, object[] args) throws throwable {
            system.out.println("代理执行" + method.getname() + "方法"); // 在原方法的基础上添加其他逻辑
            object result = method.invoke(target, args); // 通过invoke方法调用原方法
            return result;
        }
    }
    public class main {
        public static void main(string[] args) {
            person person = new person();
            invocationhandler invocationhandler = new myinvocationhandler<>(person);
            myinterface proxy = (myinterface) proxy.newproxyinstance(person.class.getclassloader(),
                    person.class.getinterfaces(), invocationhandler);
            proxy.fun();
        }
    }

    输出结果:

    代理执行fun方法
    person实现接口方法

    缺陷:只能代理接口方法,因为jdk代理需要继承一个proxy类,又由于java的单继承机制,导致代理类无法继承父类的函数,只能实现接口

    2、cglib代理

    原理与jdk代理类似,区别在于cglib代理创建的代理类直接继承于被代理类,所以可以实现被代理类的方法而非仅仅接口方法

    一个简单的cglib代理实现:

    public class main {
        public static void main(string[] args) {
            enhancer enhancer = new enhancer();
            enhancer.setsuperclass(car.class);
            enhancer.setcallback(new methodinterceptor() {
                @override
                public object intercept(object obj, method method, object[] args, methodproxy methodproxy)
                        throws throwable {
                    system.out.println("before");
                    object res = methodproxy.invokesuper(obj, args);
                    system.out.println("after");
                    return res;
                }
            });
            car car = (car) enhancer.create();
            car.print();
        }
    }
    class car {
        void print() {
            system.out.println("执行原方法");
        }
    }

    由于cglib并非jdk自带,所以需要通过maven引入一个依赖

    <dependency>
        <groupid>org.sonatype.sisu.inject</groupid>
        <artifactid>cglib</artifactid>
        <version>3.1.1</version>
    </dependency>

    输出结果:

    before
    执行原方法
    after

    3、jdk代理与cglib代理对比

    1、jdk代理只能实现接口方法,而cglib代理既可以实现接口方法也可以实现类中自带的方法

    2、性能上,在jdk1.8,cglib3.1.1的环境上,每次创建一个代理类并执行同样的方法

    当执行10000次,jdk代理用时85ms,而cglib代理用时190ms,明显jdk代理性能更佳;

    当执行1000000(一百万)次时,两种代理耗时几乎相等;

    当执行10000000次时,cglib代理已经优于jdk代理。

    所以在执行次数少时,jdk代理性能更好;反之cglib代理性能更好(但是重复执行多于1000000次的任务几乎没有吧

    总结

    本片文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注www.887551.com的更多内容!