`
lantian_123
  • 浏览: 1360953 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论
阅读更多

动态代理(Dynamic Proxy

在了解动态代理之前先来简单的回顾下代理模式

一、代理的概念:生活中的代理不胜枚举,譬如你想买一台ipad2(其实我也想买)你肯定不希望跑到美国苹果的总部买回来,多麻烦啊!一般都是希望直接在国内的苹果代理商那里去购买。这样的好处就是节省了不少时间和金钱,当然还避免的很多风险(风险都由代理商帮你完成了)。设计模式中的代理也如同生活中的代理,客户端不直接引用真实对象,而是去引用他的代理对象,由代理对象完成真实对象所要做的一些事情。

二、代理模式所涉及角色:

1.  抽象主题角色:声明真实主题和代理主题的共同接口,这样可以在使用真实主题角色的地方同时也可以使用代理角色。抽象主题角色一般是接口或者抽象类

2.  真实主题角色:真正操作的目标主题对象

3.  代理主题角色:通常代理角色包含有真实主题角色的引用,以便操作真实主题对象。因为与真实主题角色有共同的接口,这样可以替代真实主题,通常代理主题不单单处理客户调用传递过来的请求给真实主题,而且会包含一些其他的操作(好比例子中的风险处理就有代理去解决)。

三、代理的类图:

四、代码清单:

RealSubject.java

/**
 *真实主题对象 
 */
public class RealSubject extends Subject {

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

 

 

 

Subject.java

/**
 * 抽象主题角色
 *
 */
public abstract class Subject {
	
	public abstract void request();
	
}

 

 

Proxy.java

public class Proxy extends Subject{

	private RealSubject realSubject;
	
	public Proxy(RealSubject realSubject) {
		this.realSubject = realSubject;
	}
	private void beforeRequest(){
		System.out.println("proxy beforeRequest");
	}
	@Override
	public void request() {
		beforeRequest();
		realSubject.request();
		afterRequest();
	}

	private void afterRequest(){
		System.out.println("proxy afterRequest");
	}
}

 

 

 

五、动态代理:

正式进入主题,现在有这样的一个需求,系统中有一百个真实主题类,要为其手动的添加代理类可以想象是一个多大的工程。从jdk1.3开始,引入了动态代理,java.lang.reflect.Proxy,JVM可以自己创建代理类,这样不仅提高了效率,而且更灵活。
动态代理涉及的三个主要类:

Proxy,InvocationHandler,Method

Proxy类中主要三个方法:

protected Proxy(InvocationHandler h)

 

public static Class<?> getProxyClass(ClassLoader loader,

Class<?>... interfaces)

 

public static Object newProxyInstance(ClassLoader loader,

                    Class<?>[] interfaces,

                    InvocationHandler h)

1.  分析getProxyClass方法:既然是由JVM创建代理类,首先就必须为其制定ClassLoader,因为所有类都需要类加载器去加载。创建代理的目的是做为客户端和目标对象(真是主题对象)之间的一个中介,所以要为代理类指定一些方法,这里所采用的实现方式就是为其指定一个或者多个接口,JVM生成该代理类时自动的实现这些接口中的方法。这个代理类仅能用作具有相同接口的目标类的代理。

2.  InvocationHander:调用处理器,他是一个接口,就申明了一个invoke方法

public Object invoke(Object proxy, Method method, Object[] args)

每一个代理实例都必须指定一个调用处理器,代理对象调用方法时,该方法会指派到调用处理器的invoke()中去。代理的方法封装成invoke中的method对象,其中的参数封装成Object[]

代码清单:

public class ProxyTest {
	
	@SuppressWarnings("unchecked")
	public static void main(String[] args) {
		
		Collection collection = (Collection)Proxy.newProxyInstance(Collection.class.getClassLoader(), new Class[]{Collection.class}, new InvocationHandler() {
			ArrayList list = new ArrayList();
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				System.out.println("方法:"+method.getName()+"   参数:"+Arrays.toString(args));
				return method.invoke(list, args);
			}
		});
		collection.add("aaa");
		collection.add("aaa");
		collection.add("aaa");
		collection.add("aaa");
		System.out.println(collection.size());
	}
}

 

输出结果:

方法:add   参数:[aaa]

方法:add   参数:[aaa]

方法:add   参数:[aaa]

方法:add   参数:[aaa]

方法:size   参数:null

4

六、     AOP原理:http://www.iteye.com/topic/336873

利用动态代理知识可以直接模拟一个aop

Advice.java

public interface Advice {
	public void before();
	public void after();
}

 

MyProxy.java

public class MyProxy {
	
	public Object getProxy(final Object target,final Advice advice){
		
		Object object = Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(), new InvocationHandler() {
			
			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				advice.before();
				Object obj = method.invoke(target, args);
				advice.after();
				return obj;
			}
		});
		return object;
	}
}

 

  • 大小: 14.5 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics