黑马程序员----动态代理

-------  android培训 java培训 、期待与您交流! ----------

 什么是代理:要为已存在的多个具有相同接口的目标类的方法增加一些系统功能。比如:事物处理,异常处理,日志等。
 也就是业务交叉。面向切面编程AOP(Aspect Oriented program)
  
  什么是动态代理:JVM可以再运行期间动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理类。
 两中实现方式:
JVM生成动态类必须实现一个或多个接口,所以jvm生成的动态类只能用作具有相同接口的目标类的代理。

怎么让一个没有实现接口的类生成动态代理类呢?可以使用CGLIB库。他可以动态的生成一个类的子类,一个类的子类也可以用作该类代理类。

动态代理工作原理图:


代码实现:分析JVM生成动态类,以及获取生成动态类的方法信息列表

package Proxy;

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 ProxyDemo {

	/**
	 * @分析JVM生成动态类,以及获取生成动态类的方法信息列表
	 */
	public static void main(String[] args)  throws Exception{
		
		//通过反射获取jvm生成动态的字节码文件
		//参数说明: 第一个参数classLoader:一般使用使用接口的类加载器,第二个参数:该动态类需要实现的接口
	Class clazzProxy1=	Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);
	System.out.println(clazzProxy1.getName());
	//获取构造方法
	Constructor[] constructors=clazzProxy1.getConstructors();
	for(Constructor constructor: constructors){
		System.out.println(constructor);
		//这个打印出public $Proxy0(java.lang.reflect.InvocationHandler)  。说明只有一个构造方法。
	}
	
	System.out.println("begin new instance-------");
	Constructor constructor=clazzProxy1.getConstructor(InvocationHandler.class);
	Collection proxy1=(Collection) constructor.newInstance(new InvocationHandler() {
		
		@Override
		public Object invoke(Object proxy, Method method, Object[] args)
				throws Throwable {
			// TODO Auto-generated method stub
			return null;
		}
	});
	System.out.println(proxy1);
    //	proxy1.size(); size()方法有返回值。报空指针错误
	
	System.out.println("第二种创建动态实例对象方法:");
	Collection proxy2=(Collection) Proxy.newProxyInstance(
			Collection.class.getClassLoader(),
			new Class[]{Collection.class},
			new InvocationHandler() {
				ArrayList traget=new ArrayList();
				@Override
				public Object invoke(Object proxy, Method method, Object[] args)
						throws Throwable {
					long beginTime=System.currentTimeMillis();
	                Object retVal=method.invoke(traget, args);
	                long endTime=System.currentTimeMillis()-beginTime;
	                System.out.println(method.getName()+"耗时"+(endTime-beginTime));
					return retVal;
				}
			});
	    proxy2.add("zd");
	    proxy2.add("lx");
	    proxy2.add("wcb");
	    System.out.println(proxy2.size());
	}

}
面向切面实现,把代理类封装使用,可以插入日志信息等:
package Proxy;

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 ProxyDemo2 {
	public static void main(String[] args) {
		  	Collection  traget=new ArrayList();
		Collection proxy2 = (Collection) getProxy(traget,new AdvicceService());
		    proxy2.add("zd");
		    proxy2.add("lx");
		    proxy2.add("wcb");
		    System.out.println("---------"+proxy2.size());
	}

	 /**
	  * 此方法可以一直使用,动态代理类
	  * @param traget
	  * @param advice
	  * @return proxy2
	  */
	private static Object getProxy(final Object traget,final Advice advice) {
		Object proxy2= Proxy.newProxyInstance(
				traget.getClass().getClassLoader(), //用什么接口就用它的类加载器
				traget.getClass().getInterfaces(), 
				new InvocationHandler() {
					@Override
					public Object invoke(Object proxy, Method method, Object[] args)
							throws Throwable {
					    advice.beforMethod(method); 
		                Object retVal=method.invoke(traget, args);
		                advice.afterMethod(method);
						return retVal;
					}
				});
		return proxy2;
	}

}
接口:
package Proxy;

import java.lang.reflect.Method;

public interface Advice {
	
	 void beforMethod(Method method);
	 void afterMethod(Method method);

}
接口实现类:
package Proxy;

import java.lang.reflect.Method;

public class AdvicceService implements Advice {

	private long beginTime=0;
	@Override
	public void beforMethod(Method method) {
		
		beginTime=System.currentTimeMillis();
		
	}

	@Override
	public void afterMethod(Method method) {
		  long endTime=System.currentTimeMillis()-beginTime;
          System.out.println(method.getName()+"耗时"+(endTime-beginTime));
		
	}

}
-------  android培训 java培训 、期待与您交流! ----------




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值