Spring读源码系列之AOP--09---aop源码流程一把拿下

2022-05-10 16:44:47 浏览数 (1)

Spring读源码系列之AOP--09---aop源码流程一把拿下

  • 引言
  • 源码分析
    • AbstractAutoProxyCreator#postProcessAfterInitialization--bean初始化方法被调用后,尝试进行代理创建
      • AbstractAutoProxyCreator#wrapIfNecessary--是否需要对当前传入的bean记性代理
        • AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean--获取可以应用到当前bean上的拦截器链
        • AbstractAdvisorAutoProxyCreator#findEligibleAdvisors--获取可以应用到当前bean上的拦截器链
          • AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors---从当前容器中寻找到所有可用的增强器
          • AbstractAdvisorAutoProxyCreator#findCandidateAdvisors--从容器中获取所有可用的增强器
          • BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors---将所有标注了@AspectJ注解类进行解析,解析为一组advisor增强器链返回
          • ReflectiveAspectJAdvisorFactory#getAdvisors---根据切面工厂,将切面解析为一组advisor增强器链后返回
          • ReflectiveAspectJAdvisorFactory#getAdvisorMethods-获取切面类所有方法,除了@PointCut标注的方法
          • ReflectiveAspectJAdvisorFactory#getAdvisor--如果传入的方法上面标注了增强器相关注解,就转换为对应的增强器,否则返回null
          • ReflectiveAspectJAdvisorFactory#getPointcut--尝试从传入的方法上,获取切点表达式的信息
          • InstantiationModelAwarePointcutAdvisorImpl--通过解析得到的pointcut和对应的增强方法,构建一个默认的AspectJ的advisor
          • InstantiationModelAwarePointcutAdvisorImpl#instantiateAdvice-根据pointcut实现化一个advice
          • ReflectiveAspectJAdvisorFactory#getAdvice-根据advicemethod和pointcut生成对应的adivce
      • 小憩
        • AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply--判断传入的候选增强器集合能否应用到当前bean上
        • AopUtils.findAdvisorsThatCanApply---真正干活的方法
        • introductionAwareMethodMatcher.matches---切点为AspectJExpressionPointcut时,matches方法需要特殊处理
    • 小憩
      • AbstractAutoProxyCreator#createProxy---创建代理对象
        • ProxyFactory#getProxy---获取代理对象
        • ProxyCreatorSupport#createAopProxy---创建代理对象,不过返回的是包裹代理对象的AopProxy
        • DefaultAopProxyFactory#createAopProxy---选择jdk还是cglib完成动态代理的地方
        • AopProxy#getProxy--返回代理对象
  • 小结

引言

上一篇文章已经详细介绍了两种aop自动代理创建器的导入流程分析,此时我们已经知道了自动代理创建器注册到容器中的流程,下面我们来探究一下,自动代理创建器对具体bean创建代理的流程,这里测试环境还是用上一篇中开头给出的测试环境。

Spring读源码系列之AOP–08–aop执行完整源码流程之自动代理创建器导入的两种方式


源码分析

首先我们需要知道AnnotationAwareAspectJAutoProxyCreator是一个bean的后置处理器(Spring读源码系列之AOP–07—aop自动代理创建器(拿下AOP的最后一击))

这里对有关自动代理的后置处理器相关回调接口被调用时机不清楚的,看上面给出的那篇文章链接

对bean初始化源码流程不清楚的,去看我之前写的bean初始化流程源码分析


AbstractAutoProxyCreator#postProcessAfterInitialization–bean初始化方法被调用后,尝试进行代理创建

AbstractAutoProxyCreator是AnnotationAwareAspectJAutoProxyCreator的父类

postProcessAfterInitialization方法在该类中进行实现

代码语言:javascript复制
	@Override
	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			//如果当前bean还没有通过getEarlyBeanReference方法提早暴露出去,那么尝试进行代理
			//因为getEarlyBeanReference方法会尝试对提早暴露的bean进行代理,同样也是调用wrapIfNecessary方法
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

AbstractAutoProxyCreator#wrapIfNecessary–是否需要对当前传入的bean记性代理

