设计模式之代理模式(动态代理)

上一篇介绍了设计模式之代理模式的静态代理。在实际编程中,静态代理模式都很好理解。但是通常使用比较多还是动态代理。主要是因为实现阶段不用关系代理是哪个,而在运行阶段指定具体哪个代理。java中著名的spring框架中面向AOP编程的思想就是基于动态代理。
说到动态代理,不得不说个接口 InvocationHandler,java API文档中有句介绍的话。
InvocationHandler is the interface implemented by the invocation handler of a proxy instance.
Each proxy instance has an associated invocation handler. When a method is invoked on a proxy instance, the method invocation is encoded and dispatched to the invoke method of its invocation handler.
大致意思是:每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。

具体代码实现:和静态代理方式一样,我们创建了一个接口:

public interface ICompany {
	public void signContract(String companyName);
}

这个接口将由真正的实现类Company来实现:

public class Company implements ICompany {

	@Override
	public void signContract(String companyName) {
		// TODO Auto-generated method stub
		System.out.println("我们签约了"+companyName);
	}
}

上面提到每一个动态代理对象都要关联到一个handler,而这handler就是InvocationHandler的实现类:

public class ProxyCompanyHandler implements InvocationHandler {
	private ICompany company;
	
	public ProxyCompanyHandler(ICompany company){
		this.company = company;
	}
	
	@Override
	public Object invoke(Object proxy, Method method, Object[] arg2) throws Throwable {
		// TODO Auto-generated method stub
		//从侧面切入从而达到扩展的效果的编程,就是面向切面编程(AOP Aspect Oriented Programming)。
	  //AOP并不是新技术,而是相对于面向对象编程的一种新的编程思想。在日志,事务,权限等方面使用较多
		if(method.getName().equals("signContract")){
			System.out.println("这里我们可以拦截方法的执行,我可以动态代理这个对象");
			method.invoke(company, arg2);
		}
		return method.invoke(company, arg2);
	}
}
}

如何创建一个动态代理的实例呢,通过Proxy.newProxyInstance方法创建一个动态代理的实例。

public class ProxyMain {

	public static void main(String[] args) {
		ICompany tencent = new Company();
		ProxyCompanyHandler handler = new ProxyCompanyHandler(tencent);
		ICompany tencentProxy = (ICompany) Proxy.newProxyInstance(tencent.getClass().getClassLoader(),tencent.getClass().getInterfaces(), handler);
		//此处便实现了对 Company的动态代理。并且生成了代理对象 tencentProxy。如果配合java反射的思想。可以实现很多有意思的代理
		tencentProxy.signContract("阿里巴巴");
	}
}

最终执行结果为:
动态代理图

其实:如果配合java反射更是可以在代理某些私有对象。比如在android中可以通过代理,拦截android,activity的启动。通过【欺上瞒下】的手段更是可以启动没有在清单中注册的activity。这也是插件化框架的重要思想。总而言之,动态代理在一些优秀的框架中已经得到广泛的使用。这种设计模式,也给我们实现某些功能带来极大的便利性。

猜你喜欢

转载自blog.csdn.net/xu_coding/article/details/84204582