首页 > 编程语言 >AOP源码解析:AspectJExpressionPointcutAdvisor类

AOP源码解析:AspectJExpressionPointcutAdvisor类

时间:2023-08-18 18:06:38浏览次数:47  
标签:return AspectJExpressionPointcutAdvisor private 源码 shadowMatch AOP PRIMITIVES nu

  先看看 AspectJExpressionPointcutAdvisor 的类图

AOP源码解析:AspectJExpressionPointcutAdvisor类_Express

  再了解一下切点(Pointcut)表达式,它指定触发advice的方法,可以精确到返回参数,参数类型,方法名

1 package concert;
2 
3 public interface Performance {
4     void perform();
5 }

AOP源码解析:AspectJExpressionPointcutAdvisor类_类图_02

  AspectJExpressionPointcutAdvisor 源码,官方文档解释说这是可以用于任何AspectJ切入点表达式的 Spring AOP Advisor。

1 @SuppressWarnings("serial")
 2 public class AspectJExpressionPointcutAdvisor extends AbstractGenericPointcutAdvisor implements BeanFactoryAware {
 3 
 4     private final AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); // AspectJ表达式切点匹配器
 5 
 6 
 7     public void setExpression(@Nullable String expression) {
 8         this.pointcut.setExpression(expression);
 9     }
10 
11     @Nullable
12     public String getExpression() {
13         return this.pointcut.getExpression();
14     }
15 
16     public void setLocation(@Nullable String location) {
17         this.pointcut.setLocation(location);
18     }
19 
20     @Nullable
21     public String getLocation() {
22         return this.pointcut.getLocation();
23     }
24 
25     public void setParameterNames(String... names) {
26         this.pointcut.setParameterNames(names);
27     }
28 
29     public void setParameterTypes(Class<?>... types) {
30         this.pointcut.setParameterTypes(types);
31     }
32 
33     @Override
34     public void setBeanFactory(BeanFactory beanFactory) {
35         this.pointcut.setBeanFactory(beanFactory);
36     }
37 
38     @Override
39     public Pointcut getPointcut() {
40         return this.pointcut;
41     }
42 
43 }

        再看看 AspectJExpressionPointcutAdvisor 的抽象父类 AbstractGenericPointcutAdvisor 的源码

1 @SuppressWarnings("serial")
 2 public abstract class AbstractGenericPointcutAdvisor extends AbstractPointcutAdvisor {
 3 
 4     private Advice advice = EMPTY_ADVICE; // Advisor接口中定义的占位符
 5 
 6 
 7     /**
 8      * Specify the advice that this advisor should apply.
 9      */
10     public void setAdvice(Advice advice) {
11         this.advice = advice;
12     }
13 
14     @Override
15     public Advice getAdvice() {
16         return this.advice;
17     }
18 
19 
20     @Override
21     public String toString() {
22         return getClass().getName() + ": advice [" + getAdvice() + "]";
23     }
24 
25 }

  看完源码后,可以了解到一个 AspectJExpressionPointcutAdvisor 是用来处理对应 AspectJ 的 advice 和切点的,可以在代码中看见有advice的设置和获取、切点表达式的一些处理、设置切点的Bean工厂,还有获取该切点。该 AspectJExpressionPointcutAdvisor 创建了一个 AspectJExpressionPointcut,它们之间的关系是一对一的组合关系,如同字面意思,AspectJExpressionPointcut 与切点表达式有关。

  下面是 AspectJExpressionPointcut 的类图

AOP源码解析:AspectJExpressionPointcutAdvisor类_Express_03

   AspectJExpressionPointcut 的源码(过长折叠起来了)

