动态代理 Proxy InvocationHandler

来源:互联网 发布:淘宝助理csv文件制作 编辑:程序博客网 时间:2024/05/17 07:26

   动态代理一般用于在执行实例对象的基础上,增加一些扩展的功能,并且每个实例对象都会动态获取对象的方法


在使用动态代理有几个前提条件, 一个是对应的实例对象,一个是扩展功能,而扩展功能是通过接口才能实现扩展,所以代理我的理解就是在于扩展功能的定义,即接口的定义,而实例对象就是调用对应的方法,而这个方法动态的,通过反射获取实例对象的方法


备注:一般动态代理代码都是作为一个工具类使用,例如:Retrofit网络请求框架 有使用动态代理               


1、定义扩展功能的接口

public interface IAdvice {void beforeMethod(Method method);void afterMethod(Method method);}

2、定义扩展功能的对象

 

public class AdviceImpl implements IAdvice {Long beginTime=(long) 0;Long endTime=(long) 0;@Overridepublic void beforeMethod(Method method) {// TODO Auto-generated method stubbeginTime=System.currentTimeMillis();System.out.println("实例方法1");}@Overridepublic void afterMethod(Method method) {// TODO Auto-generated method stub   endTime=System.currentTimeMillis();   System.out.println("实例方法2");   System.out.println("方法名称"+method.getName()+"run time of  "+(endTime-beginTime));}}

3、定义动态代理的方法

/*将目标类实例对象作为参数注入,供InvocationHandler调用;  *将代理类要实现的扩展功能抽象成一个接口,并把对象传入 *InvocationHandler实现类中调用对象的方法,就相当于执行了外界提供的扩展功能 */<span style="color:#ff0000;">//target是实例对象,方法内的Method是实例对象调用的方法,而advice是扩展功能提供的实例对象</span>private static Object getProxy(final Object target, final IAdvice advice) {Object obj = Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method,Object[] args) throws Throwable {advice.beforeMethod(method);System.out.println("动态代理获取的方法名称=" + method.getName()+" "+target.toString());//<span style="color:#ff0000;">方法反射返回的结果是resval     args 是实例对象方法内的参数,注意如果使用for循环,那么如果调用方法为空,                                                  那么报空指针错误</span>Object retVal = method.invoke(target, args);System.out.println("反射内容="+retVal);advice.afterMethod(method);return retVal;    <span style="color:#ff0000;">//除非实例对象调用的方法没有返回值(方法上没有返回值时用void),可以返回nul,否则报错</span>}});return obj;}}
4、调用动态代理方法

public static void main(String[] args) {// TODO Auto-generated method stubArrayList<String> target = new ArrayList<String>();target.add("aaa");AdviceImpl impl = new AdviceImpl();//方法获取的一个是代理,一个是target对象通过反射获取的方法及方法返回的接口@SuppressWarnings("unchecked")Collection<String> proxy3 = (Collection<String>) getProxy(target,impl);proxy3.add("sss");
  打印日志如下;

实例方法1动态代理获取的方法名称=add [aaa]参数==sss反射内容=true    //方法返回的值 ,因为方法是boolean,结果是true实例方法2方法名称addrun time of  0

5、调用动态代理方法

public static void main(String[] args) {// TODO Auto-generated method stubArrayList<String> target = new ArrayList<String>();target.add("aaa");AdviceImpl impl = new AdviceImpl();//方法获取的一个是代理,一个是target对象通过反射获取的方法及方法返回的接口@SuppressWarnings("unchecked")Collection<String> proxy3 = (Collection<String>) getProxy(target,impl);proxy3.add("sss");Object retVal = (Object) proxy3.add("gfdh");System.out.println("结果=" + retVal);

实例方法1动态代理获取的方法名称=add [aaa]参数==sss反射内容=true实例方法2方法名称addrun time of  0实例方法1动态代理获取的方法名称=add [aaa, sss]参数==gfdh反射内容=true实例方法2方法名称addrun time of  0结果=true

6、调用动态代理方法

public static void main(String[] args) {// TODO Auto-generated method stubArrayList<String> target = new ArrayList<String>();target.add("aaa");AdviceImpl impl = new AdviceImpl();//方法获取的一个是代理,一个是target对象通过反射获取的方法及方法返回的接口@SuppressWarnings("unchecked")Collection<String> proxy3 = (Collection<String>) getProxy(target,impl);//proxy3.add("sss");//Object retVal = (Object) proxy3.add("gfdh");//System.out.println("结果=" + retVal);System.out.println(proxy3.size());

  备注    target调用的size()方法返回的是整形类型

结果日志如下:

实例方法1动态代理获取的方法名称=size [aaa]反射内容=1实例方法2方法名称sizerun time of  01




1 0
原创粉丝点击