Java基本设计模式动态代理

    代理是基本的设计模式之一,它是你为了提供额外的或不同的操作,而插入的用来代替“实际”对象的对象。这些操作通常涉及与“实际”对象的通信,因此代理通常充当着中间人的角色。下例用来展示代理结构简单示例:因为consumer()接受的Interface,所以他无法真正获得到底是RealObject还是SimpleProxy,因为二者都实现了Interface。但是SimpleProxy已经被插入到了客户端和RealObject之间,因此他会执行操作,然后调用RealObject上相同的方法。

package com.aijie.dtdl;   
/**  
 * @author   E-mail:   
 * @version 2018年6月2日 下午8:58:33  
 */
interface Interface {
	void doSomething();
	void somethingElse(String arg);
}
package com.aijie.dtdl;   
/**  
 * @author   E-mail:   
 * @version 2018年6月2日 下午9:00:24  
 */
class RealObject implements Interface{

	@Override
	public void doSomething() {
		System.out.println("doSomething");
	}

	@Override
	public void somethingElse(String arg) {
		System.out.println("somethingElse "+arg);		
	}
	
}
class SimpleProxy implements Interface{
	private Interface proxied;
	public SimpleProxy(Interface proxied){
		this.proxied = proxied;
	}
	@Override
	public void doSomething() {
		System.out.println("SimpleProxy doSomething");
		proxied.doSomething();
	}

	@Override
	public void somethingElse(String arg) {
		System.out.println("SimpleProxy somethingElse "+arg);
		proxied.somethingElse(arg);
	}
	
}
public class SimpleProxyDemo {
	public static void consumer(Interface iface){
		iface.doSomething();
		iface.somethingElse("banana");
	}
	public static void main(String[] args) {
		consumer(new RealObject());
		consumer(new SimpleProxy(new RealObject()));
	}

}
 

    想要将额外的操作从“实际”对象中分离到不同的地方,特别是当你希望能够很容易的做出修改,从没有使用额外操作转化为使用这些操作,或者反过来时,代理就变得很有用(设计模式的关键就是封装修改-因此需要修改事物证明这种模式的正确性)。

Java动态代理比代理的思想更向前迈进了一步,因为它可以动态的创建代理并动态的处理对所代理方法的调用。在动态代理上所做的所有调用都会被重定向到单一的调用处理器上,它的工作是揭示调用类型并确定相应的对策。

package com.aijie.dtdl;   

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**  
 * @author   E-mail:   
 * @version 2018年6月2日 下午9:39:19  
 */
class DynamicProxyHandler implements InvocationHandler{
	private Object proxied;
	public DynamicProxyHandler(Object proxied){
		this.proxied = proxied;
	}
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		System.out.println("**** proxy:"+proxy.getClass()+",method:"+method+",args:"+args);
		if(args!=null)
			for(Object arg:args)
				System.out.println(" "+arg);		
		return method.invoke(proxied, args);
	}
	
}
public class SimpleDynamicProxy {
	public static void consumer(Interface iface){
		iface.doSomething();
		iface.somethingElse("banana");
	}
	public static void main(String[] args) {
		RealObject real = new RealObject();
		consumer(real);
		Interface proxy = (Interface)Proxy.newProxyInstance(Interface.class.getClassLoader(),
				new Class[]{Interface.class},
				new DynamicProxyHandler(real));
		consumer(proxy);
	}

}
 

doSomething
somethingElse banana
**** proxy:class com.aijie.dtdl.$Proxy0,method:public abstract void com.aijie.dtdl.Interface.doSomething(),args:null
doSomething
**** proxy:class com.aijie.dtdl.$Proxy0,method:public abstract void com.aijie.dtdl.Interface.somethingElse(java.lang.String),args:[Ljava.lang.Object;@3be4d6ef
 banana
somethingElse banana

    通过静态方法Proxy.newProxyInstance()可以创建动态代理,这个方法需要的到一个类加载器,一个希望该代理实现的接口列表(不是类或抽象类)以及InvocationHandler接口的一个实现。

    动态代理可以将所有调用重定向到调用处理器,因此通常会向调用处理器的构造传递给一个实际对象的引用,从而使得调用器在执行其中介任务时,可以将请求转发。

package com.aijie.dtdl;   

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**  
 * @author   E-mail:   
 * @version 2018年6月3日 上午11:07:51  
 */
class MethodSelector implements InvocationHandler{
	private Object proxied;
	public MethodSelector(Object proxied){
		this.proxied = proxied;
	}
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		if(method.getName().equals("interesting"))
			System.out.println("Proxy detected the interesting method");
		return method.invoke(proxied, args);
	}
	
}
interface SomeMethods{
	void boring1();
	void boring2();
	void interesting(String arg);
	void boring3();
}
class Implementation implements SomeMethods{

	@Override
	public void boring1() {
		System.out.println("boring1");
	}

	@Override
	public void boring2() {
		System.out.println("boring2");		
	}

	@Override
	public void interesting(String arg) {
		System.out.println("interesting "+arg);		
	}

	@Override
	public void boring3() {
		System.out.println("boring3");		
	}
	
}
class SelectingMethods {

	public static void main(String[] args) {        //    我们要代理的真实对象
		SomeMethods proxy = (SomeMethods)Proxy.newProxyInstance(SomeMethods.class.getClassLoader(),
				new Class[]{SomeMethods.class}, new MethodSelector(new Implementation()));
		proxy.boring1();
		proxy.boring2();
		proxy.interesting("banana");
		proxy.boring3();
	}

}
 


在学习Spring的时候,我们知道Spring主要有两大思想,一个是IoC,另一个就是AOP,对于IoC,依赖注入就不用多说了,而对于Spring的核心AOP来说,我们不但要知道怎么通过AOP来满足的我们的功能,我们更需要学习的是其底层是怎么样的一个原理,而AOP的原理就是java的动态代理机制

每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。我们来看看InvocationHandler这个接口的唯一一个方法 invoke 方法:

Object invoke(Object proxy, Method method, Object[] args) throws Throwable

我们看到这个方法一共接受三个参数,那么这三个参数分别代表什么呢?

Object invoke(Object proxy, Method method, Object[] args) throws Throwable

proxy:  指代我们所代理的那个真实对象
method:  指代的是我们所要调用真实对象的某个方法的Method对象
args:  指代的是调用真实对象某个方法时接受的参数
通过 Proxy.newProxyInstance 创建的代理对象是在jvm运行时动态生成的一个对象,它并不是我们的InvocationHandler类型,也不是我们定义的那组接口的类型,而是在运行是动态生成的一个对象,并且命名方式都是这样的形式,以$开头,proxy为中,最后一个数字表示对象的标号
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值