1 public class AspectJExpressionPointcut extends AbstractExpressionPointcut implements ClassFilter, IntroductionAwareMethodMatcher, BeanFactoryAware {
  2     private static final Set<PointcutPrimitive> SUPPORTED_PRIMITIVES = new HashSet();
  3     private static final Log logger;
  4     @Nullable
  5     private Class<?> pointcutDeclarationScope;
  6     private String[] pointcutParameterNames = new String[0];
  7     private Class<?>[] pointcutParameterTypes = new Class[0];
  8     @Nullable
  9     private BeanFactory beanFactory;
 10     @Nullable
 11     private transient ClassLoader pointcutClassLoader;
 12     @Nullable
 13     private transient PointcutExpression pointcutExpression;
 14     private transient Map<Method, ShadowMatch> shadowMatchCache = new ConcurrentHashMap(32);
 15 
 16     public AspectJExpressionPointcut() {
 17     }
 18 
 19     public AspectJExpressionPointcut(Class<?> declarationScope, String[] paramNames, Class<?>[] paramTypes) {
 20         this.pointcutDeclarationScope = declarationScope;
 21         if (paramNames.length != paramTypes.length) {
 22             throw new IllegalStateException("Number of pointcut parameter names must match number of pointcut parameter types");
 23         } else {
 24             this.pointcutParameterNames = paramNames;
 25             this.pointcutParameterTypes = paramTypes;
 26         }
 27     }
 28 
 29     public void setPointcutDeclarationScope(Class<?> pointcutDeclarationScope) {
 30         this.pointcutDeclarationScope = pointcutDeclarationScope;
 31     }
 32 
 33     public void setParameterNames(String... names) {
 34         this.pointcutParameterNames = names;
 35     }
 36 
 37     public void setParameterTypes(Class<?>... types) {
 38         this.pointcutParameterTypes = types;
 39     }
 40 
 41     public void setBeanFactory(BeanFactory beanFactory) {
 42         this.beanFactory = beanFactory;
 43     }
 44 
 45     public ClassFilter getClassFilter() {
 46         this.obtainPointcutExpression();
 47         return this;
 48     }
 49 
 50     public MethodMatcher getMethodMatcher() {
 51         this.obtainPointcutExpression();
 52         return this;
 53     }
 54 
 55     private PointcutExpression obtainPointcutExpression() {
 56         if (this.getExpression() == null) {
 57             throw new IllegalStateException("Must set property 'expression' before attempting to match");
 58         } else {
 59             if (this.pointcutExpression == null) {
 60                 this.pointcutClassLoader = this.determinePointcutClassLoader();
 61                 this.pointcutExpression = this.buildPointcutExpression(this.pointcutClassLoader);
 62             }
 63 
 64             return this.pointcutExpression;
 65         }
 66     }
 67 
 68     @Nullable
 69     private ClassLoader determinePointcutClassLoader() {
 70         if (this.beanFactory instanceof ConfigurableBeanFactory) {
 71             return ((ConfigurableBeanFactory)this.beanFactory).getBeanClassLoader();
 72         } else {
 73             return this.pointcutDeclarationScope != null ? this.pointcutDeclarationScope.getClassLoader() : ClassUtils.getDefaultClassLoader();
 74         }
 75     }
 76 
 77     private PointcutExpression buildPointcutExpression(@Nullable ClassLoader classLoader) {
 78         PointcutParser parser = this.initializePointcutParser(classLoader);
 79         PointcutParameter[] pointcutParameters = new PointcutParameter[this.pointcutParameterNames.length];
 80 
 81         for(int i = 0; i < pointcutParameters.length; ++i) {
 82             pointcutParameters[i] = parser.createPointcutParameter(this.pointcutParameterNames[i], this.pointcutParameterTypes[i]);
 83         }
 84 
 85         return parser.parsePointcutExpression(this.replaceBooleanOperators(this.resolveExpression()), this.pointcutDeclarationScope, pointcutParameters);
 86     }
 87 
 88     private String resolveExpression() {
 89         String expression = this.getExpression();
 90         Assert.state(expression != null, "No expression set");
 91         return expression;
 92     }
 93 
 94     private PointcutParser initializePointcutParser(@Nullable ClassLoader classLoader) {
 95         PointcutParser parser = PointcutParser.getPointcutParserSupportingSpecifiedPrimitivesAndUsingSpecifiedClassLoaderForResolution(SUPPORTED_PRIMITIVES, classLoader);
 96         parser.registerPointcutDesignatorHandler(new AspectJExpressionPointcut.BeanPointcutDesignatorHandler());
 97         return parser;
 98     }
 99 
100     private String replaceBooleanOperators(String pcExpr) {
101         String result = StringUtils.replace(pcExpr, " and ", " && ");
102         result = StringUtils.replace(result, " or ", " || ");
103         result = StringUtils.replace(result, " not ", " ! ");
104         return result;
105     }
106 
107     public PointcutExpression getPointcutExpression() {
108         return this.obtainPointcutExpression();
109     }
110 
111     public boolean matches(Class<?> targetClass) {
112         PointcutExpression pointcutExpression = this.obtainPointcutExpression();
113 
114         try {
115             try {
116                 return pointcutExpression.couldMatchJoinPointsInType(targetClass);
117             } catch (ReflectionWorldException var5) {
118                 logger.debug("PointcutExpression matching rejected target class - trying fallback expression", var5);
119                 PointcutExpression fallbackExpression = this.getFallbackPointcutExpression(targetClass);
120                 if (fallbackExpression != null) {
121                     return fallbackExpression.couldMatchJoinPointsInType(targetClass);
122                 }
123             }
124         } catch (Throwable var6) {
125             logger.debug("PointcutExpression matching rejected target class", var6);
126         }
127 
128         return false;
129     }
130 
131     public boolean matches(Method method, Class<?> targetClass, boolean hasIntroductions) {
132         this.obtainPointcutExpression();
133         ShadowMatch shadowMatch = this.getTargetShadowMatch(method, targetClass);
134         if (shadowMatch.alwaysMatches()) {
135             return true;
136         } else if (shadowMatch.neverMatches()) {
137             return false;
138         } else if (hasIntroductions) {
139             return true;
140         } else {
141             RuntimeTestWalker walker = this.getRuntimeTestWalker(shadowMatch);
142             return !walker.testsSubtypeSensitiveVars() || walker.testTargetInstanceOfResidue(targetClass);
143         }
144     }
145 
146     public boolean matches(Method method, Class<?> targetClass) {
147         return this.matches(method, targetClass, false);
148     }
149 
150     public boolean isRuntime() {
151         return this.obtainPointcutExpression().mayNeedDynamicTest();
152     }
153 
154     public boolean matches(Method method, Class<?> targetClass, Object... args) {
155         this.obtainPointcutExpression();
156         ShadowMatch shadowMatch = this.getTargetShadowMatch(method, targetClass);
157         ProxyMethodInvocation pmi = null;
158         Object targetObject = null;
159         Object thisObject = null;
160 
161         try {
162             MethodInvocation mi = ExposeInvocationInterceptor.currentInvocation();
163             targetObject = mi.getThis();
164             if (!(mi instanceof ProxyMethodInvocation)) {
165                 throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
166             }
167 
168             pmi = (ProxyMethodInvocation)mi;
169             thisObject = pmi.getProxy();
170         } catch (IllegalStateException var11) {
171             if (logger.isDebugEnabled()) {
172                 logger.debug("Could not access current invocation - matching with limited context: " + var11);
173             }
174         }
175 
176         try {
177             JoinPointMatch joinPointMatch = shadowMatch.matchesJoinPoint(thisObject, targetObject, args);
178             if (pmi != null && thisObject != null) {
179                 RuntimeTestWalker originalMethodResidueTest = this.getRuntimeTestWalker(this.getShadowMatch(method, method));
180                 if (!originalMethodResidueTest.testThisInstanceOfResidue(thisObject.getClass())) {
181                     return false;
182                 }
183 
184                 if (joinPointMatch.matches()) {
185                     this.bindParameters(pmi, joinPointMatch);
186                 }
187             }
188 
189             return joinPointMatch.matches();
190         } catch (Throwable var10) {
191             if (logger.isDebugEnabled()) {
192                 logger.debug("Failed to evaluate join point for arguments " + Arrays.asList(args) + " - falling back to non-match", var10);
193             }
194 
195             return false;
196         }
197     }
198 
199     @Nullable
200     protected String getCurrentProxiedBeanName() {
201         return ProxyCreationContext.getCurrentProxiedBeanName();
202     }
203 
204     @Nullable
205     private PointcutExpression getFallbackPointcutExpression(Class<?> targetClass) {
206         try {
207             ClassLoader classLoader = targetClass.getClassLoader();
208             if (classLoader != null && classLoader != this.pointcutClassLoader) {
209                 return this.buildPointcutExpression(classLoader);
210             }
211         } catch (Throwable var3) {
212             logger.debug("Failed to create fallback PointcutExpression", var3);
213         }
214 
215         return null;
216     }
217 
218     private RuntimeTestWalker getRuntimeTestWalker(ShadowMatch shadowMatch) {
219         return shadowMatch instanceof AspectJExpressionPointcut.DefensiveShadowMatch ? new RuntimeTestWalker(((AspectJExpressionPointcut.DefensiveShadowMatch)shadowMatch).primary) : new RuntimeTestWalker(shadowMatch);
220     }
221 
222     private void bindParameters(ProxyMethodInvocation invocation, JoinPointMatch jpm) {
223         invocation.setUserAttribute(this.resolveExpression(), jpm);
224     }
225 
226     private ShadowMatch getTargetShadowMatch(Method method, Class<?> targetClass) {
227         Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);
228         if (targetMethod.getDeclaringClass().isInterface()) {
229             Set<Class<?>> ifcs = ClassUtils.getAllInterfacesForClassAsSet(targetClass);
230             if (ifcs.size() > 1) {
231                 try {
232                     Class<?> compositeInterface = ClassUtils.createCompositeInterface(ClassUtils.toClassArray(ifcs), targetClass.getClassLoader());
233                     targetMethod = ClassUtils.getMostSpecificMethod(targetMethod, compositeInterface);
234                 } catch (IllegalArgumentException var6) {
235                 }
236             }
237         }
238 
239         return this.getShadowMatch(targetMethod, method);
240     }
241 
242     private ShadowMatch getShadowMatch(Method targetMethod, Method originalMethod) {
243         ShadowMatch shadowMatch = (ShadowMatch)this.shadowMatchCache.get(targetMethod);
244         if (shadowMatch == null) {
245             synchronized(this.shadowMatchCache) {
246                 PointcutExpression fallbackExpression = null;
247                 shadowMatch = (ShadowMatch)this.shadowMatchCache.get(targetMethod);
248                 if (shadowMatch == null) {
249                     Method methodToMatch = targetMethod;
250 
251                     try {
252                         try {
253                             shadowMatch = this.obtainPointcutExpression().matchesMethodExecution(methodToMatch);
254                         } catch (ReflectionWorldException var13) {
255                             try {
256                                 fallbackExpression = this.getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
257                                 if (fallbackExpression != null) {
258                                     shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
259                                 }
260                             } catch (ReflectionWorldException var12) {
261                                 fallbackExpression = null;
262                             }
263                         }
264 
265                         if (targetMethod != originalMethod && (shadowMatch == null || ((ShadowMatch)shadowMatch).neverMatches() && Proxy.isProxyClass(targetMethod.getDeclaringClass()))) {
266                             methodToMatch = originalMethod;
267 
268                             try {
269                                 shadowMatch = this.obtainPointcutExpression().matchesMethodExecution(methodToMatch);
270                             } catch (ReflectionWorldException var11) {
271                                 try {
272                                     fallbackExpression = this.getFallbackPointcutExpression(methodToMatch.getDeclaringClass());
273                                     if (fallbackExpression != null) {
274                                         shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);
275                                     }
276                                 } catch (ReflectionWorldException var10) {
277                                     fallbackExpression = null;
278                                 }
279                             }
280                         }
281                     } catch (Throwable var14) {
282                         logger.debug("PointcutExpression matching rejected target method", var14);
283                         fallbackExpression = null;
284                     }
285 
286                     if (shadowMatch == null) {
287                         shadowMatch = new ShadowMatchImpl(FuzzyBoolean.NO, (Test)null, (ExposedState)null, (PointcutParameter[])null);
288                     } else if (((ShadowMatch)shadowMatch).maybeMatches() && fallbackExpression != null) {
289                         shadowMatch = new AspectJExpressionPointcut.DefensiveShadowMatch((ShadowMatch)shadowMatch, fallbackExpression.matchesMethodExecution(methodToMatch));
290                     }
291 
292                     this.shadowMatchCache.put(targetMethod, shadowMatch);
293                 }
294             }
295         }
296 
297         return (ShadowMatch)shadowMatch;
298     }
299 
300     public boolean equals(Object other) {
301         if (this == other) {
302             return true;
303         } else if (!(other instanceof AspectJExpressionPointcut)) {
304             return false;
305         } else {
306             AspectJExpressionPointcut otherPc = (AspectJExpressionPointcut)other;
307             return ObjectUtils.nullSafeEquals(this.getExpression(), otherPc.getExpression()) && ObjectUtils.nullSafeEquals(this.pointcutDeclarationScope, otherPc.pointcutDeclarationScope) && ObjectUtils.nullSafeEquals(this.pointcutParameterNames, otherPc.pointcutParameterNames) && ObjectUtils.nullSafeEquals(this.pointcutParameterTypes, otherPc.pointcutParameterTypes);
308         }
309     }
310 
311     public int hashCode() {
312         int hashCode = ObjectUtils.nullSafeHashCode(this.getExpression());
313         hashCode = 31 * hashCode + ObjectUtils.nullSafeHashCode(this.pointcutDeclarationScope);
314         hashCode = 31 * hashCode + ObjectUtils.nullSafeHashCode(this.pointcutParameterNames);
315         hashCode = 31 * hashCode + ObjectUtils.nullSafeHashCode(this.pointcutParameterTypes);
316         return hashCode;
317     }
318 
319     public String toString() {
320         StringBuilder sb = new StringBuilder();
321         sb.append("AspectJExpressionPointcut: ");
322         sb.append("(");
323 
324         for(int i = 0; i < this.pointcutParameterTypes.length; ++i) {
325             sb.append(this.pointcutParameterTypes[i].getName());
326             sb.append(" ");
327             sb.append(this.pointcutParameterNames[i]);
328             if (i + 1 < this.pointcutParameterTypes.length) {
329                 sb.append(", ");
330             }
331         }
332 
333         sb.append(")");
334         sb.append(" ");
335         if (this.getExpression() != null) {
336             sb.append(this.getExpression());
337         } else {
338             sb.append("<pointcut expression not set>");
339         }
340 
341         return sb.toString();
342     }
343 
344     private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
345         ois.defaultReadObject();
346         this.shadowMatchCache = new ConcurrentHashMap(32);
347     }
348 
349     static {
350         SUPPORTED_PRIMITIVES.add(PointcutPrimitive.EXECUTION);
351         SUPPORTED_PRIMITIVES.add(PointcutPrimitive.ARGS);
352         SUPPORTED_PRIMITIVES.add(PointcutPrimitive.REFERENCE);
353         SUPPORTED_PRIMITIVES.add(PointcutPrimitive.THIS);
354         SUPPORTED_PRIMITIVES.add(PointcutPrimitive.TARGET);
355         SUPPORTED_PRIMITIVES.add(PointcutPrimitive.WITHIN);
356         SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ANNOTATION);
357         SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_WITHIN);
358         SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ARGS);
359         SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_TARGET);
360         logger = LogFactory.getLog(AspectJExpressionPointcut.class);
361     }
362 
363     private static class DefensiveShadowMatch implements ShadowMatch {
364         private final ShadowMatch primary;
365         private final ShadowMatch other;
366 
367         public DefensiveShadowMatch(ShadowMatch primary, ShadowMatch other) {
368             this.primary = primary;
369             this.other = other;
370         }
371 
372         public boolean alwaysMatches() {
373             return this.primary.alwaysMatches();
374         }
375 
376         public boolean maybeMatches() {
377             return this.primary.maybeMatches();
378         }
379 
380         public boolean neverMatches() {
381             return this.primary.neverMatches();
382         }
383 
384         public JoinPointMatch matchesJoinPoint(Object thisObject, Object targetObject, Object[] args) {
385             try {
386                 return this.primary.matchesJoinPoint(thisObject, targetObject, args);
387             } catch (ReflectionWorldException var5) {
388                 return this.other.matchesJoinPoint(thisObject, targetObject, args);
389             }
390         }
391 
392         public void setMatchingContext(MatchingContext aMatchContext) {
393             this.primary.setMatchingContext(aMatchContext);
394             this.other.setMatchingContext(aMatchContext);
395         }
396     }
397 
398     private class BeanContextMatcher implements ContextBasedMatcher {
399         private final NamePattern expressionPattern;
400 
401         public BeanContextMatcher(String expression) {
402             this.expressionPattern = new NamePattern(expression);
403         }
404 
405         /** @deprecated */
406         @Deprecated
407         public boolean couldMatchJoinPointsInType(Class someClass) {
408             return this.contextMatch(someClass) == org.aspectj.weaver.tools.FuzzyBoolean.YES;
409         }
410 
411         /** @deprecated */
412         @Deprecated
413         public boolean couldMatchJoinPointsInType(Class someClass, MatchingContext context) {
414             return this.contextMatch(someClass) == org.aspectj.weaver.tools.FuzzyBoolean.YES;
415         }
416 
417         public boolean matchesDynamically(MatchingContext context) {
418             return true;
419         }
420 
421         public org.aspectj.weaver.tools.FuzzyBoolean matchesStatically(MatchingContext context) {
422             return this.contextMatch((Class)null);
423         }
424 
425         public boolean mayNeedDynamicTest() {
426             return false;
427         }
428 
429         private org.aspectj.weaver.tools.FuzzyBoolean contextMatch(@Nullable Class<?> targetType) {
430             String advisedBeanName = AspectJExpressionPointcut.this.getCurrentProxiedBeanName();
431             if (advisedBeanName == null) {
432                 return org.aspectj.weaver.tools.FuzzyBoolean.MAYBE;
433             } else if (BeanFactoryUtils.isGeneratedBeanName(advisedBeanName)) {
434                 return org.aspectj.weaver.tools.FuzzyBoolean.NO;
435             } else if (targetType != null) {
436                 boolean isFactory = FactoryBean.class.isAssignableFrom(targetType);
437                 return org.aspectj.weaver.tools.FuzzyBoolean.fromBoolean(this.matchesBean(isFactory ? "&" + advisedBeanName : advisedBeanName));
438             } else {
439                 return org.aspectj.weaver.tools.FuzzyBoolean.fromBoolean(this.matchesBean(advisedBeanName) || this.matchesBean("&" + advisedBeanName));
440             }
441         }
442 
443         private boolean matchesBean(String advisedBeanName) {
444             return BeanFactoryAnnotationUtils.isQualifierMatch(this.expressionPattern::matches, advisedBeanName, AspectJExpressionPointcut.this.beanFactory);
445         }
446     }
447 
448     private class BeanPointcutDesignatorHandler implements PointcutDesignatorHandler {
449         private static final String BEAN_DESIGNATOR_NAME = "bean";
450 
451         private BeanPointcutDesignatorHandler() {
452         }
453 
454         public String getDesignatorName() {
455             return "bean";
456         }
457 
458         public ContextBasedMatcher parse(String expression) {
459             return AspectJExpressionPointcut.this.new BeanContextMatcher(expression);
460         }
461     }
462 }

  那下面就挑一部分代码来看,首先看静态代码块,里面的Set放的是切面表达式所支持的类型