代码语言:javascript复制
	protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
	//如果已经处理过,不需要代理,是基础类,是OriginalInstance,那么当前bean都应该直接跳过,不做任何操作
		if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// Create proxy if we have advice.
		//获取到可以应用到当前bean上的拦截器链
		//getAdvicesAndAdvisorsForBean在AbstractAutoProxyCreator类中为抽象方法,留给不同的子类去实现
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		//DO_NOT_PROXY代表一个空的Object[],如果不为空,说明需要代理
		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#getAdvicesAndAdvisorsForBean–获取可以应用到当前bean上的拦截器链
代码语言:javascript复制
	protected Object[] getAdvicesAndAdvisorsForBean(
			Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
        //findEligibleAdvisors--寻找可用于当前bean上的增强器
		List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
		if (advisors.isEmpty()) {
			return DO_NOT_PROXY;
		}
		return advisors.toArray();
	}

AbstractAdvisorAutoProxyCreator#findEligibleAdvisors–获取可以应用到当前bean上的拦截器链
代码语言:javascript复制
	protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
	//获取容器中所有Advisor类型bean
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
	//进行过滤,找到能应用到当前bean上的拦截器链
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
	//钩子方法,子类实现用来新增拦截器到拦截器链中
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
		//对拦截器链中的拦截器进行排序操作
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}

AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors—从当前容器中寻找到所有可用的增强器
代码语言:javascript复制
	protected List<Advisor> findCandidateAdvisors() {
		// Add all the Spring advisors found according to superclass rules.
		//父类借助advisorRetrievalHelper去容器中获取所有可用的增强器
		List<Advisor> advisors = super.findCandidateAdvisors();
		// Build Advisors for all AspectJ aspects in the bean factory.
		if (this.aspectJAdvisorsBuilder != null) {
			advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
		}
		return advisors;
	}

AbstractAdvisorAutoProxyCreator#findCandidateAdvisors–从容器中获取所有可用的增强器
代码语言:javascript复制
	protected List<Advisor> findCandidateAdvisors() {
		Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
		return this.advisorRetrievalHelper.findAdvisorBeans();
	}

advisorRetrievalHelper的findAdvisorBeans方法

代码语言:javascript复制
	public List<Advisor> findAdvisorBeans() {
		// Determine list of advisor bean names, if not cached already.
		String[] advisorNames = this.cachedAdvisorBeanNames;
		if (advisorNames == null) {
			// Do not initialize FactoryBeans here: We need to leave all regular beans
			// uninitialized to let the auto-proxy creator apply to them!
			//从容器中拿取到所有类型为Advisor的bean
			advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
					this.beanFactory, Advisor.class, true, false);
			this.cachedAdvisorBeanNames = advisorNames;
		}
		if (advisorNames.length == 0) {
			return new ArrayList<>();
		}

		List<Advisor> advisors = new ArrayList<>();
		for (String name : advisorNames) {
		//isEligibleBean通过正则匹配之类的方法,先过滤掉一批增强器
			if (isEligibleBean(name)) {
			//跳过正在创建的增强器
				if (this.beanFactory.isCurrentlyInCreation(name)) {
					if (logger.isTraceEnabled()) {
						logger.trace("Skipping currently created advisor '"   name   "'");
					}
				}
				else {
					try {
					//加入增强器集合,然后返回
						advisors.add(this.beanFactory.getBean(name, Advisor.class));
					}
...
				}
			}
		}
		return advisors;
	}

BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors—将所有标注了@AspectJ注解类进行解析,解析为一组advisor增强器链返回
代码语言:javascript复制
	public List<Advisor> buildAspectJAdvisors() {
		List<String> aspectNames = this.aspectBeanNames;
		//如果此时aspectBeanNames为空
         //下面会去容器中解析出所有标注了AspectJ注解的切面类,然后将其解析为一组增强器链
		if (aspectNames == null) {
			synchronized (this) {
				aspectNames = this.aspectBeanNames;
				if (aspectNames == null) {
					List<Advisor> advisors = new ArrayList<>();
					aspectNames = new ArrayList<>();
					//拿到容器中所有的bean
					String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
							this.beanFactory, Object.class, true, false);
					for (String beanName : beanNames) {
					//通过正则表达式之类的匹配式,先过滤掉一批不符合的bean
						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.
						Class<?> beanType = this.beanFactory.getType(beanName, false);
						if (beanType == null) {
							continue;
						}
						//当前bean的上要标注了AspectJ注解才可以
						if (this.advisorFactory.isAspect(beanType)) {
							aspectNames.add(beanName);
							//为当前标注了AspectJ注解的切面类构造一个切面类元数据信息
							AspectMetadata amd = new AspectMetadata(beanType, beanName);
							//如果切面是单例的,这里的单例指的是@AspectJ("singleton"),默认都是单例的
							if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
							//创建生成切面对象的工厂
								MetadataAwareAspectInstanceFactory factory =
										new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
							//AspectJAdvisorFactory可以根据MetadataAwareAspectInstanceFactory
							//获取到当前切面解析后的一组增强器链
								List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
								//将解析后的结果进行保存,即当前切面已经关联了一组增强器链
								if (this.beanFactory.isSingleton(beanName)) {
									this.advisorsCache.put(beanName, classAdvisors);
								}
								else {
								//如果当前切面是多例的--这里的多例指的是spring层面的多例
									this.aspectFactoryCache.put(beanName, factory);
								}
								advisors.addAll(classAdvisors);
							}
							else {
							//如果是Aspectj层面的其他类型的切面,例如perthis,pertarget,这里不多讲
								// 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();
		}
		//如果第二次来,此时aspectBeanNames不为null,那么尝试从缓存中获取,如果缓存中获取不到,再通过AspectJAdvisorFactory去获取
		List<Advisor> advisors = new ArrayList<>();
		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;
	}

ReflectiveAspectJAdvisorFactory#getAdvisors—根据切面工厂,将切面解析为一组advisor增强器链后返回
代码语言:javascript复制
	@Override
	public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
	//拿到切面工厂中保存的切面的class和切面name
		Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
		//对切面类进行校验,如果父类上也有AspectJ注解,但是父类不是抽象的,那么会抛出异常,并且当前切面必须是默认的单例--aspectj层面的
		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 ArrayList<>();
		//getAdvisorMethods--获取切面类中所有方法,除了被Pointcut注解标注的方法,并且这所有方法还包括其父类继承链的,继承的接口方法
		for (Method method : getAdvisorMethods(aspectClass)) {
			// Prior to Spring Framework 5.2.7, advisors.size() was supplied as the declarationOrderInAspect
			// to getAdvisor(...) to represent the "current position" in the declared methods list.
			// However, since Java 7 the "current position" is not valid since the JDK no longer
			// returns declared methods in the order in which they are declared in the source code.
			// Thus, we now hard code the declarationOrderInAspect to 0 for all advice methods
			// discovered via reflection in order to support reliable advice ordering across JVM launches.
			// Specifically, a value of 0 aligns with the default value used in
			// AspectJPrecedenceComparator.getAspectDeclarationOrder(Advisor).
			//将该adviceMethod构造为一个Adv返回isor 
			Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		// If it's a per target aspect, emit the dummy instantiating aspect.
		//如果当前aspectJ不是signleton的,那么做相关处理
		//默认都是单例的(不是spring层面的,是aspectj层面的)
		if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
			Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
			advisors.add(0, instantiationAdvisor);
		}

		// Find introduction fields.
		//@DeclareParents注解的处理,引介增强处理--这里先不讲,感兴趣可以自己去了解一下
		for (Field field : aspectClass.getDeclaredFields()) {
			Advisor advisor = getDeclareParentsAdvisor(field);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		return advisors;
	}

ReflectiveAspectJAdvisorFactory#getAdvisorMethods-获取切面类所有方法,除了@PointCut标注的方法
代码语言:javascript复制
	private List<Method> getAdvisorMethods(Class<?> aspectClass) {
		List<Method> methods = new ArrayList<>();
		//adviceMethodFilter会过滤掉被pointCut标注的方法
		//methods::add向methods集合存入当前切面类除了被过滤掉以外的方法
		ReflectionUtils.doWithMethods(aspectClass, methods::add, adviceMethodFilter);
		if (methods.size() > 1) {
			methods.sort(adviceMethodComparator);
		}
		return methods;
	}

adviceMethodFilter比较简单:

代码语言:javascript复制
	// Exclude @Pointcut methods
	private static final MethodFilter adviceMethodFilter = ReflectionUtils.USER_DECLARED_METHODS
			.and(method -> (AnnotationUtils.getAnnotation(method, Pointcut.class) == null));

ReflectionUtils的doWithMethods方法

代码语言:javascript复制
	public static void doWithMethods(Class<?> clazz, MethodCallback mc, @Nullable MethodFilter mf) {
		// Keep backing up the inheritance hierarchy.
		Method[] methods = getDeclaredMethods(clazz, false);
		for (Method method : methods) {
		//过滤器进行过滤
			if (mf != null && !mf.matches(method)) {
				continue;
			}
			try {
			//mc.dowith操作就是将合法的方法加入集合
				mc.doWith(method);
			}
			catch (IllegalAccessException ex) {
				throw new IllegalStateException("Not allowed to access method '"   method.getName()   "': "   ex);
			}
		}
		//还会沿着继承链一之去找,直到找到Object为止
		if (clazz.getSuperclass() != null && (mf != USER_DECLARED_METHODS || clazz.getSuperclass() != Object.class)) {
			doWithMethods(clazz.getSuperclass(), mc, mf);
		}
		//继承的接口里面的方法也不会放过
		else if (clazz.isInterface()) {
			for (Class<?> superIfc : clazz.getInterfaces()) {
				doWithMethods(superIfc, mc, mf);
			}
		}
	}

ReflectiveAspectJAdvisorFactory#getAdvisor–如果传入的方法上面标注了增强器相关注解,就转换为对应的增强器,否则返回null
代码语言:javascript复制
	public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
			int declarationOrderInAspect, String aspectName) {
		//对切面类进行校验,如果父类上也有AspectJ注解,但是父类不是抽象的,那么会抛出异常,并且当前切面必须是默认的单例--aspectj层面的
		validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
        //尝试去获取当前方法上的pointcut,如果获取不到,说明当前方法不是增强器方法
        //这里不是去获取pointcut注解内的切点表达式,pointcut注解标注的方法在 getAdvisorMethods中就已经被过滤掉了
        //这里获取到的是@Before("切点表达式")或者@Before("excution(* *.*.*.(..)")
		AspectJExpressionPointcut expressionPointcut = getPointcut(
				candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
		//返回的	AspectJExpressionPointcut 为null,说明当前方法上没有标注相关增强器注解	
		if (expressionPointcut == null) {
			return null;
		}
       //构造一个aspectJ相关的advisor返回  
		return new InstantiationModelAwarePointcutAdvisorImpl(
//切点表达式          advice方法  
expressionPointcut, candidateAdviceMethod,
           //当前ReflectiveAspectJAdvisorFactory工厂        
				this, aspectInstanceFactory, 
//固定为0                  切面名    
declarationOrderInAspect, aspectName);
	}

ReflectiveAspectJAdvisorFactory#getPointcut–尝试从传入的方法上,获取切点表达式的信息
代码语言:javascript复制
	@Nullable
	private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
	//寻找到方法上第一个出现的增强器注解,如@Before,@After...
		AspectJAnnotation<?> aspectJAnnotation =
				AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
	//没找到,返回null,说明当前方法不是增强器方法	
		if (aspectJAnnotation == null) {
			return null;
		}
      //构造一个AspectJExpressionPointcut
		AspectJExpressionPointcut ajexp =
				new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
	//设置AspectJExpressionPointcut的切点表达式,即@Before("切点表达式")
	//当然括号里面可以直接是切点表达式,也可以是一个方法名(),该方法上标注的pointcut注解中写了真正的切点表达式
	//所以一般情况下,这里拿到的切点表达式都长这个样子: point()
		ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
	//设置该AspectJExpressionPointcut 关联的IOC容器
		if (this.beanFactory != null) {
			ajexp.setBeanFactory(this.beanFactory);
		}
		return ajexp;
	}

AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod方法

查找并返回给定方法的第一个 AspectJ 注解(无论如何应该只有一个…)。

代码语言:javascript复制
	private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class<?>[] {
			Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};
代码语言:javascript复制
	protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
		for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
			AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
			if (foundAnnotation != null) {
				return foundAnnotation;
			}
		}
		return null;
	}

