Spring源码之创建AOP代理

我们在上节中提到了AnnotationAwareAspectJAutoProxyCreator的类,其实这个类实现了BeanPostProcessor接口,所以Spring在加载Bean时,会先调用postProcessAfterInitialization方法。因此,笔者也从这里开始分析。下面先看一张AnnotationAwareAspectJAutoProxyCreator类的层次结构图。(相关资源可到这里下载:http://pan.baidu.com/s/1sjSo9a9)

Spring源码之创建AOP代理_第1张图片

在开始了解Spring的AOP代理的源码,我们按照惯例先来分析它的时序图。

Spring源码之创建AOP代理_第2张图片

1. AbstractAutoProxyCreator

在这个类中,我们主要是看postProcessAfterInitialization中的代码。在这个方法里,主要是根据给定的bean的class和name构建出个key,格式:beanClassName_beanName,同时,如果这个bean适合被代理,那么就要封装这个bean。当然,如果这个bean需要增强方法,那就要调用相应的方法来增强该类。

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if (bean != null) {
			//根据给定的bean的class和name构建出个key,格式:beanClassName_beanName
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (!this.earlyProxyReferences.contains(cacheKey)) {
				//如果给它适合被代理,则需要封装指定bean
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
		//如果已经处理过
		if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		//无需增强
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		//给定的bean是否代表一个基础设施类,基础设施类不应代理,或者配置了指定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(
					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
			this.proxyTypes.put(cacheKey, proxy.getClass());
			return proxy;
		}

		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

2. AbstractAdvisorAutoProxyCreator

前面我们已经说了,对于有些bean是需要增强的,那么我们的程序就要调用相应的方法来处理增强。其实调用的就是上面提到的getAdvicesAndAdvisorsForBean的说方法。这个方法就是在AbstractAdvisorAutoProxyCreator的类,在方法中,首先要做的事情就是获取增强器,然后寻找匹配的增强器,这两个笔者将在下面会讲到。我们先来看getAdvicesAndAdvisorsForBean的方法,之后调用findEligibleAdvisors(),读者可以自己领悟。

protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, TargetSource targetSource) {
		List advisors = findEligibleAdvisors(beanClass, beanName);
		if (advisors.isEmpty()) {
			return DO_NOT_PROXY;
		}
		return advisors.toArray();
	}
protected List findEligibleAdvisors(Class beanClass, String beanName) {
		List candidateAdvisors = findCandidateAdvisors();
		List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}

3. AnnotationAwareAspectJAutoProxyCreator

我们继续跟踪findCandidateAdvisors()的方法,进入AnnotationAwareAspectJAutoProxyCreator的类当中。在这个方法中, 我们会发现在,不管是用注解还是用配置文件的AOP声明,其实都离不开对XML文件的读取。

protected List findCandidateAdvisors() {
		// Add all the Spring advisors found according to superclass rules.
		List advisors = super.findCandidateAdvisors();
		// Build Advisors for all AspectJ aspects in the bean factory.
		advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
		return advisors;
	}

4. BeanFactoryAspectJAdvisorsBuilder

 在上面的类中,在findCandidateAdvisor()中我们最关心的是buildAspctJAdvisors()的方法。这个方法才是提取AspectJ注解的类的核心方法。Spring的源码如下。读者可以根据笔者的注解去解读。

public List buildAspectJAdvisors() {
		List aspectNames = null;

		synchronized (this) {
			aspectNames = this.aspectBeanNames;
			if (aspectNames == null) {
				List advisors = new LinkedList();
				aspectNames = new LinkedList();
				//获取所有的beanName
				String[] beanNames =
						BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);
				//循环所有的beanName找出对应的增强方法
				for (String beanName : beanNames) {
					//不合法的bean则略过,由子类定义规则,默认返回true
					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
					//获取对应的bean的类型
					Class beanType = this.beanFactory.getType(beanName);
					if (beanType == null) {
						continue;
					}
					//如果存在Aspect注解
					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);
						//解析标记AspectJ注解中的增强方法
							List 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 advisors = new LinkedList();
		for (String aspectName : aspectNames) {
			List 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;
	}

5. ReflectiveAspectJAdvisorFactory

  我们不能忽略的就是上面的方法中的this.advisorFactory.getAdvisors(factory)的方法调用了。这个方法是在ReflectiveAspectJAdvisorFactory的类中。在这个方法中也就是最为重要,也是为复杂的的增强器获取了。我们可以来品读一下getAdvisors()的方法。

public List getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
		//获取标记为AspectJ的类
		Class aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		//获取标记为AspetJr的类
		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 advisors = new LinkedList();
		for (Method method : getAdvisorMethods(aspectClass)) {
			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.
		//获取DeclareParents注解
		for (Field field : aspectClass.getDeclaredFields()) {
			Advisor advisor = getDeclareParentsAdvisor(field);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		return advisors;
	}

在上面的函数中,对增强器的获取,最后是对DeclareParants注解的获取。增强器的获取逻辑是通过getAdvisor方法实现的,实现步骤包括对切入点的注解的获取以及根据注解信息生成增强。

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;
		}
        //根据切点信息生成增强器
		return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
				this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
	}

对于切点信息的获取,可能读者有占迷糊,其实就是指定注解表达式的获取,如@Before(“test()”)。这里主要是调用getPointcut()的方法。

private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class candidateAspectClass) {
		//获取方法上的注解
		AspectJAnnotation aspectJAnnotation =
				AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
		if (aspectJAnnotation == null) {
			return null;
		}
        //使用AspetJExpressionPointcut实例封装获取的信息
		AspectJExpressionPointcut ajexp =
				new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class[0]);
		//提取得到的注解中的表达式。
		ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
		return ajexp;
	}