1     private static final Set<PointcutPrimitive> SUPPORTED_PRIMITIVES = new HashSet<>();
 2 
 3     static {
 4         SUPPORTED_PRIMITIVES.add(PointcutPrimitive.EXECUTION);
 5         SUPPORTED_PRIMITIVES.add(PointcutPrimitive.ARGS);
 6         SUPPORTED_PRIMITIVES.add(PointcutPrimitive.REFERENCE);
 7         SUPPORTED_PRIMITIVES.add(PointcutPrimitive.THIS);
 8         SUPPORTED_PRIMITIVES.add(PointcutPrimitive.TARGET);
 9         SUPPORTED_PRIMITIVES.add(PointcutPrimitive.WITHIN);
10         SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ANNOTATION);
11         SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_WITHIN);
12         SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_ARGS);
13         SUPPORTED_PRIMITIVES.add(PointcutPrimitive.AT_TARGET);
14     }

  切点表达式类型:

  1. execution表达式:能在运行指定方法时拦截指定方法,用的最多。
  2. args:匹配参数,当执行的方法的参数是指定类型时生效。
  3. reference:表示引用其他命名切入点,只有@ApectJ风格支持,Schema风格不支持
  4. this:Spring Aop是基于代理的,生成的bean也是一个代理对象,this就是这个代理对象,当这个对象可以转换为指定的类型时,对应的切入点就是它了,Spring Aop将生效。
  5. target:当被代理的对象可以转换为指定的类型时,对应的切入点就是它了,Spring Aop将生效。
  6. within:指定某些类型的全部方法执行,也可用来指定一个包。
  7. @target:当代理的目标对象上拥有指定的注解时生效。
  8. @args:当执行的方法参数类型上拥有指定的注解时生效。
  9. @within:与@target类似,看官方文档和网上的说法都是@within只需要目标对象的类或者父类上有指定的注解,则@within会生效,而@target则是必须是目标对象的类上有指定的注解。而根据笔者的测试这两者都是只要目标类或父类上有指定的注解即可。
  10. @annotation:当执行的方法上拥有指定的注解时生效。

  还有一种是Spring Aop扩展的类型 bean:当调用的方法是指定的bean的方法时生效。

  AspectJExpressionPointcut 的属性里面还有 PointcutExpression,是org.aspectj.weaver.tools.PointcutExpression 中的类 ,经过一系列操作后由org.aspectj.weaver.tools.PointcutParser#parsePointcutExpression 从字符串表达式解析出来。

