Spring源码解析(27)之AOP的核心对象创建过程2
一、前言
我们在上一节中已经介绍了Advisor的创建过程,当时我们创建的logUtil这bean,他在
resolveBeforeInstantiation返回的是null,那么就会继续往下执行doCreateBean方法。
二、源码分析
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {// Instantiate the bean.// 这个beanWrapper是用来持有创建出来的bean对象的BeanWrapper instanceWrapper = null;// 获取factoryBean实例缓存if (mbd.isSingleton()) {// 如果是单例对象,从factorybean实例缓存中移除当前bean定义信息instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}// 没有就创建实例if (instanceWrapper == null) {// 根据执行bean使用对应的策略创建新的实例,如,工厂方法,构造函数主动注入、简单初始化instanceWrapper = createBeanInstance(beanName, mbd, args);}// 从包装类中获取原始beanObject bean = instanceWrapper.getWrappedInstance();// 获取具体的bean对象的Class属性Class<?> beanType = instanceWrapper.getWrappedClass();// 如果不等于NullBean类型,那么修改目标类型if (beanType != NullBean.class) {mbd.resolvedTargetType = beanType;}// Allow post-processors to modify the merged bean definition.// 允许beanPostProcessor去修改合并的beanDefinitionsynchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {try {// MergedBeanDefinitionPostProcessor后置处理器修改合并bean的定义applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Post-processing of merged bean definition failed", ex);}mbd.postProcessed = true;}}// Eagerly cache singletons to be able to resolve circular references// even when triggered by lifecycle interfaces like BeanFactoryAware.// 判断当前bean是否需要提前曝光:单例&允许循环依赖&当前bean正在创建中,检测循环依赖boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));if (earlySingletonExposure) {if (logger.isTraceEnabled()) {logger.trace("Eagerly caching bean '" + beanName +"' to allow for resolving potential circular references");}// 为避免后期循环依赖,可以在bean初始化完成前将创建实例的ObjectFactory加入工厂addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));// //只保留二级缓存,不向三级缓存中存放对象
// earlySingletonObjects.put(beanName,bean);
// registeredSingletons.add(beanName);
//
// synchronized (this.singletonObjects) {
// if (!this.singletonObjects.containsKey(beanName)) {
// //实例化后的对象先添加到三级缓存中,三级缓存对应beanName的是一个lambda表达式(能够触发创建代理对象的机制)
// this.singletonFactories.put(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
// this.registeredSingletons.add(beanName);
// }
// }}// Initialize the bean instance.// 初始化bean实例Object exposedObject = bean;try {// 对bean的属性进行填充,将各个属性值注入,其中,可能存在依赖于其他bean的属性,则会递归初始化依赖的beanpopulateBean(beanName, mbd, instanceWrapper);// 执行初始化逻辑exposedObject = initializeBean(beanName, exposedObject, mbd);}catch (Throwable ex) {if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {throw (BeanCreationException) ex;}else {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);}}if (earlySingletonExposure) {// 从缓存中获取具体的对象Object earlySingletonReference = getSingleton(beanName, false);// earlySingletonReference只有在检测到有循环依赖的情况下才会不为空if (earlySingletonReference != null) {// 如果exposedObject没有在初始化方法中被改变,也就是没有被增强if (exposedObject == bean) {exposedObject = earlySingletonReference;}else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {String[] dependentBeans = getDependentBeans(beanName);Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);for (String dependentBean : dependentBeans) {// 返回false说明依赖还没实例化好if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {actualDependentBeans.add(dependentBean);}}// 因为bean创建后所依赖的bean一定是已经创建的// actualDependentBeans不为空则表示当前bean创建后其依赖的bean却没有全部创建完,也就是说存在循环依赖if (!actualDependentBeans.isEmpty()) {throw new BeanCurrentlyInCreationException(beanName,"Bean with name '" + beanName + "' has been injected into other beans [" +StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +"] in its raw version as part of a circular reference, but has eventually been " +"wrapped. This means that said other beans do not use the final version of the " +"bean. This is often the result of over-eager type matching - consider using " +"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");}}}}// Register bean as disposable.try {// 注册bean对象,方便后续在容器销毁的时候销毁对象registerDisposableBeanIfNecessary(beanName, bean, mbd);}catch (BeanDefinitionValidationException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);}return exposedObject;}
然后就会进入到 initializeBean,进行bean的初始化,我们之前都知道在这个initializeBean会会执行BPP的after方法,然后我们之前解析AOP配置文件的时候注入的AutoProxyCreator他是一个BeanPostProcessor,这里会执行它的after方法来判断是否需要创建代理对象,我们继续往下跟。
/*** 初始化给定的bean实例,应用工厂回调以及init方法和BeanPostProcessors** Initialize the given bean instance, applying factory callbacks* as well as init methods and bean post processors.* <p>Called from {@link #createBean} for traditionally defined beans,* and from {@link #initializeBean} for existing bean instances.* @param beanName the bean name in the factory (for debugging purposes)* @param bean the new bean instance we may need to initialize* @param mbd the bean definition that the bean was created with* (can also be {@code null}, if given an existing bean instance)* @return the initialized bean instance (potentially wrapped)* @see BeanNameAware* @see BeanClassLoaderAware* @see BeanFactoryAware* @see #applyBeanPostProcessorsBeforeInitialization* @see #invokeInitMethods* @see #applyBeanPostProcessorsAfterInitialization*/protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {// 如果安全管理器不为空if (System.getSecurityManager() != null) {// 以特权的方式执行回调bean中的Aware接口方法AccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareMethods(beanName, bean);return null;}, getAccessControlContext());}else {// Aware接口处理器,调用BeanNameAware、BeanClassLoaderAware、beanFactoryAwareinvokeAwareMethods(beanName, bean);}Object wrappedBean = bean;//如果mdb不为null || mbd不是"synthetic"。一般是指只有AOP相关的prointCut配置或者Advice配置才会将 synthetic设置为trueif (mbd == null || !mbd.isSynthetic()) {// 将BeanPostProcessors应用到给定的现有Bean实例,调用它们的postProcessBeforeInitialization初始化方法。// 返回的Bean实例可能是原始Bean包装器wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}try {//调用初始化方法,先调用bean的InitializingBean接口方法,后调用bean的自定义初始化方法invokeInitMethods(beanName, wrappedBean, mbd);}catch (Throwable ex) {//捕捉调用初始化方法时抛出的异常,重新抛出Bean创建异常:调用初始化方法失败throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),beanName, "Invocation of init method failed", ex);}//如果mbd为null || mbd不是"synthetic"if (mbd == null || !mbd.isSynthetic()) {// 将BeanPostProcessors应用到给定的现有Bean实例,调用它们的postProcessAfterInitialization方法。// 返回的Bean实例可能是原始Bean包装器wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}//返回包装后的Beanreturn wrappedBean;}
我们继续往里面跟AutoProxyCretor的after方法,看里面具体的执行逻辑。
@Overridepublic Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {//初始化结果对象为result,默认引用existingBeanObject result = existingBean;//遍历该工厂创建的bean的BeanPostProcessors列表for (BeanPostProcessor processor : getBeanPostProcessors()) {//回调BeanPostProcessor#postProcessAfterInitialization来对现有的bean实例进行包装Object current = processor.postProcessAfterInitialization(result, beanName);//一般processor对不感兴趣的bean会回调直接返回result,使其能继续回调后续的BeanPostProcessor;// 但有些processor会返回null来中断其后续的BeanPostProcessor// 如果current为nullif (current == null) {//直接返回result,中断其后续的BeanPostProcessor处理return result;}//让result引用processor的返回结果,使其经过所有BeanPostProcess对象的后置处理的层层包装result = current;}//返回经过所有BeanPostProcess对象的后置处理的层层包装后的resultreturn result;}
AbstractAutoProxyCreator的postProcessAfterInitialization方法。他里面会调用具体的wrapIfNecessary来判断是否要创建代理对象。
@Overridepublic Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {if (bean != null) {// 获取当前bean的key:如果beanName不为空,则以beanName为key,如果为FactoryBean类型,// 前面还会添加&符号,如果beanName为空,则以当前bean对应的class为keyObject cacheKey = getCacheKey(bean.getClass(), beanName);// 判断当前bean是否正在被代理,如果正在被代理则不进行封装if (this.earlyProxyReferences.remove(cacheKey) != bean) {// 如果它需要被代理,则需要封装指定的beanreturn wrapIfNecessary(bean, beanName, cacheKey);}}return bean;}
这里的前面判断逻辑是跟之前是一样,首先会在缓存里面判断当前bean是否已经被处理过,很明显我们当前的logUtil之前已经被解析过并且放入到了缓存中,因为我们的logUtil他是一个切面逻辑他不需要被创建代理对象。
其次会判断当前的bean是否是基础bean,如果是则不用创建带来对象,如果不是则会去盗用shouldSkip方法来判断当前的bean是否需要被跳过,而在这这个shouldSkip方法中我们知道,会寻找容器中的advisor对象。
/*** 先判断是否已经处理过,是否需要跳过,跳过的话直接就放进advisedBeans里,表示不进行代理,如果这个bean处理过了,获取通知拦截器,然后开始进行代理** Wrap the given bean if necessary, i.e. if it is eligible for being proxied.* @param bean the raw bean instance* @param beanName the name of the bean* @param cacheKey the cache key for metadata access* @return a proxy wrapping the bean, or the raw bean instance as-is*/protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {// 如果已经处理过,直接返回if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {return bean;}// 这里advisedBeans缓存了已经进行了代理的bean,如果缓存中存在,则可以直接返回if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {return bean;}// 这里isInfrastructureClass()用于判断当前bean是否为Spring系统自带的bean,自带的bean是// 不用进行代理的;shouldSkip()则用于判断当前bean是否应该被略过if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {// 对当前bean进行缓存this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}// Create proxy if we have advice.// 获取当前bean的Advices和AdvisorsObject[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);// 对当前bean的代理状态进行缓存if (specificInterceptors != DO_NOT_PROXY) {// 对当前bean的代理状态进行缓存this.advisedBeans.put(cacheKey, Boolean.TRUE);// 根据获取到的Advices和Advisors为当前bean生成代理对象Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));// 缓存生成的代理bean的类型,并且返回生成的代理beanthis.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}
然后我们跳过logUtil,看一下真正需要被创建代理对象的 myCalculator。
他会进入到 getAdvicesAndAdvisorsForBean方法中,这个方法就是给当前的bean寻找适配的advisor对象,我们知道advisor对象中包含advice对象,advice对象中包含MethodLocadingFactory还有AspectJExpressionPointcut和SimpleBeanFactoryAwareAspectInstanceFactory对象。
思考一个问题,我们根据什么条件给bean对象创建代理对象,肯定是根据我们配置express表达式来判断哪些包那些类那些对象需要创建代理对象,而Spring的匹配规则主要是通过ClassFilter和MethodMatcher对象来实现的,之前我们只知道advice对象需要一个AspectJExpressionPointCut对象,我们来看下这个类的继承关系图。
@FunctionalInterface
public interface ClassFilter {/*** 是否应该将pointcut应用到给定的接口或者类上** Should the pointcut apply to the given interface or target class?* @param clazz the candidate target class* @return whether the advice should apply to the given target class*/boolean matches(Class<?> clazz);/*** ClassFilter的规范实例能够匹配所有的类** Canonical instance of a ClassFilter that matches all classes.*/ClassFilter TRUE = TrueClassFilter.INSTANCE;}
/*** 一个特殊类型的MethodMatcher接口,当匹配方法的时候需要将说明考虑进去** A specialized type of {@link MethodMatcher} that takes into account introductions* when matching methods. If there are no introductions on the target class,* a method matcher may be able to optimize matching more effectively for example.** @author Adrian Colyer* @since 2.0*/
public interface IntroductionAwareMethodMatcher extends MethodMatcher {/*** Perform static checking whether the given method matches. This may be invoked* instead of the 2-arg {@link #matches(java.lang.reflect.Method, Class)} method* if the caller supports the extended IntroductionAwareMethodMatcher interface.* @param method the candidate method* @param targetClass the target class* @param hasIntroductions {@code true} if the object on whose behalf we are* asking is the subject on one or more introductions; {@code false} otherwise* @return whether or not this method matches statically*/boolean matches(Method method, Class<?> targetClass, boolean hasIntroductions);}
有了以上知识,我们继续往下跟getAdvicesAndAdvisorsForBean方法。
/*** 检查前面切面解析是否有通知器advisors创建,有就返回,没有就是null* @param beanClass the class of the bean to advise* @param beanName the name of the bean* @param targetSource* @return*/@Override@Nullableprotected 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();}
里面是通过findEligibleAdvisors查找合适的advisor对象。
/*** 找到所有符合条件的通知对于自动代理的类** Find all eligible Advisors for auto-proxying this class.* @param beanClass the clazz to find advisors for* @param beanName the name of the currently proxied bean* @return the empty List, not {@code null},* if there are no pointcuts or interceptors* @see #findCandidateAdvisors* @see #sortAdvisors* @see #extendAdvisors*/protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {// 将当前系统中所有的切面类的切面逻辑进行封装,从而得到目标AdvisorList<Advisor> candidateAdvisors = findCandidateAdvisors();// 对获取到的所有Advisor进行判断,看其切面定义是否可以应用到当前bean,从而得到最终需要应用的AdvisorList<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);// 提供的hook方法,用于对目标Advisor进行扩展extendAdvisors(eligibleAdvisors);if (!eligibleAdvisors.isEmpty()) {// 对需要代理的Advisor按照一定的规则进行排序eligibleAdvisors = sortAdvisors(eligibleAdvisors);}return eligibleAdvisors;}
findCandidateAdvisors我们在之前就比较熟悉了,他是寻找容器中所有的advisor对象,他在之前第一次调用的时候就会初始化所有的advisor对象,并且把他放入到缓存中去。
获取得到所有的advisor对象之后就会通过findAdvisorsThatCanApply查找可以应用在当前类的advisor对象,如果找不到适配的advisor对象说明当前对象不需要被代理,直接返回空,表示不需要被代理,我们继续往下看他的匹配过程。
/*** 检测实例化之后的bean是否需要通知器,其实就是检测方法或者类上是否需要事务注解** Search the given candidate Advisors to find all Advisors that* can apply to the specified bean.* @param candidateAdvisors the candidate Advisors* @param beanClass the target's bean class* @param beanName the target's bean name* @return the List of applicable Advisors* @see ProxyCreationContext#getCurrentProxiedBeanName()*/protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {ProxyCreationContext.setCurrentProxiedBeanName(beanName);try {// 从候选的通知器中找到合适正在创建的实例对象的通知器return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);}finally {ProxyCreationContext.setCurrentProxiedBeanName(null);}}
继续往下跟findAdvisorsThatCanApply方法。
/*** 遍历每一个advisor,然后判断是否可以应用到目标类clazz上,可以的话就加入候选列表** Determine the sublist of the {@code candidateAdvisors} list* that is applicable to the given class.* @param candidateAdvisors the Advisors to evaluate* @param clazz the target class* @return sublist of Advisors that can apply to an object of the given class* (may be the incoming List as-is)*/public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {// 若候选的增强器集合为空 直接返回if (candidateAdvisors.isEmpty()) {return candidateAdvisors;}// 定义一个合适的增强器集合对象List<Advisor> eligibleAdvisors = new ArrayList<>();// 循环我们候选的增强器对象,IntroductionAdvisor与PointcutAdvisor本质区别,一个是可以作用在类上,一个是可以作用的方法上for (Advisor candidate : candidateAdvisors) {// 判断我们的增强器对象是不是实现了IntroductionAdvisor (很明显我们事务的没有实现 所以不会走下面的逻辑)if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {eligibleAdvisors.add(candidate);}}// 是否有引介增强boolean hasIntroductions = !eligibleAdvisors.isEmpty();for (Advisor candidate : candidateAdvisors) {// 判断我们的增强器对象是不是实现了IntroductionAdvisorif (candidate instanceof IntroductionAdvisor) {// already processed// 在上面已经处理过,不需要处理continue;}// 真正的判断增强器是否合适当前类型if (canApply(candidate, clazz, hasIntroductions)) {eligibleAdvisors.add(candidate);}}return eligibleAdvisors;}
第一个循环我们所有获取得到的advisor对象,判断当前的advisor对象是否是引介增强,之前我们都知道,我们AOP创建的advisor都是AspectJPointcutAdvisor对象,所以我们跳过,直接看canApply方法。
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {// 如果是IntroductionAdvisor的话,则调用IntroductionAdvisor类型的实例进行类的过滤// 这里是直接调用的ClassFilter的matches方法if (advisor instanceof IntroductionAdvisor) {return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);}// 通常我们的Advisor都是PointcutAdvisor类型else if (advisor instanceof PointcutAdvisor) {// 转为PointcutAdvisor类型PointcutAdvisor pca = (PointcutAdvisor) advisor;//这里从Advisor中获取Pointcut的实现类 这里是AspectJExpressionPointcutreturn canApply(pca.getPointcut(), targetClass, hasIntroductions);}else {// It doesn't have a pointcut so we assume it applies.return true;}}
这里开始也是有一个advisor对象的类型判断,我们继续往下跟他具体实现的canApply方法。
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {Assert.notNull(pc, "Pointcut must not be null");// 进行切点表达式的匹配最重要的就是ClassFilter和MethodMatcher这两个方法的实现。// MethodMatcher中有两个matches方法。一个参数是只有Method对象和targetClass,另一个参数有// Method对象和targetClass对象还有一个Method的方法参数,他们两个的区别是:// 两个参数的matches是用于静态的方法匹配 三个参数的matches是在运行期动态的进行方法匹配的// 先进行ClassFilter的matches方法校验// 首先这个类要在所匹配的规则下if (!pc.getClassFilter().matches(targetClass)) {return false;}// 再进行MethodMatcher方法级别的校验MethodMatcher methodMatcher = pc.getMethodMatcher();if (methodMatcher == MethodMatcher.TRUE) {// No need to iterate the methods if we're matching any method anyway...return true;}// 判断匹配器是不是IntroductionAwareMethodMatcherIntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;if (methodMatcher instanceof IntroductionAwareMethodMatcher) {introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;}// 创建一个集合用于保存targetClass的class对象Set<Class<?>> classes = new LinkedHashSet<>();// 判断当前class是不是代理的class对象if (!Proxy.isProxyClass(targetClass)) {// 加入到集合中去classes.add(ClassUtils.getUserClass(targetClass));}// 获取到targetClass所实现的接口的class对象,然后加入到集合中classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));// 循环所有的class对象for (Class<?> clazz : classes) {// 通过class获取到所有的方法Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);// 循环我们的方法for (Method method : methods) {// 只要有一个方法能匹配到就返回true// 这里就会有一个问题:因为在一个目标中可能会有多个方法存在,有的方法是满足这个切点的匹配规则的// 但是也可能有一些方法是不匹配切点规则的,这里检测的是只有一个Method满足切点规则就返回true了// 所以在运行时进行方法拦截的时候还会有一次运行时的方法切点规则匹配if (introductionAwareMethodMatcher != null ?introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :// 通过方法匹配器进行匹配methodMatcher.matches(method, targetClass)) {return true;}}}return false;}
这里就比较有意思了,首先获取对应的classFilter进行类级别的匹配,然后会在循环方法进行方法级别的匹配。
这里看得到匹配到一个方法就返回true,因为这里只是单纯的判断当前类是否需要创建代理对对象,在后续的创建代理对象的时候会再具体进行匹配,所以这里匹配到一个就直接返回true。
进过以上一系列判断,我们就可以获取得到当前bean适配的所有的advisor对象。
获取得到对应的所有的advisor对象的时候,对调用一个对这些advisor进行拓extendAdvisors,我们继续往下跟。
@Overrideprotected void extendAdvisors(List<Advisor> candidateAdvisors) {AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);}public static boolean makeAdvisorChainAspectJCapableIfNecessary(List<Advisor> advisors) {// Don't add advisors to an empty list; may indicate that proxying is just not requiredif (!advisors.isEmpty()) {boolean foundAspectJAdvice = false;for (Advisor advisor : advisors) {// Be careful not to get the Advice without a guard, as this might eagerly// instantiate a non-singleton AspectJ aspect...if (isAspectJAdvice(advisor)) {foundAspectJAdvice = true;break;}}if (foundAspectJAdvice && !advisors.contains(ExposeInvocationInterceptor.ADVISOR)) {advisors.add(0, ExposeInvocationInterceptor.ADVISOR);return true;}}return false;}
可以看得到他只是给我们的advisor集合中添加了ExposeInvocationInterceptor,这个类的作用是啥呢?在解决这个问题之前,首先问一下大家,我们生成的这个advisor对象在执行切面逻辑的时候是不是会有执行顺序,答案是肯定会有的,那我们如果控制这些advisor的执行顺序呢?
我们看下ExposeInvocationIntercetor里面有啥。
其实他就是通过这个ExposeInvocationInterceptor里面维护的一个ThreadLocal来控制当前的执行的advisor对象 。
public static final Advisor ADVISOR = new DefaultPointcutAdvisor(INSTANCE) {@Overridepublic String toString() {return ExposeInvocationInterceptor.class.getName() +".ADVISOR";}};private static final ThreadLocal<MethodInvocation> invocation =new NamedThreadLocal<>("Current AOP method invocation");/*** 此处是继续调用ReflectiveMethodInvocation的proceed方法来进行递归调用** Return the AOP Alliance MethodInvocation object associated with the current invocation.* @return the invocation object associated with the current invocation* @throws IllegalStateException if there is no AOP invocation in progress,* or if the ExposeInvocationInterceptor was not added to this interceptor chain*/public static MethodInvocation currentInvocation() throws IllegalStateException {MethodInvocation mi = invocation.get();if (mi == null) {throw new IllegalStateException("No MethodInvocation found: Check that an AOP invocation is in progress and that the " +"ExposeInvocationInterceptor is upfront in the interceptor chain. Specifically, note that " +"advices with order HIGHEST_PRECEDENCE will execute before ExposeInvocationInterceptor! " +"In addition, ExposeInvocationInterceptor and ExposeInvocationInterceptor.currentInvocation() " +"must be invoked from the same thread.");}return mi;}
既然我们的advisor有执行顺序,所以spring接下来就是对获取得到的advisor对象进行排序。
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {// 将当前系统中所有的切面类的切面逻辑进行封装,从而得到目标AdvisorList<Advisor> candidateAdvisors = findCandidateAdvisors();// 对获取到的所有Advisor进行判断,看其切面定义是否可以应用到当前bean,从而得到最终需要应用的AdvisorList<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);// 提供的hook方法,用于对目标Advisor进行扩展extendAdvisors(eligibleAdvisors);if (!eligibleAdvisors.isEmpty()) {// 对需要代理的Advisor按照一定的规则进行排序eligibleAdvisors = sortAdvisors(eligibleAdvisors);}return eligibleAdvisors;}
这里的排序就比较麻烦了,他使用到的是一个拓扑有限无环排序,有兴趣的伙伴可以去研究一下这个算法。
最后就会返回排好序的advisor对象,接下来就是真正创建代理对象。在看创建代理对象的之前,如果对cglib跟jdk动态代理源码不是很熟悉的先去看一下之前的博客Spring源码解析(24)之JDK动态代理与cglib动态代理源码解析_spring 选择 jdk 代理 cglib 代理源码-CSDN博客
接下来会先画一个图总结一下,这三篇博客的脉络,然后再往下看他是如何创建代理对象的。