InstantiationModelAwarePointcutAdvisorImpl–通过解析得到的pointcut和对应的增强方法,构建一个默认的AspectJ的advisor
代码语言:javascript复制
	public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
			Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
			MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
        //pointcut
		this.declaredPointcut = declaredPointcut;
		//切面类型
		this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
		//增强方法名
		this.methodName = aspectJAdviceMethod.getName();
		//增强方法的参数类型数组
		this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
		//增强方法
		this.aspectJAdviceMethod = aspectJAdviceMethod;
		//解析切面类,创建advisor的工厂
		this.aspectJAdvisorFactory = aspectJAdvisorFactory;
		//生产切面的工厂
		this.aspectInstanceFactory = aspectInstanceFactory;
		//固定为0
		this.declarationOrder = declarationOrder;
		//切面名
		this.aspectName = aspectName;

       //如果切面是懒加载的
       //isLazilyInstantiated--->return (isPerThisOrPerTarget() || isPerTypeWithin());
       //因此这里先不用管,默认切面都是单例的
		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 {
		//切面是单例的,这里的单例是aspectj层面的
			// A singleton aspect.
			this.pointcut = this.declaredPointcut;
			this.lazy = false;
			//根据declaredPointcut实例化得到对应的advice
			this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
		}
	}

InstantiationModelAwarePointcutAdvisorImpl#instantiateAdvice-根据pointcut实现化一个advice
代码语言:javascript复制
	private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
	//内部还是靠aspectJAdvisorFactory来完成
		Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
				this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
		return (advice != null ? advice : EMPTY_ADVICE);
	}