1     @Nullable
2     private transient PointcutExpression pointcutExpression;

  这个是ClassFilter 接口的实现方法,借助的 PointcutExpression#couldMatchJoinPointsInType 去匹配,其参数为一个代表被检测类Class的实例,如果切入点适合该类,则返回true

1     @Override
 2     public boolean matches(Class<?> targetClass) {
 3         PointcutExpression pointcutExpression = obtainPointcutExpression();
 4         try {
 5             try {
 6                 return pointcutExpression.couldMatchJoinPointsInType(targetClass);
 7             }
 8             catch (ReflectionWorldException ex) {
 9                 logger.debug("PointcutExpression matching rejected target class - trying fallback expression", ex);
10                 // Actually this is still a "maybe" - treat the pointcut as dynamic if we don't know enough yet
11                 PointcutExpression fallbackExpression = getFallbackPointcutExpression(targetClass);
12                 if (fallbackExpression != null) {
13                     return fallbackExpression.couldMatchJoinPointsInType(targetClass);
14                 }
15             }
16         }
17         catch (Throwable ex) {
18             logger.debug("PointcutExpression matching rejected target class", ex);
19         }
20         return false;
21     }

  下面这个是 MethodMatcher 接口中的 match 方法,作为Spring支持静态和动态的MethodMatcher。执行静态检查给定的方法是否匹配。

