spring的动态代理和静态代理

什么是代理
代理是一种设计模式,提供了对目标对象另外的访问方式,即通过代理对象访问目标对象。可以不修改目标对象,对目标对象功能进行拓展。在我们学习Spring的时候就会发现,AOP(面向切面编程)的底层就是代理。

代理的实现可以分为静态代理和动态代理。动态代理又根据实现的方式分为:基于JDK接口的动态实现和基于Cglib类的动态实现

静态代理
这里可以通过一个现实中的具体例子,来理解代理:

  • 抽象角色:一般会使用接口或者抽象类来解决,这里指代租房
  • 真实角色:被代理的角色,这里指代房东
  • 代理角色:代理真实角色,真实角色通过代理对象可以完成操作。这里指代中介
  • 客户:访问代理对象的人。这里指代租房的人

代码实现:

1,抽象角色(接口)

public interface Rent {
    public void rent();
}

2,真实角色(房东)

public class Host implements Rent {

    @Override
    public void rent() {
        System.out.println("我有房子要出租!!!");
    }
}

代理角色(中介)

public class Proxy implements Rent {
    private Host host;

    public Proxy() {
    }
//构造方法,和真实角色(房东)的连接
    public Proxy(Host host) {
        this.host = host;
    }

    @Override
    public void rent() {
        seeHouse();
        fare();
        contract();
        host.rent();
    }

    //看房
    public void seeHouse() {
        System.out.println("中介带你看房");
    }

    //收中介费
    public void fare() {
        System.out.println("收中介费");
    }

    //签合同
    public void contract() {
        System.out.println("签租赁合同");
    }
}

4,客户(要租房的人)

public class Client {
    public static void main(String[] args) {
        //房东要租房子
        Host host = new Host();
        //代理,中介帮房东租房子,但是代理一般会有一些附属操作
        Proxy proxy = new Proxy(host);

        //你不用面对房东,直接面对中介
        proxy.rent();
    }
}

这里实现了房东出租房子给租客,但是租客完全和房东没有联系,完全靠中介来实现。那在租房子的过程中,遇到的附加操作也可以通过中间来实现。这就是静态代理的实现原理。

动态代理:(和静态代理角色一样 动态生成)

1,基于JDK接口的动态实现
首先我们需要学习两个类:Proxy :提供了创建动态代理类和实例的静态方法。InvocationHandler:invoke(proxy,method,):调用处理程序。下面附上官方的详细介绍:

InvocationHandler是java.lang.reflect包下的一个接口,其是由代理实例关联的调用处理程序实现的接口。因为每一个代理实例都会有一个关联的调用处理程序,所以当在代理实例上调用方法时,该方法将会被编码并分派到代理实例关联的调用处理程序的invoke方法中。(invoke是通过反射实现的)

实际操作进行代码实现:

1,抽象角色(接口)

public interface Rent {
    public void rent();
}

2,真实角色(房东)

public class Host implements Rent {

    @Override    
    public void rent() {
        System.out.println("我有房子要出租!!!");
    }
}

3,动态代理类(中介)

因为每一个代理实例都会关联一个调用处理程序,

因此我们的动态代理类要实InvocationHandler接口。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//这个类的作用:自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {

    //被代理的接口
    private Rent rent;

    public void setRent(Rent rent) {
        this.rent = rent;
    }

    //生成代理对象
    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                                      rent.getClass().getInterfaces(),
                                      this);
    }
    
    //处理代理实例,并返回结果
    //proxy:调用该方法的代理实例
    //method:对应调用代理实例上的接口方法的实例
    //args:包含方法调用传递代理实例的参数值的对象
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //动态代理的本质,就是使用反射机制
        seeHouse();
        Object result = method.invoke(rent, args);
        fare();
        return result;
    }

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

    public void fare() {
        System.out.println("收中介费");
    }
}

4.客户端

public class   Client {
    public static void main(String[] args) {
        //真实角色(房东)
        Host host = new Host();

        //1,代理角色,现在没有
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        //2,通过调用程序处理角色来处理我们要用的接口
        pih.setRent(host);
		//这里的Proxy就是利用我们写的动态代理类动态生成的
        //3(动态代理类通过调用getProxy()方法生成代理对象,getProxy()方法中通过调用Proxy类的静态方法newProxyInstance生成代理类实例)
        Rent proxy = (Rent)pih.getProxy();
        //4
        proxy.rent();
    }
}

输出结果:

基于cglib类的动态实现

与JDK动态代理相比,基于cglib类的动态实现不需要接口,实现的具体流程也差不多,使用起来更简单。

动态代理的实现步骤:

首先,利用实现了InvocationHandler接口的生成一个动态代理角色。

第二,通过调用处理程序角色来处理我们要调用的接口对象。

第三,动态生成代理类实例。

最后,代理类实例处理对应的接口对象。

总结两者的区别:

1.代理分为静态代理和动态代理两种。
⒉.静态代理,代理类需要自己编写代码写成。
3.动态代理,代理类通过Proxy.newInstance()方法生成。
4.不管是静态代理还是动态代理,代理与被代理者都要实现两样接口                                              5.静态代理和动态代理的区别是在于要不要开发者自己定义Proxy类。
6.动态代理通过Proxy动态生成proxy class,但是它也指定了一个InvocationHandler的实现类。    7.代理模式本质上的目的是为了增强现有代码的功能。
 

  • 41
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值