动态代理
优点
动态代理与静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)。
这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。
在本示例中看不出来,因为invoke方法体内嵌入了具体的外围业务(记录任务处理前后时间并计算时间差),实际中可以类似Spring AOP那样配置外围业务。
缺点
诚然,Proxy已经设计得非常优美,但是还是有一点点小小的遗憾之处,那就是它始终无法摆脱仅支持interface代理的桎梏,因为它的设计注定了这个遗憾。
回想一下那些动态生成的代理类的继承关系图,它们已经注定有一个共同的父类叫Proxy。
Java的继承机制注定了这些动态代理类们无法实现对class的动态代理,原因是多继承在Java中本质上就行不通。
有很多条理由,人们可以否定对 class代理的必要性,但是同样有一些理由,相信支持class动态代理会更美好。
接口和类的划分,本就不是很明显,只是到了Java中才变得如此的细化。如果只从方法的声明及是否被定义来考量,
有一种两者的混合体,它的名字叫抽象类。实现对抽象类的动态代理,相信也有其内在的价值。
此外,还有一些历史遗留的类,它们将因为没有实现任何接口而从此与动态代理永世无缘。
如此种种,不得不说是一个小小的遗憾。但是,不完美并不等于不伟大,伟大是一种本质,Java动态代理就是佐例。
1,通过实现 InvocationHandler 接口创建自己的调用处理器;
public class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler() {
super();
}
public MyInvocationHandler(Object target) {
super();
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("getName".equals(method.getName())) {
System.out.println("++++++before " + method.getName() + "++++++");
Object result = method.invoke(target, args);
System.out.println("++++++after " + method.getName() + "++++++");
return result;
} else {
Object result = method.invoke(target, args);
return result;
}
}
}
2.代理接口
public interface userService {
public abstract String getName(int id);
public abstract int getAge(int id);
}
3.代理真实对象
public class userServiceImpl implements userService {
@Override
public String getName(int id) {
return "tom";
}
@Override
public int getAge(int id) {
return 10;
}
}
4,测试类
通过反射得到单前代理的对象实例测试
@Test
public void run() {
userService user = new userServiceImpl();
InvocationHandler invocationHandler = new MyInvocationHandler(user);
userService userServiceProxy = (userService) Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces()
, invocationHandler);
System.out.println(userServiceProxy.getName(1));
System.out.println(userServiceProxy.getAge(1));
}
通过 Proxy 为包括 Interface 接口在内的一组接口动态创建代理类的类对象的测试
@Test
public void run1() {
userService user = new userServiceImpl();
InvocationHandler invocationHandler = new MyInvocationHandler(user);
userService userServiceProxy = (userService) Proxy.newProxyInstance(userService.class.getClassLoader(), new Class[]{userService.class}, invocationHandler);
System.out.println(userServiceProxy.getName(1));
System.out.println(userServiceProxy.getAge(1));
}
对于接口的代理,JDK Poxy几乎完美,但是不能对类进行代理:
但是cglib很好的解决对类的代理,可以参考:cglib详解
SpringAOP底层实现就是一个很好的动态代理,对于SpringAOP,可以参考:SpringAOP 代理详解