回首Spring源码之AOP:解析切面(aspect)

前言

        之前分析了spring容器创建bean的整个流程,其中涉及到了bean的后置处理器的几处调用,其中在bean的实例化前置调用中,aop会在此处解析aspect切面,我们先来回顾一下这个BeanPostProcessor。

解析切面

//bean后置处理器实例化前置处理
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);


protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
		Object bean = null;
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
			// Make sure bean class is actually resolved at this point.
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
				Class<?> targetType = determineTargetType(beanName, mbd);
				if (targetType != null) {
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
					if (bean != null) {
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
}


protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                //循环调用InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
				Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
				if (result != null) {
					return result;
				}
			}
		}
		return null;
}

        在上篇讲到的@EnableAspectjAutoProxy中引入的bean实现了InstantiationAwareBeanPostProcessor ,下面来到AbstractAutoProxyCreator#postProcessBeforeInstantiation:

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
		//首先时获取缓存,类似这种缓存在送spring中广泛使用
		Object cacheKey = getCacheKey(beanClass, beanName);
		//这里的targetSourcedBeans也是一个缓存,缓存了通过customTargetSourceCreators创建了代理的bean
		//customTargetSourceCreators是留给开发者的一个扩展点,用以指定bean代理的目标对象
		if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
			if (this.advisedBeans.containsKey(cacheKey)) {
				//表示之前已经判断过了,跳过
				return null;
			}
            最重要的方法shouldSkip,在这里解析切面
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				//表示这个bean不需要被代理,跳过
				this.advisedBeans.put(cacheKey, Boolean.FALSE);
				return null;
			}
		}

		//下面这个if:如果指定了CustomTargetSource,那么提前为bean创建代理,创建代理的过程和aop一样,只是targetSource换成了指定的CustomTargetSource
		TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
		if (targetSource != null) {
			if (StringUtils.hasLength(beanName)) {
				this.targetSourcedBeans.add(beanName);
			}
			Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
			Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		return null;
}

下面进入shouldSkip方法解析切面:

