白话Spring源码(十):Spring AOP源码分析-筛选合适的通知器

上一篇博客介绍了AOP的相关概念:白话Spring源码(九):Spring AOP原理和相关概念。其实AOP的原理比较简单,但是里面的概念和抽象比较多,入口也藏得比较深。好了,我带大家从入口开始进去源码吧!

要找到入口我们就必须搞清楚 Spring AOP 是在何处向目标 bean 中织入通知(Advice)的。也说过 Spring 是如何将 AOP 和 IOC 模块整合到一起的,即通过拓展点 BeanPostProcessor 接口。Spring AOP 抽象代理创建器实现了 BeanPostProcessor 接口,并在 bean 初始化后置处理过程中向 bean 中织入通知。下面我们就来看看相关源码,如下:

public abstract class AbstractAutoProxyCreator extends ProxyConfig
		implements BeanPostProcessor, BeanFactoryAware, Ordered {



	public Object postProcessBeforeInitialization(Object bean, String name) {
		return bean;
	}

	/**
	 * Create a proxy with the configured interceptors if the bean is
	 * identified as one to proxy by the subclass.
	 * @see #getInterceptorsAndAdvisorsForBean
	 */
	public Object postProcessAfterInitialization(Object bean, String name) throws BeansException {
		// Check for special cases. We don't want to try to autoproxy a part of the autoproxying
		// infrastructure, lest we get a stack overflow.
		if (isInfrastructureClass(bean, name) || shouldSkip(bean, name)) {
			logger.debug("Did not attempt to autoproxy infrastructure class '" + bean.getClass() + "'");
			return bean;
		}
		
		TargetSource targetSource = getTargetSource(bean, name);
		
		Object[] specificInterceptors = getInterceptorsAndAdvisorsForBean(bean, name);
		
		// proxy if we have advice or if a TargetSourceCreator wants to do some
		// fancy stuff such as pooling
		if (specificInterceptors != DO_NOT_PROXY || !(targetSource instanceof SingletonTargetSource)) {

			// handle prototypes correctly
			Advisor[] commonInterceptors = resolveInterceptorNames();

			List allInterceptors = new ArrayList();
			if (specificInterceptors != null) {
				allInterceptors.addAll(Arrays.asList(specificInterceptors));
				if (commonInterceptors != null) {
					if (this.applyCommonInterceptorsFirst) {
						allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
					}
					else {
						allInterceptors.addAll(Arrays.asList(commonInterceptors));
					}
				}
			}
			if (logger.isInfoEnabled()) {
				int nrOfCommonInterceptors = commonInterceptors != null ? commonInterceptors.length : 0;
				int nrOfSpecificInterceptors = specificInterceptors != null ? specificInterceptors.length : 0;
				logger.info("Creating implicit proxy for bean '" +  name + "' with " + nrOfCommonInterceptors +
										" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
			}
			ProxyFactory proxyFactory = new ProxyFactory();

			// copy our properties (proxyTargetClass) inherited from ProxyConfig
			proxyFactory.copyFrom(this);
			
			if (!getProxyTargetClass()) {
				// Must allow for introductions; can't just set interfaces to
				// the target's interfaces only.
				Class[] targetsInterfaces = AopUtils.getAllInterfaces(bean);
				for (int i = 0; i < targetsInterfaces.length; i++) {
					proxyFactory.addInterface(targetsInterfaces[i]);
				}
			}
			
			for (Iterator it = allInterceptors.iterator(); it.hasNext();) {
				Advisor advisor = GlobalAdvisorAdapterRegistry.getInstance().wrap(it.next());
				proxyFactory.addAdvisor(advisor);
			}
			proxyFactory.setTargetSource(getTargetSource(bean, name));
			
			return proxyFactory.getProxy();
		}
		else {
			return bean;
		}
	}



}

这个类实现了BeanPostProcessor的接口,这个会在bean初始化前后调用:

createBean方法的部分代码:

bean = applyBeanPostProcessorsBeforeInitialization(bean, beanName);//执行初始化前执行的自定义方法
invokeInitMethods(bean, beanName, mergedBeanDefinition);//执行初始化方法
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);//执行初始化后执行的自定义方法

以上就是 Spring AOP 创建代理对象的入口方法分析,过程比较简单,这里简单总结一下:

  • 若 bean 是 AOP 基础设施类型,则直接返回
  • 为 bean 查找合适的通知器
  • 如果通知器数组不为空,则为 bean 生成代理对象,并返回该对象
  • 若数组为空,则返回原始 bean

