动态代理详解

动态代理

什么是动态代理?

动态代理就是,在程序运行期,创建目标对象的代理对象,并对目标对象中的方法进行功能性增强的一种技术。在生成代理对象的过程中,目标对象不变,代理对象中的方法是目标对象方法的增强方法。可以理解为运行期间,对象中方法的动态拦截,在拦截方法的前后执行功能操作。

代理类在程序运行期间,创建的代理对象称之为动态代理对象。这种情况下,创建的代理对象,并不是事先在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();

//执行这个userServicetest方法时,就会额外会执行一些其他逻辑

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,这是需要注意的。

 


版权声明:本文为m0_57237237原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。