关于动态代理的内部原理请看前面的文章 深入理解动态代理。这次我们来谈谈动态代理的封装。
java通过Proxy.newProxyInstance()方法来动态获取我们需要的代理类字节文件,比如我们需要获取ArrayList的代理类,可以这么写:
List proxy = (List) Proxy.newProxyInstance(List.class.getClassLoader(), new Class[]{List.class}, new InvocationHandler(){
List list = new ArrayList();
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
return method.invoke(list, args);
}
});
proxy.add(111);
然后通过代理proxy来调用目标ArrayList的一些方法。
如果我们想在调用ArrayList的add()前后做一些动作,可以这么写:
List proxy = (List) Proxy.newProxyInstance(List.class.getClassLoader(), new Class[]{List.class}, new InvocationHandler(){
List list = new ArrayList();
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("--调用add()之前--");
Object obj = method.invoke(list, args);
System.out.println("--调用add()之后--");
// TODO Auto-generated method stub
return obj;
}
});
写到这里,我们想到一个问题,如何动态地将新添加的代码添加到指定的位置?也是就如何将我们新加入的两句 System.out.print语句动态添加到代理方法中?
这里有一个方法,就是把我们需要修改的操作封装到一个类的方法中,然后把这个类传给代理,这样代理就可以通过这个类来操作其方法了。具体代码如下:
1.首先创建一个修改操作接口
public interface Advice {
void before();
void after();
}
2.创建具体修改操作目标封装类
public class MyAdvice implements Advice{
@Override
public void before() {
// TODO Auto-generated method stub
System.out.println("--目标方法调用之前--");
}
@Override
public void after() {
// TODO Auto-generated method stub
System.out.println("--目标方法调用之后--");
}
}
3.封装代理方法:
private static Object getProxy(final Object target, final Advice advice){
//动态获取target的代理类
Object proxy = (Object) 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
advice.before();
Object obj = method.invoke(target, args);
advice.after();
return obj;
}
});
return proxy;
}
至此,代理获取的封装方法完成了,现在如果我们想在Arraylist调用add()前后插入我们的修改动作只需这么做:
List target = new ArrayList();
List proxy1 = (List) getProxy(target,new MyAdvice());
proxy1.add(111);
其实,这与AOP编程的思想如出一辙,我们也可以用这种方式简单实现AOP。