这里有两个关键点

1.为bean查找合适的通知器。

2.为bean生成代理对象。

下面我们就围绕着两点展开,这篇博客主要分析怎么为bean找到合适的通知器,下面就是对应的调用:

Object[] specificInterceptors = getInterceptorsAndAdvisorsForBean(bean, name);

getInterceptorsAndAdvisorsForBean:这里没有具体的实现,只是调用findEligibleAdvisors,然后排序

	protected Object[] getInterceptorsAndAdvisorsForBean(Object bean, String name) {
		List advices = findEligibleAdvisors(bean.getClass());
		if (advices.isEmpty()) {
			return DO_NOT_PROXY;
		}
		advices = sortAdvisors(advices);
		return advices.toArray();
	}

findEligibleAdvisors:先找到所有的Advice,然后再筛选

扫描二维码关注公众号,回复: 5805731 查看本文章
	protected List findEligibleAdvisors(Class clazz) {
		List candidateAdvice = findCandidateAdvisors();
		List eligibleAdvice = new LinkedList();
		for (int i = 0; i < candidateAdvice.size(); i++) {
			// Sun, give me generics, please!
			Advisor candidate = (Advisor) candidateAdvice.get(i);
			if (AopUtils.canApply(candidate, clazz, null)) {
				eligibleAdvice.add(candidate);
				logger.info("Candidate Advice [" + candidate + "] accepted for class [" + clazz.getName() + "]");
			}
			else {
				logger.info("Candidate Advice [" + candidate + "] rejected for class [" + clazz.getName() + "]");
			}
		}
		return eligibleAdvice;
	}

findCandidateAdvisors:用beanFactory找到所有实现Advisor接口的类

	protected List findCandidateAdvisors() {
		if (!(getBeanFactory() instanceof ListableBeanFactory)) {
			throw new IllegalStateException("Cannot use DefaultAdvisorAutoProxyCreator without a ListableBeanFactory");
		}
		ListableBeanFactory owningFactory = (ListableBeanFactory) getBeanFactory();
		
		String[] adviceNames = BeanFactoryUtils.beanNamesIncludingAncestors(owningFactory, Advisor.class);
		List candidateAdvisors = new LinkedList();
		for (int i = 0; i < adviceNames.length; i++) {
			String name = adviceNames[i];
			if (!this.usePrefix || name.startsWith(this.advisorBeanNamePrefix)) {
				Advisor advisor = (Advisor) owningFactory.getBean(name);
				candidateAdvisors.add(advisor);
			}
		}
		return candidateAdvisors;
	}

那怎么筛选适合的Advice:

AopUtils.canApply(candidate, clazz, null)

canApply:判断是IntroductionAdvisor还是PointcutAdvisor

IntroductionAdvisor与PointcutAdvisor最本质上的区别就是,IntroductionAdvisor只能应用于类级别的拦截,只能使用Introduction型的Advice,而不能像PointcutAdvisor那样,可以使用任何类型的Pointcut,以及差不多任何类型的Advice。也就是说,IntroductionAdvisor纯粹就是为Introduction而生的。

	public static boolean canApply(Advisor advisor, Class targetClass, Class[] proxyInterfaces) {
		if (advisor instanceof IntroductionAdvisor) {
			return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
		}
		else if (advisor instanceof PointcutAdvisor) {
			PointcutAdvisor pca = (PointcutAdvisor) advisor;
			return canApply(pca.getPointcut(), targetClass, proxyInterfaces);
		}
		else {
			// It doesn't have a pointcut so we assume it applies
			return true;
		}
	}

PointcutAdvisor的canApply:

	public static boolean canApply(Pointcut pc, Class targetClass, Class[] proxyInterfaces) {
		if (!pc.getClassFilter().matches(targetClass)) {
			return false;
		}
		
		// It may apply to the class
		// Check whether it can apply on any method
		// Checks public methods, including inherited methods
		Method[] methods = targetClass.getMethods();
		for (int i = 0; i < methods.length; i++) {
			Method m = methods[i];
			// If we're looking only at interfaces and this method
			// isn't on any of them, skip it
			if (proxyInterfaces != null && !methodIsOnOneOfTheseInterfaces(m, proxyInterfaces)) {
				continue;
			}
			if (pc.getMethodMatcher().matches(m, targetClass))
				return true;
		}
		return false;
	}

猜你喜欢

转载自blog.csdn.net/haoxin963/article/details/89074883
今日推荐