在上篇文章 SpringAop源码分析(基于注解)一 中,我们分析了Spring是怎样把专门处理AOP的类进行注册的,本篇文章我们将分析这个类是怎么对AOP起作用的。
我们已经知道 BeanPostProcessors
是在Bean实例化前后起作用的,如果看过前面的文章 Spring Ioc源码分析 之 Bean的加载(八):初始化
,应该知道Spring是在 AbstractAutowireCapableBeanFactory#doCreateBean()
方法中有一个初始化Bean的方法:
exposedObject = initializeBean(beanName, exposedObject, mbd) 复制代码
继续深入:
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) { //JDK的安全机制验证权限 if (System.getSecurityManager() != null) { // <1> 激活 Aware 方法,对特殊的 bean 处理:Aware、BeanClassLoaderAware、BeanFactoryAware AccessController.doPrivileged((PrivilegedAction<Object>) () -> { invokeAwareMethods(beanName, bean); return null; }, getAccessControlContext()); } else { // <1> 激活 Aware 方法,对特殊的 bean 处理:Aware、BeanClassLoaderAware、BeanFactoryAware invokeAwareMethods(beanName, bean); } Object wrappedBean = bean; // <2> 后置处理器,before if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); } // <3> 激活用户自定义的 init 方法 try { invokeInitMethods(beanName, wrappedBean, mbd); } catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } // <2> 后置处理器,after if (mbd == null || !mbd.isSynthetic()) { // 我们关注的重点是这里!!! wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; } 复制代码
其中第<2>步就是触发我们 BeanPostProcessors
的地方。
我们再回过头来看 AnnotationAwareAspectJAutoProxyCreator
有一个上层父类 AbstractAutoProxyCreator
,它实现了SmartInstantiationAwareBeanPostProcessor接口,来看下它的主要方法。
//AbstractAutoProxyCreator.java //在Bean初始化之前回调 @Override public Object postProcessBeforeInitialization(Object bean, String beanName) { return bean; } /** * Create a proxy with the configured interceptors if the bean is * identified as one to proxy by the subclass. * @see #getAdvicesAndAdvisorsForBean */ //在Bean初始化之后回调 @Override public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); //判断缓存中是否有 if (!this.earlyProxyReferences.contains(cacheKey)) { // 没有,为 bean 生成代理对象 return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; } 复制代码
可以看到 AbstractAutoProxyCreator
类里实现了 postProcessAfterInitialization()
方法,该方法将在Bean初始化之后调用。
接着看wrapIfNecessary方法:
//AbstractAutoProxyCreator.java protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { return bean; } if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { return bean; } /* * 如果是基础设施类(Pointcut、Advice、Advisor 等接口的实现类),或是应该跳过的类, * 则不应该生成代理,此时直接返回 bean */ if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } // Create proxy if we have advice. // 返回匹配当前 bean 的所有的通知器 advisor、advice、interceptor Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); // 核心!创建代理对象 Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } 复制代码
这里看起来逻辑不复杂:
但是这两步具体细节就很复杂了,我们一个一个来看,先看第一步。
//AbstractAdvisorAutoProxyCreator protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) { //获取匹配的通知器 List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); if (advisors.isEmpty()) { return DO_NOT_PROXY; } return advisors.toArray(); } 复制代码
继续深入:
//AbstractAdvisorAutoProxyCreator.java protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { //获取所有的通知器 List<Advisor> candidateAdvisors = findCandidateAdvisors(); //筛选可应用在 beanClass 上的 Advisor,通过 ClassFilter 和 MethodMatcher //对目标类和方法进行匹配 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); // extendAdvisors(eligibleAdvisors); if (!eligibleAdvisors.isEmpty()) { eligibleAdvisors = sortAdvisors(eligibleAdvisors); } return eligibleAdvisors; } 复制代码
接上面的代码:
//AnnotationAwareAspectJAutoProxyCreator.java protected List<Advisor> findCandidateAdvisors() { // 调用父类方法从容器中获取所有的通知器 List<Advisor> advisors = super.findCandidateAdvisors(); // 解析 @Aspect 注解,并构建通知器 if (this.aspectJAdvisorsBuilder != null) { advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); } return advisors; } 复制代码
先看一下调用父类的方法
//AbstractAdvisorAutoProxyCreator.java protected List<Advisor> findCandidateAdvisors() { Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available"); return this.advisorRetrievalHelper.findAdvisorBeans(); } 复制代码
继续深入:
//BeanFactoryAdvisorRetrievalHelper.java public List<Advisor> findAdvisorBeans() { String[] advisorNames = null; synchronized (this) { // cachedAdvisorBeanNames 是 advisor 名称的缓存 advisorNames = this.cachedAdvisorBeanNames; //如果缓存为空,到容器中查找, //并设置缓存,后续直接使用缓存即可 if (advisorNames == null) { // 从容器中查找 Advisor 类型 bean 的名称 advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Advisor.class, true, false); // 设置缓存 this.cachedAdvisorBeanNames = advisorNames; } } if (advisorNames.length == 0) { return new LinkedList<Advisor>(); } List<Advisor> advisors = new LinkedList<Advisor>(); // 遍历 advisorNames for (String name : advisorNames) { if (isEligibleBean(name)) { // 忽略正在创建中的 advisor bean if (this.beanFactory.isCurrentlyInCreation(name)) { if (logger.isDebugEnabled()) { logger.debug("Skipping currently created advisor '" + name + "'"); } } else { try { //调用 getBean 方法从容器中获取名称为 name 的 bean, //并将 bean 添加到 advisors 中 advisors.add(this.beanFactory.getBean(name, Advisor.class)); } catch (BeanCreationException ex) { Throwable rootCause = ex.getMostSpecificCause(); if (rootCause instanceof BeanCurrentlyInCreationException) { BeanCreationException bce = (BeanCreationException) rootCause; if (this.beanFactory.isCurrentlyInCreation(bce.getBeanName())) { if (logger.isDebugEnabled()) { logger.debug("Skipping advisor '" + name + "' with dependency on currently created bean: " + ex.getMessage()); } continue; } } throw ex; } } } } return advisors; } 复制代码
这段代码虽然很长,但并不复杂:
先从缓存中获取,获取不到就从IOC容器中获取类型为 Advisor
的BeanName
遍历获取到的BeanName,调用getBean()方法获取实例,并加入到通知器集合中
代码如下:
//BeanFactoryAspectJAdvisorsBuilder.java public List<Advisor> buildAspectJAdvisors() { List<String> aspectNames = this.aspectBeanNames; if (aspectNames == null) { synchronized (this) { aspectNames = this.aspectBeanNames; if (aspectNames == null) { List<Advisor> advisors = new LinkedList<>(); aspectNames = new LinkedList<>(); // 从容器中获取所有 bean 的名称 String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors( this.beanFactory, Object.class, true, false); for (String beanName : beanNames) { if (!isEligibleBean(beanName)) { continue; } // We must be careful not to instantiate beans eagerly as in this case they // would be cached by the Spring container but would not have been weaved. // 根据 beanName 获取 bean 的类型 Class<?> beanType = this.beanFactory.getType(beanName); if (beanType == null) { continue; } // 检测 beanType 是否包含 Aspect 注解 if (this.advisorFactory.isAspect(beanType)) { aspectNames.add(beanName); //创建Aspect元数据 AspectMetadata amd = new AspectMetadata(beanType, beanName); if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) { //创建元数据aop实例化工厂 MetadataAwareAspectInstanceFactory factory = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName); // 从工厂中获取通知器 List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory); if (this.beanFactory.isSingleton(beanName)) { this.advisorsCache.put(beanName, classAdvisors); } else { this.aspectFactoryCache.put(beanName, factory); } advisors.addAll(classAdvisors); } else { // Per target or per this. if (this.beanFactory.isSingleton(beanName)) { throw new IllegalArgumentException("Bean with name '" + beanName + "' is a singleton, but aspect instantiation model is not singleton"); } MetadataAwareAspectInstanceFactory factory = new PrototypeAspectInstanceFactory(this.beanFactory, beanName); this.aspectFactoryCache.put(beanName, factory); advisors.addAll(this.advisorFactory.getAdvisors(factory)); } } } this.aspectBeanNames = aspectNames; return advisors; } } } if (aspectNames.isEmpty()) { return Collections.emptyList(); } List<Advisor> advisors = new LinkedList<>(); for (String aspectName : aspectNames) { List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName); if (cachedAdvisors != null) { advisors.addAll(cachedAdvisors); } else { MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName); advisors.addAll(this.advisorFactory.getAdvisors(factory)); } } return advisors; } 复制代码
代码很长,但我们在只需要关注关键步骤即可:
这里也可以和我们前面的demo对应起来,我们之前定义了一个 LogAspect
的类,然后用注解 @Component
和 @Aspect
声明了。
上面这段代码的逻辑就是:
找到这个标注 @Aspect
的类,并找到里面定义的通知器,如 @Before
、 @After
等。
同时这也回答了上篇文章的一个问题:Spring是怎么找到我们定义的切面的?
@Aspect @Component @EnableAspectJAutoProxy public class LogAspect { @Before("execution(* com.mydemo.work.StudentController.getName(..))") public void doBefore() { System.out.println("========before"); } @After("execution(* com.mydemo.work.StudentController.getName(..))") public void doAfter() { System.out.println("========after"); } } 复制代码
接着看从工厂获取通知器的方法 this.advisorFactory.getAdvisors(factory)
//ReflectiveAspectJAdvisorFactory.java public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) { Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass(); String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName(); validate(aspectClass); // We need to wrap the MetadataAwareAspectInstanceFactory with a decorator // so that it will only instantiate once. MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory); List<Advisor> advisors = new LinkedList<>(); <1> //获取该切面的所有方法,排除@Pointcut修饰的 for (Method method : getAdvisorMethods(aspectClass)) { //遍历,获取被 通知注解 修饰的方法,并封装成Advisor <2> Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName); if (advisor != null) { advisors.add(advisor); } } // If it's a per target aspect, emit the dummy instantiating aspect. if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) { Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory); advisors.add(0, instantiationAdvisor); } // Find introduction fields. for (Field field : aspectClass.getDeclaredFields()) { Advisor advisor = getDeclareParentsAdvisor(field); if (advisor != null) { advisors.add(advisor); } } return advisors; } 复制代码
接着追踪 getAdvisor()
方法:
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrderInAspect, String aspectName) { validate(aspectInstanceFactory.getAspectMetadata().getAspectClass()); //获取切点Pointcut <3> AspectJExpressionPointcut expressionPointcut = getPointcut( candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass()); if (expressionPointcut == null) { return null; } // 创建 Advisor 实现类,封装切点表达式、通知名称、方法名称等 <6> return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod, this, aspectInstanceFactory, declarationOrderInAspect, aspectName); } @Nullable private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) { // 获取方法上的 AspectJ 相关注解,包括 @Before,@After、@Around、@Pointcut 等 //因为这些注解上都可以设置切点 <4> AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod); if (aspectJAnnotation == null) { return null; } AspectJExpressionPointcut ajexp = new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]); <5> //设置切点匹配表达式 ajexp.setExpression(aspectJAnnotation.getPointcutExpression()); if (this.beanFactory != null) { ajexp.setBeanFactory(this.beanFactory); } return ajexp; } 复制代码
这里的逻辑其实也不复杂,。
<1>,获取切面中的所有方法,排除@Pointcut修饰的方法
<2>,遍历所有方法
<3>,获取该方法的切点
<4>,根据AspectJ相关注解,包括 @Before,@After、@Pointcut等获取切点
<5>,设置切点表达式到AspectJExpressionPointcut 封装结果如下:
<6>,创建Advisor,封装切点表达式、通知名称、方法名称等
封装结果如下:
this.advisorFactory.getAdvisors(factory)
这段代码的最终目的,就是获取该切面所有的通知方法、它们的切点,并把它们都封装成一个个 Advisor
。
但其实每个 Advisor
里的 Advice
都是不同的,我们来看下创建 Advisor
的过程,即第<6>步:
//InstantiationModelAwarePointcutAdvisorImpl.java public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut, Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) { this.declaredPointcut = declaredPointcut; this.declaringClass = aspectJAdviceMethod.getDeclaringClass(); this.methodName = aspectJAdviceMethod.getName(); this.parameterTypes = aspectJAdviceMethod.getParameterTypes(); this.aspectJAdviceMethod = aspectJAdviceMethod; this.aspectJAdvisorFactory = aspectJAdvisorFactory; this.aspectInstanceFactory = aspectInstanceFactory; this.declarationOrder = declarationOrder; this.aspectName = aspectName; if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) { // Static part of the pointcut is a lazy type. Pointcut preInstantiationPointcut = Pointcuts.union( aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut); // Make it dynamic: must mutate from pre-instantiation to post-instantiation state. // If it's not a dynamic pointcut, it may be optimized out // by the Spring AOP infrastructure after the first evaluation. this.pointcut = new PerTargetInstantiationModelPointcut( this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory); this.lazy = true; } else { // A singleton aspect. this.pointcut = this.declaredPointcut; this.lazy = false; // 按照注解解析 Advice this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut); } } 复制代码
上面是 InstantiationModelAwarePointcutAdvisorImpl
的构造方法,不过我们无需太关心这个方法中的一些初始化逻辑。我们把目光移到构造方法的最后一行代码中,即 instantiateAdvice(this.declaredPointcut)
,这个方法用于创建通知 Advice。
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) { return this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pcut, this.aspectInstanceFactory, this.declarationOrder, this.aspectName); } public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut, MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) { Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass(); validate(candidateAspectClass); // 获取 Advice 注解 AspectJAnnotation<?> aspectJAnnotation = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod); if (aspectJAnnotation == null) { return null; } if (!isAspect(candidateAspectClass)) { throw new AopConfigException("Advice must be declared inside an aspect type: " + "Offending method '" + candidateAdviceMethod + "' in class [" + candidateAspectClass.getName() + "]"); } if (logger.isDebugEnabled()) { logger.debug("Found AspectJ method: " + candidateAdviceMethod); } AbstractAspectJAdvice springAdvice; // 按照注解类型生成相应的 Advice 实现类 switch (aspectJAnnotation.getAnnotationType()) { case AtBefore: // @Before -> AspectJMethodBeforeAdvice springAdvice = new AspectJMethodBeforeAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); break; case AtAfter: // @After -> AspectJAfterAdvice springAdvice = new AspectJAfterAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); break; case AtAfterReturning: // @AfterReturning -> AspectJAfterAdvice springAdvice = new AspectJAfterReturningAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation(); if (StringUtils.hasText(afterReturningAnnotation.returning())) { springAdvice.setReturningName(afterReturningAnnotation.returning()); } break; case AtAfterThrowing: // @AfterThrowing -> AspectJAfterThrowingAdvice springAdvice = new AspectJAfterThrowingAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation(); if (StringUtils.hasText(afterThrowingAnnotation.throwing())) { springAdvice.setThrowingName(afterThrowingAnnotation.throwing()); } break; case AtAround: // @Around -> AspectJAroundAdvice springAdvice = new AspectJAroundAdvice( candidateAdviceMethod, expressionPointcut, aspectInstanceFactory); break; //什么都不做,直接返回 null。 case AtPointcut: if (logger.isDebugEnabled()) { logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'"); } return null; default: throw new UnsupportedOperationException( "Unsupported advice type on method: " + candidateAdviceMethod); } springAdvice.setAspectName(aspectName); springAdvice.setDeclarationOrder(declarationOrder); //获取方法的参数列表名称,比如方法 int sum(int numX, int numY), //getParameterNames(sum) 得到 argNames = [numX, numY] String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod); if (argNames != null) { // 设置参数名 springAdvice.setArgumentNamesFromStringArray(argNames); } springAdvice.calculateArgumentBindings(); return springAdvice; } 复制代码
可见,根据注解的不同,创建不同的 Advice
,并封装到 Advisor
中。
现在我们已经拿到了所有通知器,接下来就要筛选出匹配当前Bean的通知器。
代码 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
中:
//AbstractAdvisorAutoProxyCreator.java protected List<Advisor> findAdvisorsThatCanApply( List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) { ProxyCreationContext.setCurrentProxiedBeanName(beanName); try { //筛选匹配的通知器 return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); } finally { ProxyCreationContext.setCurrentProxiedBeanName(null); } } 复制代码
继续深入:
//AbstractAdvisorAutoProxyCreator.java protected List<Advisor> findAdvisorsThatCanApply( List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) { ProxyCreationContext.setCurrentProxiedBeanName(beanName); try { //筛选出匹配当前Bean的通知器 return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); } finally { ProxyCreationContext.setCurrentProxiedBeanName(null); } } 复制代码
//AopUtils.java public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) { if (candidateAdvisors.isEmpty()) { return candidateAdvisors; } List<Advisor> eligibleAdvisors = new LinkedList<>(); // 筛选 IntroductionAdvisor 类型的通知器 for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) { eligibleAdvisors.add(candidate); } } boolean hasIntroductions = !eligibleAdvisors.isEmpty(); // 筛选普通类型的通知器 for (Advisor candidate : candidateAdvisors) { if (candidate instanceof IntroductionAdvisor) { // already processed continue; } if (canApply(candidate, clazz, hasIntroductions)) { eligibleAdvisors.add(candidate); } } return eligibleAdvisors; } 复制代码
//AopUtils.java public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) { //ClassFilter直接匹配 if (advisor instanceof IntroductionAdvisor) { return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass); } else if (advisor instanceof PointcutAdvisor) { PointcutAdvisor pca = (PointcutAdvisor) advisor; //继续调用重载方法 return canApply(pca.getPointcut(), targetClass, hasIntroductions); } else { // It doesn't have a pointcut so we assume it applies. return true; } } 复制代码
//AopUtils.java public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) { Assert.notNull(pc, "Pointcut must not be null"); if (!pc.getClassFilter().matches(targetClass)) { return false; } MethodMatcher methodMatcher = pc.getMethodMatcher(); if (methodMatcher == MethodMatcher.TRUE) { // No need to iterate the methods if we're matching any method anyway... return true; } IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null; if (methodMatcher instanceof IntroductionAwareMethodMatcher) { introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher; } //查找当前类及其父类(以及父类的父类等等)所实现的接口,由于接口中的方法是 public, //所以当前类可以继承其父类,和父类的父类中所有的接口方法 Set<Class<?>> classes = new LinkedHashSet<>(ClassUtils.getAllInterfacesForClassAsSet(targetClass)); classes.add(targetClass); for (Class<?> clazz : classes) { // 获取当前类的方法列表,包括从父类中继承的方法 Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz); for (Method method : methods) { // 使用 methodMatcher 匹配方法,匹配成功即可立即返回 if ((introductionAwareMethodMatcher != null && introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) || methodMatcher.matches(method, targetClass)) { return true; } } } return false; } 复制代码
上面就是筛选通知器的过程,筛选的工作主要由 ClassFilter 和 MethodMatcher 来完成。关于 ClassFilter 和 MethodMatcher,在 AOP 中,切点 Pointcut 是用来匹配连接点的,以 AspectJExpressionPointcut 类型的切点为例。该类型切点实现了ClassFilter 和 MethodMatcher 接口,匹配的工作则是由 AspectJ 表达式解析器负责。除了使用 AspectJ 表达式进行匹配,Spring 还提供了基于正则表达式的切点类,以及更简单的根据方法名进行匹配的切点类。大家有兴趣的话,可以自己去了解一下,这里就不多说了。
现在,我们知道了通知是怎么创建和筛选的。那下篇文章,我们一起来分析一下AOP是怎么创建代理对象的。
总结
这篇文章花了比较大的功夫,受个人能力限制,很遗憾没有对里面的源码作非常详细的分析,只理解了主流程,希望朋友们发现文章中的错误或不妥之处,还请指出,互相交流~
参考:
www.tianxiaobo.com/2018/06/20/…