动态代理的两种实现方式

1、动态代理介绍

动态代理:在不改变目标对象方法的情况下对方法进行增强

组成:

    被代理对象:真实的对象 代理对象:内存中的对象

要求:代理对象必须和被代理对象实现相同的接口

代理的实现方式有两种:(1)jdk动态代理;(2)CGLIB动态代理(这个是第三方实现的,所以使用这种方式,我们要引入jar包)

2、代码准备

StudentInterface接口代码

public interface StudentInterface {
    void eat(String name);
    void study();
}

Student代码

public class Student implements StudentInterface{
    public void eat(String name) {
        System.out.println("学生吃" + name);
    }

    public void study() {
        System.out.println("在家自学");
    }
}

Test代码

public class Test {
    public static void main(String[] args) {
        Student stu = new Student();
        stu.eat("米饭");
        stu.study();
    }
}

3、要求

要求:在不改动Student类中任何的代码的前提下,通过study方法输出一句话:来大学学习。

4、方法一:使用jdk动态代理

public class Test {
    public static void main(String[] args) {
        Student stu = new Student();
        /*stu.eat("米饭");
        stu.study();*/

        /*
            
            类加载器:和被代理对象使用相同的类加载器
            接口类型Class数组:和被代理对象使用相同接口
            代理规则:完成代理增强的功能
         */
        StudentInterface proxyStu = (StudentInterface) Proxy.newProxyInstance(stu.getClass().getClassLoader(), new Class[]{StudentInterface.class}, new InvocationHandler() {
            /*
                执行Student类中所有的方法都会经过invoke方法
                对method方法进行判断
                    如果是study,则对其增强
                    如果不是,还调用学生对象原有的功能即可
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                if(method.getName().equals("study")) {
                    System.out.println("来大学学习");
                    return null;
                }else {
                    return method.invoke(stu,args);
                }
            }
        });

        proxyStu.eat("米饭");
        proxyStu.study();

    }
}

5、方式二:使用CGLIB动态代理

CGLIB jar的maven坐标

<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.1_2</version> </dependency>
public class Test {
    public static void main(String[] args) {
        Student stu = new Student();
        /*stu.eat("米饭");
        stu.study();*/

        Object proxyStu = Enhancer.create(stu.getClass(), new MethodInterceptor() {
                    @Override
                    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                        if (method.getName().equals("study")) {
                            System.out.println("来大学学习");
                            return null;
                        } else {
                            return method.invoke(stu, args);
                        }
                    }

                }
                proxyStu.eat("米饭");
                proxyStu.study();
               }
            }

与jdk动态代理相比,CGLIB不要求必须要实现接口StudentInterface ,就能直接对目标对象就行代理增强,更加的简单方便。

经验分享 程序员 微信小程序 职场和发展