1   @Override
 2     public boolean matches(Method method, Class<?> targetClass, Object... args) {
 3         obtainPointcutExpression();
 4         ShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass);
 5 
 6         // Bind Spring AOP proxy to AspectJ "this" and Spring AOP target to AspectJ target,
 7         // consistent with return of MethodInvocationProceedingJoinPoint
 8         ProxyMethodInvocation pmi = null;
 9         Object targetObject = null;
10         Object thisObject = null;
11         try {
12             MethodInvocation mi = ExposeInvocationInterceptor.currentInvocation();
13             targetObject = mi.getThis();
14             if (!(mi instanceof ProxyMethodInvocation)) {
15                 throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
16             }
17             pmi = (ProxyMethodInvocation) mi;
18             thisObject = pmi.getProxy();
19         }
20         catch (IllegalStateException ex) {
21             // No current invocation...
22             if (logger.isDebugEnabled()) {
23                 logger.debug("Could not access current invocation - matching with limited context: " + ex);
24             }
25         }
26 
27         try {
28             JoinPointMatch joinPointMatch = shadowMatch.matchesJoinPoint(thisObject, targetObject, args);
29 
30             /*
31              * Do a final check to see if any this(TYPE) kind of residue match. For
32              * this purpose, we use the original method's (proxy method's) shadow to
33              * ensure that 'this' is correctly checked against. Without this check,
34              * we get incorrect match on this(TYPE) where TYPE matches the target
35              * type but not 'this' (as would be the case of JDK dynamic proxies).
36              * <p>See SPR-2979 for the original bug.
37              */
38             if (pmi != null && thisObject != null) {  // there is a current invocation
39                 RuntimeTestWalker originalMethodResidueTest = getRuntimeTestWalker(getShadowMatch(method, method));
40                 if (!originalMethodResidueTest.testThisInstanceOfResidue(thisObject.getClass())) {
41                     return false;
42                 }
43                 if (joinPointMatch.matches()) {
44                     bindParameters(pmi, joinPointMatch);
45                 }
46             }
47 
48             return joinPointMatch.matches();
49         }
50         catch (Throwable ex) {
51             if (logger.isDebugEnabled()) {
52                 logger.debug("Failed to evaluate join point for arguments " + Arrays.asList(args) +
53                         " - falling back to non-match", ex);
54             }
55             return false;
56         }
57     }

  初始化一个基础的AspectJ切入点解析器,BeanPointcutDesignatorHandler 这个是Spring实现真正解析的内部类。

