设计模式五(代理模式)

        代理模式就是给对象提供一个代理,并由代理对象来控制原对象的引用,使得客户不能与真正的目标对象通信,代理对象是目标对象的代表, 其他需要与这个目标对象打交道的操作都是和这个代理对象在交涉

静态代理

抽象角色:一般使用接口和抽象类来实现

public interface Rent {
    //抽象对象
    public void rent();
}

真实角色:被代理的角色

public class Host implements Rent{
    @Override
    public void rent() {
        System.out.println("房屋出租");
    }
}

代理角色:代理真实角色

public class Proxy implements Rent{

    private Host host;
    public Proxy(Host host){
        this.host=host;
    }
    @Override
    public void rent() {
        host.rent();
    }
}

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

public class Client {
    public static void main(String[] args) {
        //房东要租房
        Host host = new Host();
        //中介帮房东
        Proxy proxy = new Proxy(host);
        //客户找中介
        proxy.rent();
    }
}

优点:使真实角色更加存粹,公共业务由代理类来完成,满足开闭原则

缺点:多了代理类,工作量变大,对于框架场景不太适合

动态代理

基于接口的JDK代理

创建一个对象生成器,实现了InvocationHandler接口重写了invoke方法,被代理的目标对象要实现接口,通过接口来获取对象信息

public class ProxyInvocationHandler implements InvocationHandler {
    private Host host;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object o = method.invoke(host, args);
        return o;
    }

    //生成代理类,重点是第二个参数,获取要代理的抽象角色!之前都是一个角色,现在可以代理一类角色
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),
                host.getClass().getInterfaces(),this);
    }
}

 基于cglib代理

对于没有接口的类,想要实现动态代理,就需要cglib了,CGLib 采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建 子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑

Cglib 子类代理实现方法:

1.需要引入 cglib 的 jar 文件,但是 Spring 的核心包中已经包括了 Cglib 功能,所 以直接引入 spring-core-xxx.jar 即可.

2.引入功能包后,就可以在内存中动态构建子类

3.代理的类不能为 final,否则报错

4.目标对象的方法如果为 final/static,那么就不会被拦截,即不会执行目标对象额 外的业务方法.

public  class CarFactoryImpl {
	    public  void sell() {
	        System.out.println("汽车厂卖汽车");
	    }
}
public class CGLibProxy implements MethodInterceptor {
    
	    private Enhancer enhancer = new Enhancer();
	    
	    public Object getProxy(Class<?> clazz){  
	        enhancer.setSuperclass(clazz);  
	        enhancer.setCallback(this);  
	        return enhancer.create();  
	    }  
	    /*
	     * 拦截所有目标类方法的调用 
	     * 参数: 
	     * obj  目标实例对象 
	     * method 目标方法的反射对象 
	     * args 方法的参数 
	     * proxy 代理类的实例 
	     */
	    public Object intercept(Object obj, Method method, Object[] args,  
	            MethodProxy proxy) throws Throwable {
	        //代理类调用父类的方法  
	        System.out.println("开始事务");  
	        Object obj1 = proxy.invokeSuper(obj, args);  
	        System.out.println("关闭事务");  
	        return obj1;  
	    }
}
public class Test {

	 public static void main(String[] args) {
		  CGLibProxy proxy = new CGLibProxy();
		  CarFactoryImpl carFactory = (CarFactoryImpl) proxy.getProxy(CarFactoryImpl.class);
		  carFactory.sell();
	}
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值