动态代理 Proxy InvocationHandler
2016-03-23 14:45
183 查看
动态代理一般用于在执行实例对象的基础上,增加一些扩展的功能,并且每个实例对象都会动态获取对象的方法
在使用动态代理有几个前提条件, 一个是对应的实例对象,一个是扩展功能,而扩展功能是通过接口才能实现扩展,所以代理我的理解就是在于扩展功能的定义,即接口的定义,而实例对象就是调用对应的方法,而这个方法动态的,通过反射获取实例对象的方法
备注:一般动态代理代码都是作为一个工具类使用,例如:Retrofit网络请求框架 有使用动态代理
1、定义扩展功能的接口
2、定义扩展功能的对象
3、定义动态代理的方法
5、调用动态代理方法
6、调用动态代理方法
备注 target调用的size()方法返回的是整形类型
结果日志如下:
在使用动态代理有几个前提条件, 一个是对应的实例对象,一个是扩展功能,而扩展功能是通过接口才能实现扩展,所以代理我的理解就是在于扩展功能的定义,即接口的定义,而实例对象就是调用对应的方法,而这个方法动态的,通过反射获取实例对象的方法
备注:一般动态代理代码都是作为一个工具类使用,例如: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; @Override public void beforeMethod(Method method) { // TODO Auto-generated method stub beginTime=System.currentTimeMillis(); System.out.println("实例方法1"); } @Override public 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() { @Override public 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 stub ArrayList<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 stub ArrayList<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 stub ArrayList<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 0 1
相关文章推荐
- Cg入门1:输入输出和语义
- mysql 按照姓氏排序
- 转:使用gradle 构建编译程序
- github 操作指南
- Jquery 返回顶部
- Target 'Pods' of project 'Pods' was rejected as an implicit dependency for 'libPods.a' because its a
- debian添加删除用户
- 集成gitHub的几款常用工具
- 链表中的添加节点和删除节点的操作
- ASP.NET MVC的TextBoxFor()和TextBox()
- Spark中常用工具类Utils的简明介绍
- Tab切换
- HTTP错误码集合,及错误原因
- javascript基本知识小结--命名空间,函数
- 安卓组件的设计思想
- linux路由添加
- twisted理论基础
- Microsoft Azure系列之二 Microsoft Azure概述
- Gradle编译的APK反编译看不到VersionCode
- [从头学数学] 第149节 一元二次方程 小结与复习题