Spring中的代理

代理

为什么么要学习代理模式,因为aop的底层机制就是动态代理;

代理模式:

  • 静态代理
  • 动态代理

静态代理

代理模式的角色分析:

抽象角色:一般会使用抽象类或者接口实现

真实角色:被代理的角色

代理角色:代理真实角色,代理真实角色后,一般会做一些附属的操作;

客户:使用代理角色进行一些操作

在这里插入图片描述关于静态代理的详细讲解在我之前的博客《静态代理》中有较为详细的讲解,这里不再重复,

在这篇博客中我们将租客、房东和中介的关系使用代理来进行描述,这个关系和之前我的博客中的结婚和婚庆公司的关系一致,可以实现一一对应,这里不再过多描述:

代码实现:

公共实现的接口:

package com.org.westos.DongProxy;
//租房的接口:抽象
public interface Rent {
    //租房
    void rent();
}

真实对象:

package com.org.westos.DongProxy;
//这个房子要出租
public class Host implements Rent {

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

}

代理对象:

package com.org.westos.DongProxy;

//房屋中介--代理
public class Proxy implements Rent {

    //房东
    private Host host;

    public void setHost(Host host) {
        this.host = host;
    }

    public void rent() {
        lookHouse();
        host.rent();
        fare();
    }

    private void lookHouse(){
        System.out.println("中介带你看房");
    }

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


}

测试:

package com.org.westos.DongProxy;

public class You {
    public static void main(String[] args) {

        Host host = new Host();

        Proxy proxy = new Proxy();
        proxy.setHost(host);
        proxy.rent();

    }
}

通过上述的代码就实现了简单的静态代理

静态代理模式的好处

  • 可以使真实角色更加纯粹,不用去关注一些公共的事情;
  • 公共的业务由代理来完成,实现业务的分工;
  • 公共业务的要扩展的话,可以更加集中和方便;

缺点:

  • 假如我们的真实角色变得非常多,代理类也会随之增多,工作量变大,开发效率变低!

然后我们想需要一种能够有静态代理的全部好处,但是又不存在这种缺点的东西。

动态代理

动态代理和静态代理的角色都是一样;

静态代理模式的代理类是我们提前写好的,动态代理的类是动态生成的;

动态代理大概分两类:

基于接口实现:JDK

基于类实现:cglib

当今用的比较多的是 JAVAssist来生成动态代理

了解动态代理之前,需要掌握两个类:

  • InvocationHandler
  • Proxy

在JDK帮助文档中查阅这两个类:

  1. InvocationHandler是由代理实例的调用处理程序实现的接口
    上面这句话听起来很拗口,可以理解为动态产生代理的类需要实现的接口

  2. 在实现上面的接口后需要重写invoke(Object proxy, 方法 method, Object[] args) 处理代理实例上的方法调用并返回结果。

  3. Proxy提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。

  4. 通过帮助文档查找到Proxy类的静态方法为newProxyInstance(ClassLoader loader, 类<?>[] interfaces,InvocationHandler h) 返回指定接口的代理类的实例,该接口将方法调用分派给指定的调用处理程序。
    上述静态方法的参数为类加载器、通过反射查找到类的接口和其他参数

在这里插入图片描述之前的几个类都是在将静态代理的时候讲解的

我们需要创建两个新的类来分别作为动态产生代理的类和测试类,这里房东和Rent接口不再重新写,直接使用之前写静态代理时候写好的

1.动态产生代理的类需要实现InvocationHandler接口

public class InvocationHandlerProxy implements InvocationHandler {

}

2.在实现上面的接口后需要重写invoke方法

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return null;
}

3.重写上面的方法时第二个参数methodIDE会自动导入java.lang.reflect.Method包,导入这个包后我们需要调用这个包下的invoke方法

Object result = method.invoke(rent, args);
return result;

invoke方法的第一个参数是一个对象,这里需要我们代理类和真实类共同实现的接口也就是Rent,第二个是对象的参数,这里直接使用传入的args,在执行这个方法完成后我们可以返回result对象

4.当然我们在重写InvocationHandler接口中的invoke方法时也可以在里面添加一些代理的特有的一些方法,比如:

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

private void zhongJieFei(){
        System.out.println("收中介费");
}

上面的两个方法就是代理类特有的两个方法,我们可以将他们添加到重写的接口中的invoke方法中

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

5.在写method.invoke方法时我们需要一个对象,这个对象就是真实对象和代理类一起实现的共同的接口,在我们的例子中就是Rent接口,因为是动态设置,所以不同的接口就会产生不同的代理类,所以我们需要写一个方法来从外界设置我们使用的接口

private Rent rent;

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

6.在执行完上面的操作后还有一点,在我们重写InvocationHandler接口中的invoke方法时其中的一个参数就是proxy,所以我们还需要一个方法来产生proxy,这里我们需要使用到Proxy类的静态方法newProxyInstance,这里要注意newProxyInstance方法的几个参数:类加载器、通过反射查找到类的接口和其他参数

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

到这里动态代理的代码才算全部完成,之后可以编写一个测试列来进行测试

测试类代码为:

package com.org.westos.DongProxy;

public class Test {
    public static void main(String[] args) {
        Host host = new Host();
        InvocationHandlerProxy ihp = new InvocationHandlerProxy();
        ihp.setRent(host);

        Rent proxy = (Rent) ihp.getProxy(); //dong

        proxy.rent();
    }
}

在这里插入图片描述可以看到运行成功,动态代理完成

后续我还会添加一些自己对代理的理解,敬请期待

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值