使用 CGLIB 生成代理类

使用 CGLIB 生成代理类

CGLIBCode Generation Library),简单来说,就是一个代码生成类库。它可以在运行时候动态是生成某个类的子类。

此处使用前面定义的 Chinese 类,现在改为直接使用 CGLIB 来生成代理,这个代理类同样可以实现 Spring AOP 代理所达到的效果。

下面先为 CGLIB 提供一个拦截器实现类:

清单 12.AroundAdvice.java

显示更多上面这个 AroundAdvice.java 的作用就像前面介绍的 Around Advice,它可以在调用目标方法之前、调用目标方法之后织入增强处理。

接下来程序提供一个 ChineseProxyFactory 类,这个 ChineseProxyFactory 类会通过 CGLIB 来为

Chinese 生成代理类:

清单 13.ChineseProxyFactory.java

显示更多

上面粗体字代码就是使用 CGLIB  Enhancer 生成代理对象的关键代码,此时的 Enhancer 将以

Chinese 类作为目标类,以 AroundAdvice 对象作为”Advice”,程序将会生成一个 Chinese 的子类,这

个子类就是 CGLIB 生成代理类,它可作为 Chinese 对象使用,但它增强了 Chinese 类的方法。

测试 Chinese 代理类的主程序如下:

清单 14.Main.java

public class AroundAdvice implements MethodInterceptor

{

public Object intercept(Object target, Method method

, Object[] args, MethodProxy proxy)

throws java.lang.Throwable

{

System.out.println("执行目标方法之前,模拟开始事务 ...");

// 执行目标方法,并保存目标方法执行后的返回值

Object rvt = proxy.invokeSuper(target, new String[]{"被改变的参数"});

System.out.println("执行目标方法之后,模拟结束事务 ...");

return rvt + " 新增的内容";

}

}

public class ChineseProxyFactory

{

public static Chinese getAuthInstance()

{

Enhancer en = new Enhancer();

// 设置要代理的目标类

en.setSuperclass(Chinese.class);

// 设置要代理的拦截器

en.setCallback(new AroundAdvice());

// 生成代理类的实例

return (Chinese)en.create();

}

}显示更多

运行上面主程序,看到如下输出结果:

执行目标方法之前,模拟开始事务 …

正在执行 sayHello 方法 —

执行目标方法之后,模拟结束事务 …

被改变的参数 Hello , CGLIB 新增的内容

执行目标方法之前,模拟开始事务 …

我正在吃 : 被改变的参数

执行目标方法之后,模拟结束事务 …

class lee.Chinese$$EnhancerByCGLIB$$4bd097d9

从上面输出结果来看,CGLIB 生成的代理完全可以作为 Chinese 对象来使用,而且 CGLIB 代理对象的

sayHello()eat() 两个方法已经增加了事务控制(只是模拟),这个 CGLIB 代理其实就是 Spring AOP

所生成的 AOP 代理。

通过程序最后的输出,不难发现这个代理对象的实现类是

lee.Chinese$$EnhancerByCGLIB$$4bd097d9,这就是 CGLIB 所生成的代理类,这个代理类的格式与

前面 Spring AOP 所生成的代理类的格式完全相同。

这就是 Spring AOP 的根本所在:Spring AOP 就是通过 CGLIB 来动态地生成代理对象,这个代理对象

就是所谓的 AOP 代理,而 AOP 代理的方法则通过在目标对象的切入点动态地织入增强处理,从而完成

了对目标方法的增强。

结束语

AOP 广泛应用于处理一些具有横切性质的系统级服务,AOP 的出现是对 OOP 的良好补充,它使得开发

者能用更优雅的方式处理具有横切性质的服务。不管是那种 AOP 实现,不论是 AspectJ、还是 Spring

AOP,它们都需要动态地生成一个 AOP 代理类,区别只是生成 AOP 代理类的时机不同:AspectJ 采用

编译时生成 AOP 代理类,因此具有更好的性能,但需要使用特定的编译器进行处理;而 Spring AOP

采用运行时生成 AOP 代理类,因此无需使用特定编译器进行处理。由于 Spring AOP 需要在每次运行时

生成 AOP 代理,因此性能略差一些。

public class Main

{

public static void main(String[] args)

{

Chinese chin = ChineseProxyFactory.getAuthInstance();

System.out.println(chin.sayHello("孙悟空"));

chin.eat("西瓜");

System.out.println(chin.getClass());

}

}JDK Proxy

Cglib Proxy

只能代理接口

以继承的方式完成代理,不能代理被final修饰的类

JDK Proxy

Cglib Proxy

生成代理类时间

1'060.766

960.527

方法调用时间

0.008

0.003

来源

JDK原生代码

第三方库,更新频率较低

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
下面是一个使用CGLIB进行动态代理的简单例子: 假设我们有一个接口UserService,其中定义了一个方法getUserById(int id),我们希望对该方法进行拦截,记录方法的执行时间。我们可以使用CGLIB生成代理类,并通过MethodInterceptor来实现拦截逻辑。 首先,我们需要引入CGLIB的相关依赖: ```xml <!-- CGLIB --> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version> </dependency> ``` 然后,定义一个UserService的实现类UserServiceImpl: ```java public class UserServiceImpl implements UserService { @Override public User getUserById(int id) { // 模拟查询数据库 try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } return new User(id, "张三"); } } ``` 接下来,我们定义一个MethodInterceptor来实现拦截逻辑: ```java public class TimeInterceptor implements MethodInterceptor { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { long start = System.currentTimeMillis(); Object result = proxy.invokeSuper(obj, args); long end = System.currentTimeMillis(); System.out.println("方法" + method.getName() + "执行时间:" + (end - start) + "ms"); return result; } } ``` 最后,我们使用CGLIB生成代理类,将拦截逻辑加入到代理类中: ```java public class CglibTest { public static void main(String[] args) { UserServiceImpl userService = new UserServiceImpl(); Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(userService.getClass()); enhancer.setCallback(new TimeInterceptor()); UserService proxy = (UserService) enhancer.create(); proxy.getUserById(1); } } ``` 在上面的代码中,我们使用Enhancer类来生成代理类,将原始的UserService实现类作为代理类的父类,然后设置MethodInterceptor作为代理类的回调函数。最后,我们通过enhancer.create()方法来创建代理类,并将其强制转换为UserService接口类型,从而实现代理类的功能。 当我们调用代理类的getUserById方法时,MethodInterceptor中的intercept方法将被执行,从而实现了对方法的拦截。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

向前齐步走

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值