Java中的动态代理和静态代理(回顾)

一、什么是代理

现在有三个人:农民、秘书和领导。

农民要去找领导盖章,但是领导很忙,然后就授权秘书可以代替领导进行盖章操作。

这时候,秘书就代理了领导进行盖章。

这个秘书呢,为了谋取私利,找他盖章的人都要缴纳20元的手续费!

秘书在代理领导盖章工作以外,有增加了一项业务(收手续费),这就是代理的“好处”。

代理(秘书)提供了农民对目标对象(领导)的间接访问方式,农民通过代理(秘书)访问目标对象(领导)。

这样就便于在目标实现(领导盖章)的基础上增加额外的功能操作(收手续费),这个额外操作(收手续费)可以在

实现目标对象(盖章)之前操作,也可以在(盖章)其之后操作。以满足自身的业务需要。

代理模式便于扩展目标对象功能(盖章+收手续费)。

二、什么是静态代理呢?

领导不只一个,还有签字的领导A、调研的领导B、剪彩的领导C。。。

但是秘书只代理了盖章领导,秘书就只有代理盖章的功能。如果农民找秘书签字,

秘书是无法签的,农民还是要找领导A去签字,这就是“静态代理”!秘书的代理功能单一。

具体实现:代理类(秘书)通过实现与目标对象(签字领导)相同的接口(盖章),

并在类中维护一个代理对象。通过构造器塞入目标对象,赋值给代理对象,进而执行代理对象实现的接口方法,

并实现前拦截(收费),后拦截等所需的业务功能。

具体实现如下:

/**
 * 目标对象实现的接口(盖章)
 */
public interface BussinessInterface {
 
    void execute();
}
 
/**
 * 目标对象实现类(签字领导)
 */
public class Bussiness implements BussinessInterface{
 
    @Override
    public void execute() {
        System.out.println("盖章。。。");
    }
}
 
/**
 * 代理类(秘书),通过实现与目标对象(领导)相同的接口(盖章)
 * 并维护一个代理对象,通过构造器传入实际目标对象并赋值
 * 执行代理对象实现的接口方法,实现对目标对象实现的干预
 * 
 */
public class BussinessProxy implements BussinessInterface{
     
    private BussinessInterface bussinessImpl;
     
    public BussinessProxy(BussinessInterface bussinessImpl) {
        this.bussinessImpl = bussinessImpl;
    }
     
    @Override
    public void execute() {
        System.out.println("收手续费");
        bussinessImpl.execute();
        System.out.println("其他工作");
    }
}

通过以上代码看到,因为代理对象,需要实现与目标对象一样的接口,如果有多个需要代理的对象,导致代理类也会很多,不易维护,如果增加接口中的方法,代理对象也需要维护。

三、什么是动态代理?

但是领导A、B、C太忙了,于是有了秘书处,秘书处专门“生产秘书”,盖章的秘书、签字的秘书、调研的秘书等都有。

无论是什么领导,秘书处都能“生产”出代理他们的秘书。农民只需找秘书处就行了。

这样就灵活了,无论是什么领导,秘书处都能有对应的秘书代理领导干活。这个秘书处就是“动态代理”。

动态代理是指(秘书处)动态的在内存中构建代理对象(秘书)(需要我们制定要代理的目标对象(领导们)实现的接口类型),即利用JDK的API生成指定接口的对象,也称之为JDK代理或者接口代理。

动态代理实现如下:

/**
 * 动态代理对象(秘书),无需实现任何接口
 * 通过传入任何类型的目标对象(任何领导)并指定接口
 * 调用JDK接口动态创建代理对象
 */
public class ProxyFactory {
 
    private Object targetObject;
     
    public ProxyFactory(Object targetObject) {
        this.targetObject = targetObject;
    }
     
    public Object getProxyInstance(){
        return Proxy.newProxyInstance(
                targetObject.getClass().getClassLoader(), //和目标对象的类加载器保持一致
                targetObject.getClass().getInterfaces(), //目标对象实现的接口,因为需要根据接口动态生成对象
                new InvocationHandler() { //InvocationHandler:事件处理器,即对目标对象方法的执行
                     
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("收费");
                         
                        Object result = method.invoke(targetObject, args);
                         
                        System.out.println("干其他活");
                        return result;
                    }
                });
    }
}

那农民怎么找秘书进行具体的工作呢?

代码如下:

public class Client {

	@Test
	public void dynamicProxy(){
		//农民想找签字的秘书
		Bussiness bussiness = new Bussiness();
        //告诉秘书处,我想找签字的秘书。秘书处生产了能够签字的秘书
		Object obj = new ProxyFactory(bussiness).ProxyInstance();
		BussinessInterface bussinessImpl = (BussinessInterface)obj;
        
        //秘书签字
		bussinessImpl .excute();
		

	}
}

动态代理的优势:代理对象无需实现接口,免去了编写很多代理类的烦恼,同时接口增加方法也无需再维护代理对象,只需在事件处理器中添加对方法的判断即可。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值