ReflectiveAspectJAdvisorFactory#getAdvice-根据advicemethod和pointcut生成对应的adivce
代码语言:javascript复制
	@Override
	@Nullable
	public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
			MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
        //拿到切面类型
		Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		validate(candidateAspectClass);
       //拿到当前advicemethod上标注的增强器注解
		AspectJAnnotation<?> aspectJAnnotation =
				AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
		//为空直接返回--说明不是一个增强器方法
		if (aspectJAnnotation == null) {
			return null;
		}

		// If we get here, we know we have an AspectJ method.
		// Check that it's an AspectJ-annotated class
		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()) {
		//pointcut注解跳过
			case AtPointcut:
				if (logger.isDebugEnabled()) {
					logger.debug("Processing pointcut '"   candidateAdviceMethod.getName()   "'");
				}
				return null;
		//增强方法上标注的是around注解		
			case AtAround:
			//构造AspectJAroundAdvice返回
				springAdvice = new AspectJAroundAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
		//before注解
			case AtBefore:
				springAdvice = new AspectJMethodBeforeAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
		//after注解
			case AtAfter:
				springAdvice = new AspectJAfterAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
		//afterreturning注解
			case AtAfterReturning:
				springAdvice = new AspectJAfterReturningAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
				//可以指定接收的返回变量名或者变量类型
				if (StringUtils.hasText(afterReturningAnnotation.returning())) {
					springAdvice.setReturningName(afterReturningAnnotation.returning());
				}
				break;
		//afterreturning注解		
			case AtAfterThrowing:
				springAdvice = new AspectJAfterThrowingAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
				if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
					//可以指定接收的异常名或异常类型
					springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
				}
				break;
			default:
				throw new UnsupportedOperationException(
						"Unsupported advice type on method: "   candidateAdviceMethod);
		}

		// Now to configure the advice...
		//设置切面名
		springAdvice.setAspectName(aspectName);
		//固定为0
		springAdvice.setDeclarationOrder(declarationOrder);
		//获取增强方法的参数名数组
		String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
		if (argNames != null) {
		//设置到advice中
			springAdvice.setArgumentNamesFromStringArray(argNames);
		}
		//计算参数绑定--感兴趣的可以研究一下--这里也可以看出joinpoint只能放在advice方法第一个参数位置
		springAdvice.calculateArgumentBindings();

		return springAdvice;
	}

