Java-CGLib动态代理

标签: cglib动态代理
1742人阅读 评论(0) 收藏 举报
分类:

导读

Spring-AOP基础知识

Java-JDK动态代理

Java-CGLib动态代理


问题

另一篇博文中的问题

性能监视横切逻辑代码


CGLib动态代理和JDK动态代理的区别

我们知道使用JDK创建代理时只能为接口创建代理实例。我们从Proxy的newProxyInstance方法中可以看出

    @CallerSensitive
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)

第二个参数interfaces就是需要代理实例实现的接口列表。

对于没有通用接口定义业务方法的类,该如何动态创建代理实例呢?
JDK动态代理技术显然无能为力了,CGLib作为一个替代者,很好地解决了这个问题


CGLib概述

CGLib采用底层的字节码技术,可以为一个类创建子类,在子类中采用方法拦截的技术拦截所有父类方法的调用并顺势织入横切逻辑。


改造

代码已托管到Github—> https://github.com/yangshangwei/SpringMaster

首先在我们的java maven工程中 添加依赖

    <!-- https://mvnrepository.com/artifact/cglib/cglib -->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>${cglib.version}</version>
        </dependency>

使用的版本为 3.2.5

这里写图片描述

package com.xgj.aop.base.cglib;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CglibProxy implements MethodInterceptor {

    private Enhancer enhancer = new Enhancer();

    public Object getProxy(Class clazz) {
        // 设置需要创建的子类的类
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        // 通过字节码动态创建子类实例
        return enhancer.create();

    }

    // 拦截父类所有方法的调用
    @Override
    public Object intercept(Object obj, Method method, Object[] args,
            MethodProxy proxy) throws Throwable {
        // 横切逻辑代码
        PerformanceMonitor.begin(obj.getClass().getName() + "."
                + method.getName());
        // 业务逻辑,通过代理类调用父类中的方法
        Object result = proxy.invokeSuper(obj, args);
        // 横切逻辑代码
        PerformanceMonitor.end();
        return result;
    }

}

上述代码,我们通过getProxy(Class clazz)方法为一个类创建动态代理对象,该代理对象通过扩展clazz实现代理。

在这个代理对象中,织入性能监视的横切逻辑。

public Object intercept(Object obj, Method method, Object[] args,MethodProxy proxy) 是CGLib定义的Interceptor接口方法,它拦截所有目标类方法中的调用。

其中

  • obj表述目标类的实例

  • method为目标类方法的反射对象

  • args为方法的动态入参

  • proxy为代理类的实例

测试类

通过CglibProxy为ForumSerivceImpl类创建代理对象,并测试代理对象的方法

package com.xgj.aop.base.cglib;

public class ForumServiceTest {

    public static void main(String[] args) {

        CglibProxy cglibProxy = new CglibProxy();
        // 通过动态生成子类的方式创建代理类
        ForumServiceImpl forumService = (ForumServiceImpl) cglibProxy
                .getProxy(ForumServiceImpl.class);
        // 调用代理类的业务方法
        forumService.removeTopic(1);
        forumService.removeForum(2);
    }
}

运行结果

这里写图片描述

通过输出,可以看到除了两个业务方法中都织入了性能监控的逻辑外,还发现代理类的名字变成了

com.xgj.aop.base.cglib.ForumServiceImpl$$EnhancerByCGLIB$$2088954a

这个特殊的类就是CGLib为ForumServiceImpl动态创建的子类。

注意:由于cglib采用动态创建子类的方式生成代理对象,所以不能对目标类中的final或者private方法进行代理

1
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:1115159次
    • 积分:17006
    • 等级:
    • 排名:第662名
    • 原创:452篇
    • 转载:0篇
    • 译文:5篇
    • 评论:144条
    WeChat
      欢迎关注我的公众号,干货只有干货,还有更多惊喜和资源在等着你
    博客专栏