代理


动态代理技术可以动态的生成一段内部有一个被扩展类引用的代码,生成的类类似于用组合这种方式,并把它动态的编译成class文件,然后装载进jvm中执行。著名的框架Spring的核心技术之一aop就是使用的就是动态代理技术。

 Java中为动态代理提供了支持,用到了类Proxy用于产生代理,还有一个接口InvocationHandler,用于在被代理的类的方法前后加入处理逻辑,这个接口内部有一个invoke方法,invoke接受三个参数,

代理Proxy 基本概念

安全、事物、日志要贯穿到好多模块中,就是交叉业务

AOP面向方面编程

目标:要使交叉业务模块化,将切面代码移动到原始方法的周围
代理是实现AOP功能的核心和关键技术

JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理类

1JVM生成的动态类必须实现一个或多个接口,JVM生成的动态类只能用作具有相同接口的目标类的代


    2
CGLIB库可以动态生成一个类的子类一个类的子类也可以用作该类的代理。,如果要为一个没有实现

接口的类生成动态代理类,那么可以使用CGLIB
   
代理方法在系统代码位置
    1
)在调用模板方法之前
    2
)在调用模板方法之后
    3
)在调用模板方法之前后
    4
)在处理目标方法异常的catch块中

二、创建代理
InvocationHandler
接口
   
创建实现Collection接口的动态类和查看其名称,分析Proxy.getProxyClass方法的各个参数

    创建动态类的实例对象
       1
)用反射获得构造方法
       2
)编写一个简单的InvocationHandler
       3
)调用构造方法创建动态类的实例对象,并编写的InvocationHandler类的实例对象穿进去
   InvocationHandler
的运行原理
创建某一接口 MyInterface的代理:
     InvocationHandler handler = newMyInvocationHandler(...);
           
代理实例调用处理程序实现的接口,对代理实例调用方法时,将对方法调用进行编码并将其指

派到它的调用处理程序的 invoke方法
Class proxyClass = Proxy.getProxyClass(MyInterface.class.getClassLoader(), new Class[] { MyInterface .class });
得到接口代理类的类加载器,要接口数组(因为可能要加载的不是一个接口)
MyInterface myint = (MyInterface ) proxyClass.getConstructor(newClass[]{               

 InvocationHandler.class}).newInstance(new Object[] { handler });

创建代理的示例代码:

package lianxi;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;

public class proxytest {

	/**
	 * @param args
	 * @throws Exception
	 * @throws SecurityException
	 */
	public static void main(String[] args) throws SecurityException, Exception {
		// TODO Auto-generated method stub

		Class clazz = Proxy.getProxyClass(Collection.class.getClassLoader(),
				Collection.class);
		Constructor[] Constructors = clazz.getConstructors();
		for (Constructor constructor : Constructors) {
			StringBuilder sb = new StringBuilder();
			sb.append("(");
			Class[] paramclazzs = constructor.getParameterTypes();
			for (Class paramclazz : paramclazzs) {
				sb.append(paramclazz.getName());
				sb.append(",");
			}
			if (paramclazzs.length != 0)
				sb.deleteCharAt(sb.length() - 1);
			sb.append(")");
			System.out.println(constructor.getName() + sb.toString());
		}
		class myInvocationHandler implements InvocationHandler {

			@Override
			public Object invoke(Object proxy, Method method, Object[] args)
					throws Throwable {
				// TODO Auto-generated method stub
				return null;
			}

		}

		final ArrayList Target = new ArrayList();
		Collection coll1 = (Collection) getProxy(Target);
		coll1.add("123");
		coll1.add("456");
		coll1.add("ert");
		// System.out.println(coll1);
		System.out.println(Target);

		/*
		 * System.out.println("*************************************"); Method[]
		 * methods=clazz.getMethods(); for(Method method:methods){ StringBuilder
		 * sb=new StringBuilder(); sb.append("("); Class[]
		 * paramclazzs=method.getParameterTypes(); for(Class
		 * paramclazz:paramclazzs){ sb.append(paramclazz.getName());
		 * sb.append(","); } if(paramclazzs.length!=0)
		 * sb.deleteCharAt(sb.length()-1); sb.append(")");
		 * System.out.println(method.getName()+sb.toString()); }
		 */
	}

	private static Object getProxy(final Object Target) {
		Object coll1 = Proxy.newProxyInstance(Target.getClass()
				.getClassLoader(), Target.getClass().getInterfaces(),
				new InvocationHandler() {

					@Override
					public Object invoke(Object proxy, Method method,
							Object[] args) throws Throwable {

						// TODO Auto-generated method stub
						long starttime = System.currentTimeMillis();
						if ("123".equals(args[0]))
							args[0] = "hello";
						Object obj = method.invoke(Target, args);
						System.out.println("args:::" + args);
						// System.out.println("proxy:::"+proxy);
						long endtime = System.currentTimeMillis();
						System.out.println(method + "....runtime..."
								+ (endtime - starttime));
						return obj;
					}
				});
		return coll1;
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章