小憩

上面大部分代码流程都是在找所有可用的增强器候选集合,即findCandidateAdvisors

代码语言:javascript复制
	protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}

下面既然已经拿到了所有可能会用到的候选增强器集合,那么下面就是判断这些增强器能否应用到当前被拦截的bean上,如果不能,说明当前bean不需要被代理


AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply–判断传入的候选增强器集合能否应用到当前bean上
代码语言:javascript复制
	protected List<Advisor> findAdvisorsThatCanApply(
			List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

		ProxyCreationContext.setCurrentProxiedBeanName(beanName);
		try {
		//利用aoputils这个工具类来判断
			return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
		}
		finally {
			ProxyCreationContext.setCurrentProxiedBeanName(null);
		}
	}
AopUtils.findAdvisorsThatCanApply—真正干活的方法
代码语言:javascript复制
	public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
		if (candidateAdvisors.isEmpty()) {
			return candidateAdvisors;
		}
		List<Advisor> eligibleAdvisors = new ArrayList<>();
		for (Advisor candidate : candidateAdvisors) {
		//优先处理IntroductionAdvisor ,然后通过canApply方法进行最终判决
			if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
				eligibleAdvisors.add(candidate);
			}
		}
		boolean hasIntroductions = !eligibleAdvisors.isEmpty();
		for (Advisor candidate : candidateAdvisors) {
		//IntroductionAdvisor上面处理过了
			if (candidate instanceof IntroductionAdvisor) {
				// already processed
				continue;
			}
			//其他类型的Advisor 进行最终判决
			if (canApply(candidate, clazz, hasIntroductions)) {
				eligibleAdvisors.add(candidate);
			}
		}
		//返回最终适合作用于当前类上的增强器链集合
		return eligibleAdvisors;
	}

canapply方法:

代码语言:javascript复制
	public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
	//如果是IntroductionAdvisor,就直接进行类过滤即可
		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;
		}
	}

canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions)重载方法

代码语言:javascript复制
	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;
		}
       //再进行方法过滤---如果AspectJExpressionPointcut,那么这里返回的是他自己
       //因为他实现了IntroductionAwareMethodMatcher接口
		MethodMatcher methodMatcher = pc.getMethodMatcher();
		if (methodMatcher == MethodMatcher.TRUE) {
			// No need to iterate the methods if we're matching any method anyway...
			return true;
		}
        
        //AspetJ会使用IntroductionAwareMethodMatcher,通过切点表达式进行过滤匹配
		IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
		if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
			introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
		}

		Set<Class<?>> classes = new LinkedHashSet<>();
		//如果当前类不是是jdk代理类了
		if (!Proxy.isProxyClass(targetClass)) {
		//那么再判断是否是cglib代理类,如果是拿到其superClass,即目标对象类型
			classes.add(ClassUtils.getUserClass(targetClass));
		}
		//上面可以确保拿到的是目标对象类型,而不是代理对象的class类型
		//下面再将目标对象实现的接口全部加入集合中去
		classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

		for (Class<?> clazz : classes) {
		//遍历该集合,获取每个class里面的所有方法
			Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
			for (Method method : methods) {
			//如果introductionAwareMethodMatcher 不为空,说明Pointcut为AspectJExpressionPointcut
			//挨个方法,调用introductionAwareMethodMatcher 的matches方法进行匹配
			//如果introductionAwareMethodMatcher 为null,那么为普通pointCut,调用methodMatcher.matches方法进行匹配
				if (introductionAwareMethodMatcher != null ?
						introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
						methodMatcher.matches(method, targetClass)) {
					return true;
				}
			}
		}

		return false;
	}

