当前位置: 首页 > 图灵资讯 > 技术篇> CGLIB动态代理

CGLIB动态代理

来源:图灵教育
时间:2023-06-11 09:19:00

1.引入依赖102

CGLIB既可以代理界面,也可以代理类别。底层是通过继承来实现的。因此,代理的目标类别不能用final来修改。

使用CGLIB,需要引入其依赖性:

<dependency>  <groupId>cglib</groupId>  <artifactId>cglib</artifactId>  <version>3.3.0</version></dependency>

2.具体实现102

我们准备了一个未实现接口的类别,如下:

package com.powernode.proxy.service;/** * 目标类  动态代理CGLIB  102 **/public class UserService {    // 目标方法    public boolean login(String username, String password){        System.out.println(”系统正在验证身份...");        if ("admin".equals(username) && "123".equals(password)) {            return true;        }        return false;    }    // 目标方法    public void logout(){        System.out.println(”系统正在退出...");    }}

在内存中使用CGLIB为UserService类生成代理类,并创建对象:

package com.powernode.proxy.client;import com.powernode.proxy.service.TimerMethodInterceptor;import com.powernode.proxy.service.UserService;import net.sf.cglib.proxy.Enhancer;/////  102public class Client {    public static void main(String[] args) {        // 创建字节码增强器对象        // 这个对象是CGLIB库的核心对象,依靠它来生成代理类。        Enhancer enhancer = new Enhancer();        // 告诉CGLIB父类是谁。        Enhancer enhancer = new Enhancer();        // 告诉CGLIB父类是谁。告诉CGLIB目标类是谁。        enhancer.setSuperclass(UserService.class);        // 设置回调(相当于JDK动态代理中的调用处理器。InvocationHandler)        // InvocationHandler接口不在CGLIB中,方法拦截器接口:MethodInterceptor        enhancer.setCallback(new TimerMethodInterceptor());        // 创建代理对象        // 这一步将做两件事:        // 第一件事:在内存中生成UserService子类,其实是代理类的字节码。        // 第二件事:创建代理对象。        // 父类是UserService,代理类子类必须是UserService        UserService userServiceProxy = (UserService) enhancer.create();        // 建议您对CGLIB动态代理生成的代理对象的名称格式有一点印象。        // 根据这个名字,可以推测框架底部是否使用CGLIB动态代理        System.out.println(userServiceProxy);        // 调用代理对象的代理方法。        boolean success = userServiceProxy.login("admin", "123");        System.out.println(success ? “成功登录” : “登录失败”;        userServiceProxy.logout();    }}// 底层的本质///class UserService$$EnhancerByCGLIB$$82cb55e3 extends UserService{}

与JDK动态代理原理相似,在CGLIB中需要提供的不是InvocationHandler,而是:net.sf.cglib.proxy.MethodInterceptor

编写Methodinterceptor接口实现类:

在Methodinterceptor接口中,intercept()有四个参数:

第一个参数:目标对象

第二个参数:目标方法

第三个参数:调用目标方法时的实际参数

第四个参数:代理方法

package com.powernode.proxy.service;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;import java.lang.reflect.Method;/** * 动态代理CGLIB  102 **/public class TimerMethodInterceptor implements MethodInterceptor {    @Override    public Object intercept(Object target, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {        // 前面增强        long begin = System.currentTimeMillis();        // 目标对象的目标方法如何调用?        Object retValue = methodProxy.invokeSuper(target, objects);        // 后面增强        long end = System.currentTimeMillis();        System.out.println("耗时"+(end - begin)+"毫秒");        return retValue;    }}

对于高版JDK,如果使用CGLIB,则需要在启动项中添加两个启动参数:

CGLIB动态代理_CGLIB动态代理

●--add-opensjava.base/java.lang=ALL-UNNAMED

●--add-opensjava.base/sun.net.util=ALL-UNNAMED

CGLIB动态代理_CGLIB动态代理_02