动态代理
什么是动态代理?
动态代理就是,在程序运行期,创建目标对象的代理对象,并对目标对象中的方法进行功能性增强的一种技术。在生成代理对象的过程中,目标对象不变,代理对象中的方法是目标对象方法的增强方法。可以理解为运行期间,对象中方法的动态拦截,在拦截方法的前后执行功能操作。
代理类在程序运行期间,创建的代理对象称之为动态代理对象。这种情况下,创建的代理对象,并不是事先在Java代码中定义好的。而是在运行期间,根据我们在动态代理对象中的“指示”,动态生成的。也就是说,你想获取哪个对象的代理,动态代理就会为你动态的生成这个对象的代理对象。动态代理可以对被代理对象的方法进行功能增强。有了动态代理的技术,那么就可以在不修改方法源码的情况下,增强被代理对象的方法的功能,在方法执行前后做任何你想做的事情。
比如,现在存在一个UserService类:
public classUserService{
public voidtest() {
System.out.println("test...");
}
}
此时,我们new一个UserService对象,然后执行test()方法,结果是显而易见的。
如果我们现在想在不修改UserService类的源码前提下,给test()增加额外逻辑,那么就可以使用动态代理机制来创建UserService对象了,比如:
UserService target =newUserService();
//通过cglib技术
Enhancer enhancer =newEnhancer();
enhancer.setSuperclass(UserService.class);
//定义额外逻辑,也就是代理逻辑
enhancer.setCallbacks(newCallback[]{newMethodInterceptor() {
@Override
publicObjectintercept(Object o, Method method, Object[] objects, MethodProxy
methodProxy)throwsThrowable {
System.out.println("before...");
Object result = methodProxy.invoke(target, objects);
System.out.println("after...");
returnresult;
}
}});
//动态代理所创建出来的UserService对象
UserService userService = (UserService) enhancer.create();
//执行这个userService的test方法时,就会额外会执行一些其他逻辑
userService.test();
得到的都是UserService对象,但是执行test()方法时的效果却不一样了,这就是代理所带来的效果。上面是通过cglib来实现的代理对象的创建,是基于父子类的,被代理类(UserService)是父类,代理类是子类,代理对象就是代理类的实例对象,代理类是由cglib创建的,对于程序员来说不用关心。
除开cglib技术,jdk本身也提供了一种创建代理对象的动态代理机制,但是它只能代理接口,也就是UserService得先有一个接口才能利用jdk动态代理机制来生成一个代理对象,比如:
public interfaceUserInterface{
public voidtest();
}
public classUserServiceimplementsUserInterface{
public voidtest() {
System.out.println("test...");
}
}
利用JDK动态代理来生成一个代理对象:
UserService target =newUserService();
// UserInterface接口的代理对象
Object proxy = Proxy.newProxyInstance(UserService.class.getClassLoader(),newClass[]
{UserInterface.class},newInvocationHandler() {
@Override
publicObjectinvoke(Object proxy, Method method, Object[] args)throwsThrowable {
System.out.println("before...");
Object result = method.invoke(target, args);
System.out.println("after...");
returnresult;
}
});
UserInterface userService = (UserInterface) proxy;
userService.test();
如果你把new Class[]{UserInterface.class},替换成new Class[]{UserService.class},允许代码会直接报错:
Exception in thread"main"java.lang.IllegalArgumentException:
com.zhouyu.service.UserService is not aninterface
表示一定要是个接口。
由于这个限制,所以产生的代理对象的类型是UserInterface,而不是UserService,这是需要注意的。