java中的静态代理和动态代理

文章目录


前言

这是一个新的系列,主要用来记录复盘java基础时候的一些笔记。


一、静态代理

在正式介绍静态代理之前呢,先看下代理模式的定义:代理模式为其他对象提供一种代理以控制对这个对象的访问。
那什么又是静态代理呢,简单来讲,就是要创建出一个代理类,这个代理类与目标类实现了同一个接口,当去使用目标对象的时候,不是直接创建目标对象,而是创建代理对象,去调用目标对象中的方法。
java中的静态代理和动态代理
接下来看下每个部分的代码:
代理了和目标类继承的接口:

public interface Service {
    public void sing();

    public void dance();
}

目标类:

public class Provider implements Service{
    public void sing() {
        System.out.println("正在唱歌。。。。。。");
    }

    public void dance() {
        System.out.println("正在跳舞。。。。。。");
    }
}

代理类:

public class Agent implements Service{

    private Service service;
    public Agent(Service service){          //代理类主要是要在构造中传入一个接口类型的参数
        this.service=service;
    }
    public void sing() {                   //代理类中的方法其实,是调用传入参数的方法
        service.sing();
    }

    public void dance() {
        service.dance();
    }
}

使用者:

public class Customer {
    public static void main(String[] args) {
        Agent agent = new Agent(new Provider());        //实例化一个代理对象,但是传入的是目标对象
        agent.sing();            //这里最终调用的还是目标对象中的方法
        agent.dance();
    }
}

二、动态代理

静态代理其实很好理解,就是要创建一个代理对象,去代理目标对象。那么动态代理又是什么呢?
基于静态代理的理解上,动态代理其实就是直接给某一个目标对象生成一个代理对象,而不需要代理类存在,动态代理与静态代理原理是一样的,只是它没有具体的代理类,而直接通过反射生成了一个代理对象。
这里,是借助Proxy下的newProxyInstance()来实现直接生成代理对象的。需要注意的是Proxy是reflect包下的。
接口和目标类的方法其实和静态代理是一样的,这里就不写了。直接看下在使用的时候,如何动态生成代理对象:

public class Customer {
    public static void main(String[] args) {
    	//这里把目标对象的类型提升为接口类型,是为了如果有多个目标类的时候,想更换目标对象,只需要在这里更改,而不需要在下面动态代理传入的参数里面再改成新的目标对象
        final Service service = new Provider();    
        Service agent = (Service)Proxy.newProxyInstance(service.getClass().getClassLoader(), service.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("准备中......");
                method.invoke(service, null);
                System.out.println("结束啦~~~");
                return null;
            }
        });
        agent.dance();
        agent.Sing();
    }
}

这里解释下newProxyInstance():
service.getClass().getClassLoader():这里传入的是目标类的类加载器。
service.getClass().getInterfaces():这里传入的是目标类继承的接口。
InvocationHandler():策略设计模式的应用,通过实现这个接口,说明如何代理真实对象,怎么实现代理。
invoke():(这里是InvocationHandler里面重写的方法)调用代理类的任何方法,这个方法都会执行;比如下面的agent.dance(),调用这个方法,实际上,执行的是invoke方法。
Object proxy:(invoke方法中的参数)代理对象本身的引用,这个一般不用。
Method method:(invoke方法中的参数)当前调用的方法;比如agent.dance(),那这里就会执行dance这个方法。
Object[] args:(invoke方法中的参数)当前方法用到的参数,如果没有,method.invoke()里面参数部分就传入null。

三、动态代理的应用

其实,在上面动态代理的代码中已经写到了应用的示例。

System.out.println("准备中......");
method.invoke(service, null);
System.out.println("结束啦~~~");

在每次目标对象的方法执行前和执行后,都可以执行一些其他代码,来扩展目标对象的功能。
而这么做的好处是,当这些扩展的功能都一样时,不需要在每个方法里都写一遍了,直接加在代理对象里,这样代理对象去执行这个方法的时候,扩展的功能也会执行一次。

总结

以上就是静态代理和动态代理的内容啦。

上一篇:Java遍历对象属性(反射实现)


下一篇:java类反射获取成员方法