静态代理/动态代理理解

静态代理角色分析

  • 抽象角色:真实角色和代理角色要共同做同一件事,一般使用接口或抽象类
  • 真实角色:真实要做事情的角色
  • 代理角色:代理真实角色
  • 用户:不直接和真实角色打交道,通过代理角色和真实角色打交道
    静态代理/动态代理理解_第1张图片

静态代理

这里使用真实案例
抽象角色:租房
真实角色:房东
代理角色:中介
用户:和中介打交道而不和房东直接打交道

1.创建抽象角色

public interface Rent {
    //租房
    void rentHouse();
}

2.创建真实角色

//房东
public class Host implements Rent{

    public void rentHouse() {
        System.out.println("房东要租房子");
    }
}

3.创建代理角色

//中介
public class Zhongjie implements Rent{

	//中介要代理房东这个角色
    private Host host;

    public Zhongjie(Host host) {
        this.host = host;
    }

	//也重写了接口的方法,但不是中介租房,而是房东租房子
	//并且可以干一些其他事情,比如看房子,签合同
    public void rentHouse() {
        seeHouse();
        host.rentHouse();
        qianhetong();
    }

    public void qianhetong(){
        System.out.println("签合同");
    }

    public void seeHouse(){
        System.out.println("看房子");
    }

}

4.用户测试

public class Test {
    public static void main(String[] args) {
    	//实例化一个房东对象
        Host host = new Host();
        //中介代理房东,所以将房东对象传给中介
        Zhongjie zhongjie = new Zhongjie(host);
        //中介调用租房子方法
        zhongjie.rentHouse();

    }
}

5.结果
静态代理/动态代理理解_第2张图片
分析:在这个过程中,你直接接触的就是中介,就如同现实生活中的样子,你看不到房东,但是你依旧租到了房东的房子通过代理,这就是所谓的代理模式,程序源自于生活,所以学编程的人,一般能够更加抽象的看待生活中发生的事情。

静态代理的好处:

  • 可以使真实角色更加纯粹,不再关注一些公共的事
  • 公共的业务交给代理完成,实现了业务的分工
  • 公共业务发生扩展使更加集中和方便

缺点:

  • 有多少个真实角色,就要有多少个代理角色,工作量大,开发效率低

我们想要静态代理的好处,又不想要静态代理的缺点,所以 , 就有了动态代理 !

动态代理

动态代理和静态代理的区别

  • 静态代理的代理类是提前写好的
  • 动态代理的代理类是动态生成的

动态代理分为两种

  • 基于接口的动态代理:JDK动态代理
  • 基于类的动态代理:cglib

这里将基于接口的动态代理
1.创建抽象角色

public interface Renting {
	//租房	
    void rentingHouse();
}

2.创建真实对象

//房东
public class HouseHost implements Renting{
    public void rentingHouse() {
        System.out.println("房东出租房子!");
    }
}

3.创建代理处理类

public class ProxyInvocationHandler implements InvocationHandler {

	//代理的抽象角色
	//动态代理代理的不再是一个角色,而是一类角色,所以传的是接口
    private Renting renting;

    public void setRenting(Renting renting) {
        this.renting = renting;
    }

	//生成代理类
	//newProxyInstance(arg1,arg2,arg3)参数
	//arg1:实现InvocationHandler 接口的类加载器
	//arg2:抽象角色也就是接口
	//arg3:实现InvocationHandler 接口的类的实例
    public Object getProxy(){
        return Proxy.newProxyInstance(ProxyInvocationHandler.class.getClassLoader(),
                renting.getClass().getInterfaces(),
                this);
    }

	// 处理代理实例上的方法调用并返回结果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    	//核心:反射实现的
        Object result = method.invoke(renting, args);
        return result;
    }
}

将ProxyInvocationHandler 类中的接口换成Object类型,就可以处理不同业务,代码如下:

public class ProxyInvocationHandler implements InvocationHandler {

    private Object object;

    public void setRenting(Object object) {
        this.object = object;
    }

    public Object getProxy(){
        return Proxy.newProxyInstance(ProxyInvocationHandler.class.getClassLoader(),
                object.getClass().getInterfaces(),
                this);
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(object, args);
        return result;
    }
}

4.测试

public class Test {
    public static void main(String[] args) {
    	//创建抽象角色的实例
        Renting host = new HouseHost();
        ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
        //代理一类角色
        proxyInvocationHandler.setRenting(host);
        //生成代理对象
        Renting proxy = (Renting) proxyInvocationHandler.getProxy();
        //调用方法
        proxy.rentingHouse();
    }
}

第3,4步也可这样写
3.创建代理处理类

public class ProxyInvocationHandler implements InvocationHandler {

    private Renting renting;

    public void setRenting(Renting renting) {
        this.renting = renting;
    }


    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(renting, args);
        return result;
    }
}

4.测试

public class Test {
    public static void main(String[] args) {
        Renting host = new HouseHost();
        ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
        //代理一类角色
        proxyInvocationHandler.setRenting(host);
        //生成代理对象
        Renting proxy = (Renting) Proxy.newProxyInstance(proxyInvocationHandler.getClass().getClassLoader()
                , host.getClass().getInterfaces()
                , proxyInvocationHandler);
        proxy.rentingHouse();
    }
}

结果相同,写法不同

动态代理的好处

  • 可以使真实角色更加纯粹,不再关注一些公共的事
  • 公共的业务交给代理完成,实现了业务的分工
  • 公共业务发生扩展使更加集中和方便
  • 一个动态代理,一般代理某一类业务
  • 一个动态代理可以代理多个类,代理的是接口

你可能感兴趣的:(Spring,java,设计模式,静态代理,动态代理,jdk动态代理)