6. AbstractAspectJAdvisorFactory

在上面的类方法getPointcut()中,我们找到的findAspectJAnnotationOnMethod的方法,这个方法是存在AbstractAspectJAdvisorFactory类中的,所以我们继续跟踪,可以看到这个方法就是对所有敏感类的注解。看到这个地方的代码,相信读者可以“柳暗花明”了。

@SuppressWarnings("unchecked")
	protected static AspectJAnnotation findAspectJAnnotationOnMethod(Method method) {
		//设置敏感的注解类
		Class[] classesToLookFor = new Class[] {
				Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
		for (Class c : classesToLookFor) {
			AspectJAnnotation foundAnnotation = findAnnotation(method, (Class) c);
			if (foundAnnotation != null) {
				return foundAnnotation;
			}
		}
		return null;
	}

这里还有一个方法另忽略了,那就是findAnnotation,这里就是指定方法上的注解并使用AspectJAnnotation封装。

private static  AspectJAnnotation findAnnotation(Method method, Class toLookFor) {
		A result = AnnotationUtils.findAnnotation(method, toLookFor);
		if (result != null) {
			return new AspectJAnnotation(result);
		}
		else {
			return null;
		}
	}

7. InstantiationModelAwarePointcutAdvisorImpl

相应读者并没有忘记前4.5中的getAdvisor()方法中的另外实例化的类InstantiationModelAwarePointcutAdvisorImpl,这个类的作用就是根据切点信息生成增强。

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;
			this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
		}
	}

在方法体的最后,我们看到了instantiateAdvice()的方法。这个方法体就是对不同的增强体做不同的处理。

 private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {
		return this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pcut,
				this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
	}

8. ReflectiveAspectJAdvisorFactory

其实上面的对不同有增强做不同的处理,主要的还是getAdvice的方法中运行。

 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 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;

		switch (aspectJAnnotation.getAnnotationType()) {
			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;
			case AtAround:
				springAdvice = new AspectJAroundAdvice(
						candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
				break;
			case AtPointcut:
				if (logger.isDebugEnabled()) {
					logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
				}
				return null;
			default:
				throw new UnsupportedOperationException(
						"Unsupported advice type on method: " + candidateAdviceMethod);
		}

		// Now to configure the advice...
		springAdvice.setAspectName(aspectName);
		springAdvice.setDeclarationOrder(declarationOrder);
		String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
		if (argNames != null) {
			springAdvice.setArgumentNamesFromStringArray(argNames);
		}
		springAdvice.calculateArgumentBindings();
		return springAdvice;
	}
















你可能感兴趣的:(Spring源码)