protected boolean shouldSkip(Class<?> beanClass, String beanName) {
		//findCandidateAdvisors找到容器中所有Advisor,并且实例化
		//Advisor在aop中为通知类,其中包括了adivce通知和pointcut切点
		//aspect类中的每个通知方法都会被解析成一个Advisor
		//AnnotationAwareAspectJAutoProxyCreator这个bean会在这里解析切面
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		for (Advisor advisor : candidateAdvisors) {
			if (advisor instanceof AspectJPointcutAdvisor &&
					((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
				return true;
			}
		}
		//调用父类的shouldSkip
		return super.shouldSkip(beanClass, beanName);
}


protected List<Advisor> findCandidateAdvisors() {
		//调用父类findCandidateAdvisors拿到容器中所有的Advisor
		//一般为空,引入声明式事务的话会有相应的Advisor
		List<Advisor> advisors = super.findCandidateAdvisors();
		if (this.aspectJAdvisorsBuilder != null) {
			//aspectJAdvisorsBuilder.buildAspectJAdvisors()解析切面
			advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
		}
		return advisors;
}

下面进入解析aspect切面的过程:

public List<Advisor> buildAspectJAdvisors() {
		//这里又是缓存
		List<String> aspectNames = this.aspectBeanNames;

		if (aspectNames == null) {
			synchronized (this) {
				aspectNames = this.aspectBeanNames;
				if (aspectNames == null) {
					List<Advisor> advisors = new ArrayList<>();
					aspectNames = new ArrayList<>();
					//拿到容器中所有beanName
					String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
							this.beanFactory, Object.class, true, false);
					for (String beanName : beanNames) {
						//isEligibleBean总返回true
						if (!isEligibleBean(beanName)) {
							continue;
						}
						//拿到bean的class类型
						Class<?> beanType = this.beanFactory.getType(beanName, false);
						if (beanType == null) {
							continue;
						}
						//判断类上是否有aspectj注解
						if (this.advisorFactory.isAspect(beanType)) {
							aspectNames.add(beanName);
							//创建切面元数据对象
							AspectMetadata amd = new AspectMetadata(beanType, beanName);
							//默认一般都是单例
							if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
								//创建切面实例工厂
								MetadataAwareAspectInstanceFactory factory =
										new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
								//解析切面中的通知方法,返回一个Advisor集合
								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 ArrayList<>();
		//下面这个循环将解析出来的Advisor加入返回的集合advisors
		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;
}

真正解析切面的 this.advisorFactory.getAdvisors(factory):

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
		//拿到切面类class,就是打了aspect注解的对象
		Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		//切面名称
		String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
		validate(aspectClass);

		//对aspectInstanceFactory进行装饰,可以理解为一个静态代理,代理了aspectInstanceFactory的getAspectInstance方法
		//代理了aspectInstanceFactory的getAspectInstance方法,它会直接调用getBean获取bean对象
		//这里lazySingletonAspectInstanceFactory是new出来的对象
        //对于同一个lazySingletonAspectInstanceFactory对象没必要创建多次AspectInstance,
        //所以在lazySingletonAspectInstanceFactory对这方法代理,缓存了AspectInstance实例对象
		MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
				new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

		List<Advisor> advisors = new ArrayList<>();
        //getAdvisorMethods(aspectClass)会拿到除了@Pointcut注解的方法外的所有方法
		for (Method method : getAdvisorMethods(aspectClass)) {
            //将通知方法解析为一个Advisor
			Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		//这里对不是单例的aspect处理,几乎不用
		if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
			Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
			advisors.add(0, instantiationAdvisor);
		}

		//aop中的introduction,也几乎不用,不去了解
		for (Field field : aspectClass.getDeclaredFields()) {
			Advisor advisor = getDeclareParentsAdvisor(field);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		return advisors;
}


public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
			int declarationOrderInAspect, String aspectName) {

		validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());

		// 获得当前通知的 切点表达式
		AspectJExpressionPointcut expressionPointcut = getPointcut(
				candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
		if (expressionPointcut == null) {
			return null;
		}
		// 将切点表达式、 和通知  封装到InstantiationModelAwarePointcutAdvisorImpl对象中
		return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
				this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}


//获取切点的方法
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
		//获取方法上的通知注解,@Around @Before @After  @AfterReturning  @AfterThrowing
		AspectJAnnotation<?> aspectJAnnotation =
				AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
		if (aspectJAnnotation == null) {
			return null;
		}
		//用通知注解构建AspectJExpressionPointcut切点
		AspectJExpressionPointcut ajexp =
				new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
		//设置切点表达式Expression
		ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
		if (this.beanFactory != null) {
			ajexp.setBeanFactory(this.beanFactory);
		}
		return ajexp;
}

再看一下通知器对象的构造方法:

public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
			Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
			MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

		//当前的切点
		this.declaredPointcut = declaredPointcut;
		//切面的class对象
		this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
		//切面方法的名称
		this.methodName = aspectJAdviceMethod.getName();
		//切面方法的参数类型
		this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
		//切面方法对象
		this.aspectJAdviceMethod = aspectJAdviceMethod;
		//aspectj的通知工厂
		this.aspectJAdvisorFactory = aspectJAdvisorFactory;
		//aspect的实例工厂
		this.aspectInstanceFactory = aspectInstanceFactory;
		//切面的顺序
		this.declarationOrder = declarationOrder;
		//切面的名称
		this.aspectName = aspectName;


		if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
			Pointcut preInstantiationPointcut = Pointcuts.union(
					aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
			this.pointcut = new PerTargetInstantiationModelPointcut(
					this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
			this.lazy = true;
		}
		else {
			this.pointcut = this.declaredPointcut;
			this.lazy = false;
			//把切面中的通知构造为一个一个的advice通知对象
			this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
		}
}

对于advice通知对象,每个方法都会对应一个特点给的通知类,看一下创建过程:

public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
			MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
		//获取切面对象
		Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		validate(candidateAspectClass);
		//获取方法上的通知注解
		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 AtPointcut:
				if (logger.isDebugEnabled()) {
					logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
				}
				return null;
			case AtAround://环绕通知
				springAdvice = new AspectJAroundAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtBefore://前置通知
				springAdvice = new AspectJMethodBeforeAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtAfter://后置通知
				springAdvice = new AspectJAfterAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtAfterReturning://返回通知
				springAdvice = new AspectJAfterReturningAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
				if (StringUtils.hasText(afterReturningAnnotation.returning())) {
					springAdvice.setReturningName(afterReturningAnnotation.returning());
				}
				break;
			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);
		}

		//配置一下advice
		springAdvice.setAspectName(aspectName);
		springAdvice.setDeclarationOrder(declarationOrder);
		String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
		if (argNames != null) {
			springAdvice.setArgumentNamesFromStringArray(argNames);
		}
		springAdvice.calculateArgumentBindings();

		return springAdvice;
}

        这5种通知后面会转换成MethodInterceptor方法拦截器,aop调用时执行invoke方法进行拦截,其中AspectJAroundAdvice,AspectJAfterAdvice,AspectJAfterThrowingAdvice直接实现了MethodInterceptor,而AspectJMethodBeforeAdvice,AspectJAfterReturningAdvice由于不是MethodInterceptor的实现类需要通过适配器转换成MethodInterceptor,后续在aop创建代理的时候详细介绍。

总结

        当spirng创建第一个bean的时候,所有Advicor就会在bean实例化前置调用处解析,也就是只会解析一次,然后缓存起来,以后就不会进去了。解析切面相当于aop的准备工作,后续将会详细分析aop创建代理和方法拦截的过程。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值