利用Cglib实现AOP
时间:2022-04-24
本文章向大家介绍利用Cglib实现AOP,主要内容包括Advice、语法糖、示例、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
前文讲了, 可以利用Spring, Guice等框架提供的容器实现AOP, 如果想绕过容器, 直接注入Class,
可以利用Cglib为对象加上动态代理,实现代码切入, 但是每次调用比较繁琐,
因此我们还需要给他加了一层语法糖, 使之更易用.
Advice
Spring带了一堆Advice, 我们只模拟实现环绕Advice, 以及增加了一个Clear切入的注解, 下面看具体实现.
1 /**
2 * 环绕Advie
3 *
4 * 可以加在类上, 或者方法上.
5 * 加在类上的话, 类中所有无@Clear注解的方法都会被切入
6 *
7 * @Before({CustomInterceptor.class, B.class})
8 * @Before(CustomInterceptor.class)
9 */
10 @Inherited
11 @Retention(RetentionPolicy.RUNTIME)
12 @Target({ElementType.TYPE, ElementType.METHOD})
13 public @interface Before {
14 Class<? extends Interceptor>[] value();
15 }
1 /**
2 * 清除Advice
3 *
4 * 可以清除方法上的指定Interceptor, 若不指定, 则清除所有切入.
5 *
6 * @Clear 清除所有
7 * @Clear(CustomInterceptor.class) 清除CustomInterceptor
8 */
9 @Inherited
10 @Retention(RetentionPolicy.RUNTIME)
11 @Target({ElementType.TYPE, ElementType.METHOD})
12 public @interface Clear {
13 Class<? extends Interceptor>[] value() default {};
14 }
语法糖
直接调用Cglib做切入, 需要setSuperClass, setCallback等等.
1 Enhancer enhancer = new Enhancer();
2 enhancer.setSuperclass(AopDemo.class);
3 enhancer.setCallback(new MethodInterceptorImpl());
4
5 AopDemo demo = (AopDemo) enhancer.create();
我们需要对Enhancer以及Callback进行封装, 减少复杂度
1 import java.util.concurrent.ConcurrentHashMap;
2
3 /**
4 * cglib中Enhancer的语法糖, 让注入更简单点
5 */
6 public class Enhancer {
7
8 private static final ConcurrentHashMap<String, Object> singleton = new ConcurrentHashMap<String, Object>();
9
10 private Enhancer(){}
11
12 public static <T> T enhance(Class<T> targetClass) {
13 return (T)net.sf.cglib.proxy.Enhancer.create(targetClass, new Callback());
14 }
15
16 public static <T> T enhance(Class<T> targetClass, Interceptor... injectInters) {
17 return (T)net.sf.cglib.proxy.Enhancer.create(targetClass, new Callback(injectInters));
18 }
19
20 public static <T> T getTarget(String singletonKey) {
21 return (T)singleton.get(singletonKey);
22 }
23
24 public static <T> T enhance(String singletonKey, Class<T> targetClass) {
25 Object target = singleton.get(singletonKey);
26 if (target == null) {
27 target = enhance(targetClass);
28 singleton.put(singletonKey, target);
29 }
30 return (T)target;
31 }
32
33 public static <T> T enhance(String singletonKey, Class<T> targetClass, Interceptor... injectInters) {
34 Object target = singleton.get(singletonKey);
35 if (target == null) {
36 target = enhance(targetClass, injectInters);
37 singleton.put(singletonKey, target);
38 }
39 return (T)target;
40 }
41 public static <T> T enhance(Object target) {
42 return (T)net.sf.cglib.proxy.Enhancer.create(target.getClass(), new Callback(target));
43 }
44
45 public static <T> T enhance(Object target, Interceptor... injectInters) {
46 return (T)net.sf.cglib.proxy.Enhancer.create(target.getClass(), new Callback(target, injectInters));
47 }
48 public static <T> T enhance(String singletonKey, Object target) {
49 Object result = singleton.get(singletonKey);
50 if (result == null) {
51 result = enhance(target);
52 singleton.put(singletonKey, result);
53 }
54 return (T)result;
55 }
56
57 public static <T> T enhance(String singletonKey, Object target, Interceptor... injectInters) {
58 Object result = singleton.get(singletonKey);
59 if (result == null) {
60 result = enhance(target, injectInters);
61 singleton.put(singletonKey, result);
62 }
63 return (T)result;
64 }
65
66 }
67
68
69 import net.sf.cglib.proxy.MethodInterceptor;
70 import net.sf.cglib.proxy.MethodProxy;
71
72 import java.lang.reflect.Method;
73 import java.util.HashSet;
74 import java.util.Set;
75
76 /**
77 * Callback.
78 */
79 class Callback implements MethodInterceptor {
80
81 private Object injectTarget = null;
82 private final Interceptor[] injectInters;
83
84 private static final Set<String> excludedMethodName = buildExcludedMethodName();
85 private static final InterceptorManager interMan = InterceptorManager.me();
86
87 public Callback() {
88 this.injectInters = InterceptorManager.NULL_INTERS;
89 }
90
91 public Callback(Interceptor... injectInters) {
92 checkInjectInterceptors(injectInters);
93 this.injectInters = injectInters;
94 }
95
96 public Callback(Object injectTarget, Interceptor... injectInters) {
97 if (injectTarget == null) {
98 throw new IllegalArgumentException("injectTarget can not be null.");
99 }
100 checkInjectInterceptors(injectInters);
101 this.injectTarget = injectTarget;
102 this.injectInters = injectInters;
103 }
104
105 private void checkInjectInterceptors(Interceptor... injectInters) {
106 if (injectInters == null) {
107 throw new IllegalArgumentException("injectInters can not be null.");
108 }
109 for (Interceptor inter : injectInters) {
110 if (inter == null) {
111 throw new IllegalArgumentException("interceptor in injectInters can not be null.");
112 }
113 }
114 }
115
116 public Object intercept(Object target, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
117 if (excludedMethodName.contains(method.getName())) {
118 // if (method.getName().equals("finalize"))
119 // return methodProxy.invokeSuper(target, args);
120 // return this.injectTarget != null ? methodProxy.invoke(this.injectTarget, args) : methodProxy.invokeSuper(target, args);
121
122 // 保留上面注释部分,此处为优化
123 if (this.injectTarget == null || method.getName().equals("finalize")) {
124 return methodProxy.invokeSuper(target, args);
125 } else {
126 return methodProxy.invoke(this.injectTarget, args);
127 }
128 }
129
130 if (this.injectTarget != null) {
131 target = this.injectTarget;
132 Interceptor[] finalInters = interMan.buildServiceMethodInterceptor(injectInters, target.getClass(), method);
133 Invocation invocation = new Invocation(target, method, args, methodProxy, finalInters);
134 invocation.useInjectTarget = true;
135 invocation.invoke();
136 return invocation.getReturnValue();
137 }
138 else {
139 Class<?> targetClass = target.getClass();
140 if (targetClass.getName().indexOf("$$EnhancerByCGLIB") != -1) {
141 targetClass = targetClass.getSuperclass();
142 }
143 Interceptor[] finalInters = interMan.buildServiceMethodInterceptor(injectInters, targetClass, method);
144 Invocation invocation = new Invocation(target, method, args, methodProxy, finalInters);
145 invocation.useInjectTarget = false;
146 invocation.invoke();
147 return invocation.getReturnValue();
148 }
149 }
150
151 private static final Set<String> buildExcludedMethodName() {
152 Set<String> excludedMethodName = new HashSet<String>();
153 Method[] methods = Object.class.getDeclaredMethods();
154 for (Method m : methods) {
155 excludedMethodName.add(m.getName());
156 }
157 // getClass() registerNatives() can not be enhanced
158 // excludedMethodName.remove("getClass");
159 // excludedMethodName.remove("registerNatives");
160 return excludedMethodName;
161 }
162 }
封装后可以直接使用一句话, 还可用来增强已有对象
1 AopDemo demo = Enhancer.enhance(AopDemo.class);
示例
1 @Before({PrivilegeInterceptor.class, LogInterceptor.class})
2 public class AopDemo {
3
4 public static void main(String[] args){
5 AopDemo demo = Enhancer.enhance(AopDemo.class);
6 demo.doSomething();
7 demo.doOtherthing();
8
9 }
10
11 public void doOtherthing() {
12 // 默认沿用Class的interceptor
13 System.out.println("do 111111111111111");
14 }
15
16 @Clear(PrivilegeInterceptor.class)
17 public void doSomething() {
18 // 手动清除了权限Interceptor
19 System.out.println("do 222222222222222");
20 }
21 }
1 public class LogInterceptor implements Interceptor{
2 @Override
3 public void intercept(Invocation inv) {
4 inv.invoke();
5 System.out.println("Log记录入库");
6 }
7 }
8
9 public class PrivilegeInterceptor implements Interceptor{
10 @Override
11 public void intercept(Invocation inv) {
12 System.out.println("鉴权成功");
13 inv.invoke();
14 }
15 }
doOtherthing执行结果
鉴权成功 do 111111111111111 Log记录入库
doSomething执行结果
do 222222222222222 Log记录入库
其他使用直接用来增强对象
1 AopDemo demoSinle1 = Enhancer.enhance(AopDemo.getInstance());
在enhance里new Interceptor
1 AopDemo demo3 = Enhancer.enhance(AopDemo.class, new Interceptor() {
2 @Override
3 public void intercept(Invocation inv) {
4 System.out.println("new before");
5 inv.invoke();
6 System.out.println("new after");
7 }
8 });
9 demo3.doSomething();
在需要增强的方法上写@Before
1 @Before(LogInterceptor.class)
2 public void doOtherthing() {
3 }
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- MybatisPlus分页插件无效解决方案
- springboot+mybatis打印sql
- jquery插件与扩展
- CNN一定需要池化层吗?
- RabbitMQ入门Demo,基于springboot
- 收藏|Pandas缺失值处理看这一篇就够了!
- Spring Boot项目页面报错 OTS parsing error: Failed to convert WOFF 2.0
- Spring Boot开启JSP页面热部署
- Springboot thymeleaf热部署
- Java初始化List的6种方式
- Java遍历Map对象的四种方式
- 【SpringBoot源码解析】第三章:SpringBoot通过打成war包的方式是如何启动的
- 让你编码嗨到停不下来的8个VSCode插件
- 【SpringBoot源码解析】第四章:SpringBoot是如何自动装配SpringMvc的
- 【SpringBoot源码解析】第二章:SpringBoot是如何通过内置Tomcat启动的