CGLIB动态代理应用和原理
来源:互联网 发布:u盘启动安装linux系统 编辑:程序博客网 时间:2024/06/05 12:33
CGLIB动态代理是一种在运行时增强字节码的技术,它通过将代理对象设置为被目标对象的子类来增强目标方法。
1.CGLIB动态代理在Spring AOP中的应用
下面我们实现一个Spring AOP的小例子
首先定义一个目标类,其中包含了我们要增强的方法
@Componentpublic class Chinese implements Person { public String sayHello(String name) { System.out.println("正在执行sayHello方法"); return name + " Hello, Spring Aop"; } public void eat(String food) { System.out.println("我正在吃: " + food); }}接着定义一个后置增强处理切面
@Aspectpublic class AfterReturningAdviceTest { @AfterReturning(returning = "rvt", pointcut = "execution(* com.cmb.china.springaop.*.*(..))") public void log(Object rvt) { System.out.println("获取目标方法返回值: " + rvt); System.out.println("模拟记录日志功能"); }}在定义一个环绕增强处理切面
@Aspectpublic class AroundAdviceTest { @Around("execution(* com.cmb.china.springaop.*.*(..))") public Object processTx(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("执行目标方法之前,模拟开始事务..."); Object rvt = joinPoint.proceed(new String[]{"被改变的参数"}); System.out.println("执行目标方法之后,模拟结束事务"); return rvt + " 新增的内容"; }}最后在Spring配置文件中开启AspectJ支持
<context:component-scan base-package="com.cmb.china"> <context:include-filter type="annotation" expression="org.aspectj.lang.annotation.Aspect"/></context:component-scan><aop:aspectj-autoproxy/>进行测试
public class BeanTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Person chinese = context.getBean("chinese", Person.class); System.out.println(chinese.sayHello("张三")); chinese.eat("西瓜"); System.out.println(chinese.getClass()); }}运行结果
执行目标方法之前,模拟开始事务...
正在执行sayHello方法
执行目标方法之后,模拟结束事务
获取目标方法返回值: 被改变的参数 Hello, Spring Aop 新增的内容
模拟记录日志功能
被改变的参数 Hello, Spring Aop 新增的内容
执行目标方法之前,模拟开始事务...
我正在吃: 被改变的参数
执行目标方法之后,模拟结束事务
获取目标方法返回值: null 新增的内容
模拟记录日志功能
class com.cmb.china.springaop.Chinese$$EnhancerBySpringCGLIB$$464c626a
从结果中可以看出,切面已经织入了目标方法,在执行目标方法的前后执行了我们在切面中定义的增强方法。@AfterReturning注解是在目标方法执行之后织入增强方法,@Around注解是在目标方法执行前后织入增强方法。从chinese.getClass()的结果com.cmb.china.springaop.Chinese&$$EnhancerBySpringCGLIB$$464c626a可知,动态代理类是由CGLIB通过Enhancer生成的。
2.CGLIB动态代理类的生成过程
下面我们再来写一个例子直观感受一下CGLIB生成代理类的过程
先为CGLIB提供一个拦截器实现类
public class AroundAdvice implements MethodInterceptor { public Object intercept(Object target, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("执行目标方法之前,模拟事务开始"); Object rvt = methodProxy.invokeSuper(target, new String[]{"被改变的参数"}); System.out.println("执行目标方法之后,模拟结束事务..."); return rvt + " 新增的内容"; }}AroundAdvice实现了MethodInterceptor接口,实现了intercept方法,其中的target是目标对象,method是目标方法,args是目标方法的实际入参,methodPorxy是目标方法的代理方法。
下面实现一个为Chinese对象生成代理类的工厂
public class ChineseProxyFactory { public static Chinese getAuthInstance() { Enhancer enhancer = new Enhancer(); // 通过运行时修改字节码设置代理类的父类 enhancer.setSuperclass(Chinese.class); enhancer.setCallback(new AroundAdvice()); return (Chinese) enhancer.create(); }}测试
public class Test { public static void main(String[] args) { Chinese chinese = ChineseProxyFactory.getAuthInstance(); System.out.println(chinese.sayHello("孙悟空")); chinese.eat("西瓜"); System.out.println(chinese.getClass()); }}运行结果
执行目标方法之前,模拟事务开始
正在执行sayHello方法
执行目标方法之前,模拟事务开始
执行目标方法之前,模拟事务开始
执行目标方法之后,模拟结束事务...
执行目标方法之后,模拟结束事务...
被改变的参数 Hello, Spring Aop 新增的内容
执行目标方法之前,模拟事务开始
我正在吃: 被改变的参数
执行目标方法之前,模拟事务开始
执行目标方法之前,模拟事务开始
执行目标方法之后,模拟结束事务...
执行目标方法之后,模拟结束事务...
class com.cmb.china.springaop.Chinese$$EnhancerByCGLIB$$83b98ab0
正在执行sayHello方法
执行目标方法之前,模拟事务开始
执行目标方法之前,模拟事务开始
执行目标方法之后,模拟结束事务...
执行目标方法之后,模拟结束事务...
被改变的参数 Hello, Spring Aop 新增的内容
执行目标方法之前,模拟事务开始
我正在吃: 被改变的参数
执行目标方法之前,模拟事务开始
执行目标方法之前,模拟事务开始
执行目标方法之后,模拟结束事务...
执行目标方法之后,模拟结束事务...
class com.cmb.china.springaop.Chinese$$EnhancerByCGLIB$$83b98ab0
阅读全文
0 0
- CGLIB动态代理应用和原理
- CGLIB动态代理应用
- CGLIB动态代理应用
- Cglib实现动态代理原理
- Cglib实现动态代理原理
- cglib动态代理实现原理
- Java动态代理之JDK动态代理和CGLib动态代理 面向切面编程AOP原理
- JDK动态代理和CGLIB动态代理
- JDK动态代理和CGLIB动态代理
- java动态代理和cglib动态代理
- JDK动态代理和Cglib动态代理
- Cglib动态代理和jdk动态代理
- jdk动态代理和CGlib动态代理
- jdk动态代理和cglib动态代理
- java动态代理和cglib动态代理
- Java动态代理和cglib动态代理
- java动态代理和cglib
- Java 动态代理和CGlib
- eclipse安装svn
- android支持横屏旋转
- Frequent Subsets Problem
- loadrunner Web_类函数之web_set_secure_proxy()
- spring中通过constructor来注入参数的四种方式
- CGLIB动态代理应用和原理
- 《机器学习实战》学习笔记(4)—— Logistic 回归
- android studio 将 cpp 文件编译的so 库 给其它工程使用
- 冠词
- keepalived 配置文件参数详解
- Simplex Noise(一)
- window远程桌面 无法黏贴
- LCA练习题
- 面向对象六大原则及单例模式