1     /**
 2      * Initialize the underlying AspectJ pointcut parser.
 3      */
 4     private PointcutParser initializePointcutParser(@Nullable ClassLoader classLoader) {
 5         PointcutParser parser = PointcutParser
 6                 .getPointcutParserSupportingSpecifiedPrimitivesAndUsingSpecifiedClassLoaderForResolution(
 7                         SUPPORTED_PRIMITIVES, classLoader);
 8         parser.registerPointcutDesignatorHandler(new BeanPointcutDesignatorHandler()); // 注册了一个BeanPointcutDesignatorHandler它是处理Spring自己支持的bean()的切点表达式的
 9         return parser;
10     }

 总结

标签:return,AspectJExpressionPointcutAdvisor,private,源码,shadowMatch,AOP,PRIMITIVES,nu
From: https://blog.51cto.com/u_15668812/7139586

相关文章

  • 直播平台源码之实现网络请求的方法
    直播平台源码开发中如果你不会网络请求,那么你开发的应用软件就是一具没有灵魂的枯骨。当你下载完软件后会要求你给与权限,否则就没办法使用,网络请求也需要对应的权限,否则就没法进行联网操作。在直播平台源码开发中首先在AndroidManifest.xml文件中添加网络请求权限要在manifest......
  • 如何在视频直播app源码开发中实现开屏广告功能
    APP开屏广告就目前来说是一个很常见的广告形式,我们现在打开各个APP几乎都会有开屏广告的身影,开屏广告也成了吸引用户注意力和实现盈利的主要方式,所以在视频直播app源码开发,开屏广告功能就显得尤为重要。一、视频直播app源码之开屏广告作用:广告、营销推广界面组成:广告、跳过(倒计......
  • 悬赏平台APP系统源码
      悬赏平台APP软件是一款在线上做任务,拉新,充场的软件,任何一个用户在平台上注册账号,发布任务,领取任务并获得佣金。本文就一悬赏任务APP软件对功能上的事项进行分析,看看都有哪些功能。  1.任务源  悬赏平台APP展示者所有的任务平台类型,任务做法流程,任务要求,有充场,拉新,......
  • CentOS7源码安装JDK8☘️
    1.下载jdk  Java版本支持路线图 Java9、Java10、Java12、Java13、Java14、Java15和Java16均为短期版本,建议不要使用以上版本。官网下载如有旧版本请先卸载openjdk:[root@localhost~]#yumerase`rpm-qa|grepopenjdk`-y2.解压安装:[root@localhost~]#tarxvz......
  • zlmediakit源码学习(扩展支持转码H265/H264)
    在zlmediakit源码基础上继续探索扩展支持H265/H264的转码功能。参照上一篇帖子:https://www.cnblogs.com/feixiang-energy/p/17623567.html 作者已经封装好了基于ffmpeg实现的解码、编码、视频图像格式转换、音频重采样等接口,https://gitee.com/xia-chu/ZLMediaKit/blob/feature......
  • Spring-3-Spring AOP概念全面解析
    今日目标能够理解AOP的作用能够完成AOP的入门案例能够理解AOP的工作流程能够说出AOP的五种通知类型一、AOP1AOP简介思考:什么是AOP,AOP的作用是什么?1.1AOP简介和作用【理解】AOP(AspectOrientedProgramming)面向切面编程,一种编程范式,指导开发者如何组织程序结构OO......
  • 医疗信息云LIS系统源码 .Net Core版SaaS模式
    SaaS模式.NetCore版云LIS系统源码医疗信息LIS系统是专为医院检验科设计的一套实验室信息管理系统,能将实验仪器与计算机组成网络,使病人样品登录、实验数据存取、报告审核、打印分发,实验数据统计分析等繁杂的操作过程实现了智能化、自动化和规范化管理。有助于提高实验室的整体管理......
  • 无限开商户的开源SaaS进销存源码,商户支持多门店多仓库
    随着软件行业的发展,越来越多的公司开始采用SaaS(软件即服务)模式来构建软件产品,以降低部署和维护的成本,并方便软件升级和更新。SaaS进销存系统是一个基于云计算的管理系统,通过浏览器或移动设备访问,无需在本地安装大量软件。它具有轻量级、自动化等特点,可以快速上手,降低企业成本。管店......
  • 国产麒麟系统KylinOS Server V10 SP2安装MySQL 8.0.26—源码编译安装
    一:操作系统环境检查1.1首先确认操作系统版本是KylinOSServerV10SP2麒麟操作系统KylinosServerV10SP2使用的安装介质是Kylin-Server-10-SP2-x86-Release-Build09-20210524.iso,执行以下命令查看版本:cat/etc/kylin-releasecat/proc/version 1.2检查系统是否......
  • 直播系统源码协议探索篇(二):网络套接字协议WebSocket
     上一篇我们分析了直播平台的会话初始化协议SIP,他关乎着直播平台的实时通信和多方互动技术的实现,今天我们来讲另一个协议,叫网络套接字协议WebSocket,WebSocket基于TCP在客户端与服务器建立双向通信的网络协议,并且可以通过单个长连接实现。在直播系统源码平台已经成为人们获取知识......