introductionAwareMethodMatcher.matches—切点为AspectJExpressionPointcut时,matches方法需要特殊处理
代码语言:javascript复制
	@Override
	public boolean matches(Method method, Class<?> targetClass, boolean hasIntroductions) {
	//获取切点表达式---默认在BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors方法中就已经全部解析好了
		obtainPointcutExpression();
	//获取目标方法和切点表达式的匹配结果---这个过程比较复杂,这里就不多展开了,核心原理就是获取到切点表达式
	//然后通过切点表达式判断当前放是否会被切入,结果封装在了	ShadowMatch 中
		ShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass);

		// Special handling for this, target, @this, @target, @annotation
		// in Spring - we can optimize since we know we have exactly this class,
		// and there will never be matching subclass at runtime.
		//一般要么是alwaysMatches表示切入成功,要么是neverMatches表示切入失败
		if (shadowMatch.alwaysMatches()) {
			return true;
		}
		else if (shadowMatch.neverMatches()) {
			return false;
		}
		else {
		//一般很少使用: 因为当我们在切点表达式用到一些动态参数,需要运行时进行判断时,才会产生不确定性
			// the maybe case
			if (hasIntroductions) {
				return true;
			}
			// A match test returned maybe - if there are any subtype sensitive variables
			// involved in the test (this, target, at_this, at_target, at_annotation) then
			// we say this is not a match as in Spring there will never be a different
			// runtime subtype.
			RuntimeTestWalker walker = getRuntimeTestWalker(shadowMatch);
			return (!walker.testsSubtypeSensitiveVars() || walker.testTargetInstanceOfResidue(targetClass));
		}
	}

小憩

到这里,我们已经走完了wrapIfNecessary一大半的方法,advisors增强器链已经创建出来了,下一步就是创建代理了

代码语言:javascript复制
	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;
		}
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// Create proxy if we have advice.
		Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
		if (specificInterceptors != DO_NOT_PROXY) {
			this.advisedBeans.put(cacheKey, Boolean.TRUE);
			//创建代理
			Object proxy = createProxy(
			       //目标对象类型,目标对象名,增强器链,SingletonTargetSource
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		//需要代理,返回代理类,否则返回原样的bean
		return bean;
	}

AbstractAutoProxyCreator#createProxy—创建代理对象
代码语言:javascript复制
//创建代理对象
	protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {

		if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
			AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
		}
        //每个代理类都对应一个ProxyFactory
		ProxyFactory proxyFactory = new ProxyFactory();
		//这里copy的是ProxyConfig的配置,两者都继承了该类
		proxyFactory.copyFrom(this);

       //isProxyTargetClass为true,说明要用cglib代理
		if (proxyFactory.isProxyTargetClass()) {
			// Explicit handling of JDK proxy targets (for introduction advice scenarios)
			//如果当前bean是jdk的代理类
			if (Proxy.isProxyClass(beanClass)) {
				// Must allow for introductions; can't just set interfaces to the proxy's interfaces only.
				for (Class<?> ifc : beanClass.getInterfaces()) {
					//拿到jdk代理类继承的所有接口,添加进当前proxyFactory
					proxyFactory.addInterface(ifc);
				}
			}
		}
		else {
			// No proxyTargetClass flag enforced, let's apply our default checks...
			//shouldProxyTargetClass返回值取决于:Boolean.TRUE.equals(bd.getAttribute(PRESERVE_TARGET_CLASS_ATTRIBUTE));
			//即当前bean定义中的PRESERVE_TARGET_CLASS_ATTRIBUTE是否存在,并且对应的值是否为true,如果为true,则采用cglib进行代理
			if (shouldProxyTargetClass(beanClass, beanName)) {
				proxyFactory.setProxyTargetClass(true);
			}
			else {
			//进行常规判断,该方法属于父类ProxyProcessorSupport
			//通过对目标对象实现的接口进行分析,判断是采用jdk还是cglib进行动态代理
				evaluateProxyInterfaces(beanClass, proxyFactory);
			}
		}
       //拦截器和targetSource设置进proxyFactory
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		proxyFactory.addAdvisors(advisors);
		proxyFactory.setTargetSource(targetSource);
		//空实现,子类可以进行定制操作
		customizeProxyFactory(proxyFactory);

		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

		// Use original ClassLoader if bean class not locally loaded in overriding class loader
		ClassLoader classLoader = getProxyClassLoader();
		if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
			classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
		}
		//创建代理对象
		return proxyFactory.getProxy(classLoader);

