Java_动态代理Proxy

1.动态代理概述
        动态代理机制的出现,可以简单地指定类加载器对象和一组接口,便能动态地获得代理类,动态扩展功能
       Proxy有一点点小小的遗憾,仅支持 interface 代理,但可以使用CGLIB动态代理支持类!

 

Java_动态代理Proxy_第1张图片
2.代理模式
        为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者看来两者没有丝毫的区别。通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施不同控制策略预留了空间,从而在设计上获得了更大的灵活性。Java 动态代理机制以巧妙的方式近乎完美地实践了代理模式的设计理念。
3.动态代理机制
        代理类构造函数只有一个,com.sun.proxy.$Proxy0(java.lang.reflect.InvocationHandler),方法和字段实现了接口的!

        (1).通过实现 InvocationHandler 接口创建自己的调用处理器; 
        (2).通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类; 
        (3).通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型; 
        (4).通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。
4.动态代理实例化
        (1).简化型
                通过newProxyInstance()方法,一步实例化动态代理类

Proxy.newProxyInstance(Collection.class.getClassLoader(), new Class[]{Collection.class}, MyInvocationHandler);
/*
 * 实例化动态代理类,应该指定有那个类加载进行加载,一般加载器与实现接口一致
 */

       (2).复杂型
              
得到动态代理类的字节码文件,通过反射得到构造函数,并进行实例化

Class clazzProxy = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
Constructor con = clazzProxy.getConstructor(InvocationHandler.class);
Collection collProxy = (Collection)con.newInstance(MyInvocationHandler);

5.InvocationHandler

      代理类调用函数就会执行InvocationHandler的invoke() 方法,并向该函数传递三个参数信息proxyObject.add("sss"),从左向右依次为代理类实例对象函数名传递数组参数

	public static void test() {

		Collection proxyObject = (Collection) Proxy.newProxyInstance(
				Collection.class.getClassLoader(),
				new Class[] { Collection.class }, new InvocationHandler() {
					public Object invoke(Object proxy, Method method,
							Object[] args) throws Throwable {
						return null;
					}
				});
		System.out.println(proxyObject.clear());//true
		proxyObject.add("ss");//false java.lang.NullPointerException
	}

       为什么clear()正确,而add却是错误的?

           因为InvocationHandler的invoke() 方法执行结果的返回值为Object,当一个函数(add())的返回值为非void时,就会发生错误。解决办法是将该函数执行的结果返回!而clear返回值为null

       正确解决办法

	public static void test() {
		Collection proxyObject = (Collection) Proxy.newProxyInstance(
				Collection.class.getClassLoader(),
				new Class[] { Collection.class }, new InvocationHandler() {
					ArrayList<String> al = new ArrayList<String>();
					public Object invoke(Object proxy, Method method,
							Object[] args) throws Throwable {
						Object returnVal = method.invoke(al, args);
						return returnVal;//返回函数执行的结果
					}
				});
		proxyObject.add("sss");//true
	}

6.动态代理细节
        (1).如果对同一组接口重复创建动态代理类,如果该Class字节码实例对象已经存在,则无需重新加载

Class clazzProxy1 = Proxy.getProxyClass(Collection.class
		.getClassLoader(), Collection.class);
Class clazzProxy2 = Proxy.getProxyClass(Collection.class
		.getClassLoader(), Collection.class);
System.out.println(clazzProxy1 == clazzProxy2); // true

        (2).所有动态代理类都是Proxy的子类

Class clazzProxy3 = Proxy.getProxyClass(Collection.class
		.getClassLoader(), Collection.class);
System.out.println(clazzProxy3.getSuperclass().getName());// java.lang.reflect.Proxy

你可能感兴趣的:(proxy,代理模式)