JAVA动态代理详解

JAVA动态代理详解

问题

1:什么是静态代理,动态代理?
2:动态代理的好处?

什么是静态代理

以生活中例子来看,我作为某某品牌面膜的北京区代理,我替厂家卖面膜,我属于代理,厂家属于委托方。
联系到JAVA中就是,我作为一个代理类,我替委托类去调用方法,同时可以添加一些附加的功能。
如果一个代理类在程序运行之前就已经存在了,那么这种代理方式被称为静态代理。
先上代码
父接口:

public interface Person {
    /**
     * 吃饭
     */
    void eat();

    /**
     * 拉稀
     */
    void shit();
}

委托类:

class Zhangsan implements Person{

    @Override
    public void eat() {
        System.out.println("我每天都会吃饭;");
    }

    @Override
    public void shit() {
        System.out.println("我偶尔会拉稀;");
    }
}

静态代理类:

class DynamicPerson implements Person{
    /**
     * 委托类
     */
    private Zhangsan zhangsan;

    @Override
    public void eat() {
        System.out.println("附加功能");
        zhangsan.eat();
    }

    @Override
    public void shit() {

    }
}

由上代码可知,代理类中将委托类引入了进来,但是怎么保证代理类的方法列表和委托类的方法列表一致呢,这里是通过接口约束了方法列表。

静态代理的弊端:对于委托类的每一个方法,都得重新编辑同时加入自己的附加功能,委托类方法过多时,效率太低。

动态代理引入

动态代理的引入就是在静态代理的基础上,添加了一个中间处理类,当调用委托类的方法时,优先进入中间处理类,自定义的附加功能放在中间处理类中即可。
动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类的函数。

中间处理类:

class Handle implements InvocationHandler {

    /**
     * 委托类
     */
    private Object obj;

    /**
     * 构造方法
     * @param obj 委托类对象
     */
    public Handle(Object obj){
        this.obj = obj;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //自定义添加内容
        System.out.println("我每天先刷牙;");
        //调用委托类的方法
        Object result = method.invoke(obj, args);
        return result;
    }

测试类:

 public static void main(String[] args) {
        //获取中间处理类
        Handle handle = new Handle(new Zhangsan());

        //获取动态代理实例 向上转型
        Person person = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class[]{Person.class}, handle);

        person.shit();

    }

测试结果:

我每天先刷牙;
我偶尔会拉稀;

Process finished with exit code 0

注意点

方法内部调用方法的情况

class Zhangsan implements Person{

    @Override
    public void eat() {
        System.out.println("我每天都会吃饭;");
    }

    @Override
    public void shit() {
        System.out.println("我偶尔会拉稀;");
    }

    @Override
    public void eatAndShit() {
        eat();
        shit();
    }
}

输出结果:

我每天先刷牙;
我每天都会吃饭;
我偶尔会拉稀;

Process finished with exit code 0
对于委托类方法中的嵌套方法调用,是走方法内部调用,没有代理对象

动态代理分类

那么在Spirng当中动态代理有两种

  • 第一种是JDK自带的动态代理
    1.JDK动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理. 需要指定一个类加载器,然后生成的代理对象实现类的接口或类的类型,接着处理额外功能. JDK是基于接口

  • 第二种是Cglib的动态代理
    2.Cglib是动态代理利用asm的开源包,对代理对象的Class文件加载进来,通过修改其字节码生成的子类来处理 Cglib是基于继承父类生成的代理类.

两种代理方式的区别:

  • 1:JDK动态代理制能对实现了接口的类生成代理,而不是针对类

  • 2:CGLIB是针对类实现代理,主要对指定的类生成一个子类,覆盖其中的方法,添加额外功能,因为是继承,所以该类方法不能用final来声明.

对于具体CHLIB的代码示例参考:
https://blog.csdn.net/qq_42807370/article/details/87354522

你可能感兴趣的:(java基础,java,代理模式,开发语言)