buildAdvisors方法:

代码语言:javascript复制
/**
	 * Determine the advisors for the given bean, including the specific interceptors
	 * as well as the common interceptor, all adapted to the Advisor interface.
	 */
	protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
		// Handle prototypes correctly...
		//commonInterceptors是公共拦截器,即会应用到所有被该自动创建器创建的代理对象上
		//这里解析的是用户设置的commonInterceptors的beanNames数组,默认为空
		//resolveInterceptorNames就是拿着beanName去IOC容器中找出对应的bean,再通过适配器转换为统一的advisor后返回
		Advisor[] commonInterceptors = resolveInterceptorNames();
       
		List<Object> allInterceptors = new ArrayList<>();
		if (specificInterceptors != null) {
		//可以应用到当前目标对象上的拦截器链加入集合
			if (specificInterceptors.length > 0) {
				// specificInterceptors may equal PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS
				allInterceptors.addAll(Arrays.asList(specificInterceptors));
			}
			//公共拦截器链加入集合
			if (commonInterceptors.length > 0) {
				if (this.applyCommonInterceptorsFirst) {
					allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
				}
				else {
					allInterceptors.addAll(Arrays.asList(commonInterceptors));
				}
			}
		}
		if (logger.isTraceEnabled()) {
			int nrOfCommonInterceptors = commonInterceptors.length;
			int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
			logger.trace("Creating implicit proxy for bean '"   beanName   "' with "   nrOfCommonInterceptors  
					" common interceptors and "   nrOfSpecificInterceptors   " specific interceptors");
		}
        
        //进行适配操作
		Advisor[] advisors = new Advisor[allInterceptors.size()];
		for (int i = 0; i < allInterceptors.size(); i  ) {
			advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
		}
		return advisors;
	}

ProxyFactory#getProxy—获取代理对象
代码语言:javascript复制
	public Object getProxy(@Nullable ClassLoader classLoader) {
		return createAopProxy().getProxy(classLoader);
	}

ProxyCreatorSupport#createAopProxy—创建代理对象,不过返回的是包裹代理对象的AopProxy
代码语言:javascript复制
	protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();
		}
		//返回的是DefaultAopProxyFactory,这里我们直接看DefaultAopProxyFactory的createAopProxy方法
		return getAopProxyFactory().createAopProxy(this);
	}

DefaultAopProxyFactory#createAopProxy—选择jdk还是cglib完成动态代理的地方
代码语言:javascript复制
	@Override
	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		if (!NativeDetector.inNativeImage() &&
		//如果proxyConfig的Optimize或者proxyTargetClass或者当前类没有实现任何接口,那么都将采用cglib完成代理
				(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
			Class<?> targetClass = config.getTargetClass();
			if (targetClass == null) {
				throw new AopConfigException("TargetSource cannot determine target class: "  
						"Either an interface or a target is required for proxy creation.");
			}
			//但是,如果目标对象是个接口,或者目标对象是jdk代理类,那么还是使用jdk完成动态代理
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			//cglib完成动态代理
			return new ObjenesisCglibAopProxy(config);
		}
		else {
		//jdk完成动态代理
			return new JdkDynamicAopProxy(config);
		}
	}

	/**
	 * Determine whether the supplied {@link AdvisedSupport} has only the
	 * {@link org.springframework.aop.SpringProxy} interface specified
	 * (or no proxy interfaces specified at all).
	 */
	private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
		Class<?>[] ifcs = config.getProxiedInterfaces();
		return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
	}

AopProxy#getProxy–返回代理对象

这里就不继续深入挖掘了,因为还需要对JdkDynamicAopProxy和ObjenesisCglibAopProxy区分讨论,感兴趣的可以看我之前写的文章,链接如下:

Spring读源码系列之AOP–06—AopProxy===>spring使用jdk和cglib生成代理对象的终极奥义


小结

到此,一个代理对象被创建的完整流程就已经讲完了,这也是aop在spring中的灵魂流程

0 人点赞