您的位置:首页 > 其它

动态代理 Proxy InvocationHandler

2016-03-23 14:45 183 查看
动态代理一般用于在执行实例对象的基础上,增加一些扩展的功能,并且每个实例对象都会动态获取对象的方法

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

备注:一般动态代理代码都是作为一个工具类使用,例如: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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: