Spring中的代理模式(静态、动态代理)

先讲一下为什么学习Spring会专门来研究动态代理,那是因为,Spring的核心AOP的底层,其实全都是用动态代理来实现的。
代理模式是一种设计模式,设计思想,包括:
静态代理
动态代理
先解释一下代理的思想,打个比方,代理的作用其实就相当于中介,比如生活中的例子,当我们需要租房的时候,往往很难直接找到房东直租的,这大家都有体会吧,房东才没那闲心整天跑租房的业务,因此,房东把租房这件事,委托给中介,然后,我们需要租房的时候,其实是找中介租房,这就是代理模式的思想。
因此,代理模式中的几个角色:
抽象角色:一般使用接口或者抽象类。其实就是需要被代理的业务,在上面的例子中就是租房这件事。
真实角色:被代理的角色。在上面的例子中就是房东。
代理角色:代理真实角色,在上面的例子中就是中介。
客户:访问代理来完成一些操作,在上面的例子中就是租房的人。

静态代理

类似于装饰者模式,代理类和被代理类实现相同的接口,然后代理类聚合上被代理对象,然后动态扩展功能。
1.可以使得我们的真实角色更加纯粹 . 不再去关注一些公共的事情
2.公共的业务由代理来完成 . 实现了业务的分工
3.公共业务发生扩展时变得更加集中和方便
缺点:
因为代理类和被代理类都需要实现接口,因此,如果接口功能扩展的话,代理类和被代理对象都需要扩展代码,扩展性不好。
如何解决静态代理的缺点呢?其实就是动态代理。

动态代理

动态代理,说白了,其实就是把创建代理对象的过程,用反射来实现,代理类此时就不需要去实现被代理对象的接口了,因此也就和被代理对象解耦了。动态代理,不需要把代理类写死了,这样代理的功能就不是固定的了。注意。这里反射出来的代理对象,被代理对象仍然是创建出来然后当作参数传入的。
JDK代理
说白了JDK代理就是依赖JDK提供的代理功能。
JAVA中动态代理涉及的两个类:
InvocationHandler和Proxy
InvocationHandler:是一个接口,动态代理类需要实现这个接口,然后调用Proxy来创建被代理对象和调用代理功能。里面有一个调用处理的抽象方法:
Object invoke(Object proxy, 方法 method, Object[] args);
参数:
proxy - 调用该方法的代理实例
method -所述方法对应于调用代理实例上的接口方法的实例。方法对象的声明类将是该方法声明的接口,它可以是代理类继承该方法的代理接口的超级接口。
args -包含的方法调用传递代理实例的参数值的对象的阵列,或null如果接口方法没有参数。原始类型的参数包含在适当的原始包装器类的实例中,例如java.lang.Integer或java.lang.Boolean 。
Proxy:可以用反射来创建一个代理对象:
Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
参数:
this.getClass().getClassLoader():当前类的classloader,这个当前类一般是InvocationHandler的实现类。
target.getClass().getInterfaces():被代理对象的接口,这个接口一般就是需要被代理的功能,比如租房。
this:当前类对象,一般是InvocationHandler的实现类。

动态代理的实现代码:

public class ProxyInvocationHandler implements InvocationHandler {

    //被代理对象
    private Object target;
    public void setTarget(Object target){
        this.target=target;
    }

    //生成代理类
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),this);
    }

    //实现InvocationHandler接口的invoke方法
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = method.invoke(target,args);
        return result;
    }
}

Cglib代理
如果目标对象没有实现接口怎么办?那么,Cglib代理就是解决这个问题的。Cglib底层是通过使用字节码处理框架ASM来转换字节码并生成新的类。
对于AOP:
如果目标对象实现了接口,就使用JDK代理。
如果目标对象不需要实现接口,就使用Cglib代理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值