前文讲了, 可以利用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 }
View Code

相关文章:

  • 2021-06-20
  • 2022-12-23
  • 2022-12-23
  • 2021-12-13
猜你喜欢
  • 2021-07-12
  • 2021-08-08
  • 2021-11-12
  • 2022-12-23
  • 2021-07-13
  • 2022-12-23
  • 2021-06-23
相关资源
相似解决方案