cglib是一种动态代理技术,可以针对类来生成一个代理对象。

    比如,我们现有一个UserService类:

    1. public class UserService {
    2. public void test(){
    3. System.out.println("test");
    4. }
    5. }

    现在利用cglib对UserService类中的test()方法进行增强:

    1. public class Main {
    2. public static void main(String[] args) {
    3. final UserService target = new UserService();
    4. Enhancer enhancer = new Enhancer();
    5. enhancer.setSuperclass(UserService.class);
    6. enhancer.setCallbacks(new Callback[]{new MethodInterceptor() {
    7. @Override
    8. public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    9. // test方法增加了其他逻辑
    10. if (method.getName().equals("test")) {
    11. System.out.println("before...");
    12. Object result = method.invoke(target, objects);
    13. System.out.println("after...");
    14. return result;
    15. }
    16. // 其他方法正常执行
    17. return method.invoke(target, objects);
    18. }
    19. }});
    20. UserService userService = (UserService) enhancer.create();
    21. userService.test();
    22. }
    23. }

    在分析底层源码实现之前,我们先来试试,cglib能否代理接口,定义一个UserInterface接口:

    1. public interface UserInterface {
    2. public void test();
    3. }

    然后利用cglib来代理一个接口:

    1. public class Main {
    2. public static void main(String[] args) {
    3. Enhancer enhancer = new Enhancer();
    4. enhancer.setSuperclass(UserInterface.class);
    5. enhancer.setCallbacks(new Callback[]{new MethodInterceptor() {
    6. @Override
    7. public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    8. if (method.getName().equals("test")) {
    9. System.out.println("切面逻辑...");
    10. }
    11. return null;
    12. }
    13. }});
    14. UserInterface userInterface = (UserInterface) enhancer.create();
    15. userInterface.test();
    16. }
    17. }

    也是可以正常运行的,那么用cglib代理一个类和代理一个接口的底层有什么区别呢?我们继续分析。

    我们知道,既然要生成一个代理对象,那么就肯定需要一个代理类,只不过当我们用cglib时,这个代理类是由cglib生成的,那么我们能不能看到这个代理类是怎么生成的呢?

    可以!我们只需要在运行时加上:

    1. -Dcglib.debugLocation=D:\IdeaProjects\cglib\cglib\target\classes

    cglib就会将生成的代理类放到上面所指定的路径上。那么我们分别来看看cglib代理类和接口时所产生的代理类是怎样的。

    UserService的代理类,我保留了类中比较关键的信息:

    1. public class UserService$$EnhancerByCGLIB$$4d890297 extends UserService implements Factory {
    2. final void CGLIB$test$0() {
    3. super.test();
    4. }
    5. public final void test() {
    6. MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
    7. if (var10000 == null) {
    8. CGLIB$BIND_CALLBACKS(this);
    9. var10000 = this.CGLIB$CALLBACK_0;
    10. }
    11. if (var10000 != null) {
    12. var10000.intercept(this, CGLIB$test$0$Method, CGLIB$emptyArgs, CGLIB$test$0$Proxy);
    13. } else {
    14. super.test();
    15. }
    16. }
    17. }

    UserInterface的代理类,我保留了类中比较关键的信息:

    1. public class UserInterface$$EnhancerByCGLIB$$20ecfdd implements UserInterface, Factory {
    2. final void CGLIB$test$4() {
    3. super.test();
    4. }
    5. public final void test() {
    6. MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
    7. if (var10000 == null) {
    8. CGLIB$BIND_CALLBACKS(this);
    9. var10000 = this.CGLIB$CALLBACK_0;
    10. }
    11. if (var10000 != null) {
    12. var10000.intercept(this, CGLIB$test$4$Method, CGLIB$emptyArgs, CGLIB$test$4$Proxy);
    13. } else {
    14. super.test();
    15. }
    16. }
    17. }

    可以发现这两种情况所产生的类区别不大,无非就是UserService代理类是UserService的子类,UserInterface代理类实现了UserInterface。

    我们可以发现在代理类中(以上两个任选一个),都存在一个test()方法和CGLIB$test$0()(以UserService代理类举例子):

    test()方法内会去调用所设置的Callbacks中的intercept(),相当于执行增强逻辑,如果没有Callbacks,则会执行super.test(),那么我们自然能想到,如果不设置Callbacks,那是不是就能正常执行呢?比如这样:

    1. Enhancer enhancer = new Enhancer();
    2. enhancer.setSuperclass(UserService.class);
    3. UserService userService = (UserService) enhancer.create();
    4. userService.test();

    不好意思,运行这段代码时,cglib在构造代理对象时就会报一个没有Callbacks的空指针异常,所以我们无法看到我们想看到的效果。

    但是这并不影响我们继续研究,我们再来看代理类中的另外一个方法:

    1. final void CGLIB$test$0() {
    2. super.test();
    3. }

    这个方法我们并不能直接调用,要通过所设置的Callback,也就是MethodInterceptor中的MethodProxy对象来调用,MethodProxy对象表示方法代理,举个例子,假如UserService代理对象在执行test()方法,那么当执行流程进入到intercept()方法时,MethodProxy对象表示的就是test()方法,但是我们现在知道了在UserService类和UserService代理类中都有test()方法,所以MethodProxy对象代理的就是这两个test(),比如:

    1. // o表示当前代理对象,target表示被代理对象
    2. // 执行UserService代理对象的CGLIB$test$0()方法,也就是执行UserService代理对象的父类的test()
    3. Object result = methodProxy.invokeSuper(o, objects);
    4. // 执行UserService对象的CGLIB$test$0()方法,会报错,调用invokerSuper只能传入代理对象
    5. Object result = methodProxy.invokeSuper(target, objects);
    6. // 执行UserService对象的test()
    7. Object result = methodProxy.invoke(target, objects);
    8. // 执行UserService代理对象的test(); 又会进到拦截器,栈溢出
    9. Object result = methodProxy.invoke(o, objects);

    所以在执行methodProxy.invokeSuper()方法时,就会去执行CGLIB$test$0()方法。

    我们来总结一下cglib的大概工作原理是:cglib会根据所设置的Superclass,生成代理类作为其子类,并且会重写Superclass中的方法,Superclass中的某一个方法,比如test(),相应的在代理类中会对应两个方法,一个是重写的test(),用来执行增强逻辑,一个是CGLIB$test$0(),会直接调用super.test(),是让MethodProxy对象来用的。

    那接下来的问题就是:

    1. 代理类是怎么生成的?
    2. MethodProxy是怎么实现的?

    我们下篇文章见。