spring源码分析之aop

概述

简单来说,代理对象的创建是在bean的创建生命周期中的postProcessAfterInitialization方法调用时完成的,而干这件事的BeanPostProcessor 就是 AnnotationAwareAspectJAutoProxyCreator
关于bean的创建生命周期不再过多讲解,感兴趣可以看看我之前的文章
如下是该类的继承结构
在这里插入图片描述
可以看到这个SmartInstantiationAwareBeanPostProcessor在源码中是非常常见的,它继承了BeanPostProccessor,但是其实整个aop的核心逻辑是写在AbstractAutoProxyCreator中的

AnnotationAwareAspectJAutoProxyCreator的注册和创建

我们普通的bean的后置处理需要先有这些后置处理器,那么我们先看看这个后置处理器的注册和创建过程。这里我们需要搞清楚,注册和创建是不同的,注册的过程可以简单理解为把这个类的信息封装成BeanDefinition放入缓存,创建过程是用BeanDefinition作为原料,经过一些列的处理生成一个对象。

注册

注册有两种方式,一种是通过xml 引入命名空间 声明

	<aop:aspectj-autoproxy />

或者通过Javaconfig

@Configuration
@ComponentScan
@EnableAspectJAutoProxy
public class Config {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(Config.class);
        DoHi doHi = (DoHi)ac.getBean("doHi");
        doHi.kill();
    }
}

对于前一种方式暂时不作详细解释,我们现在来研究下通过JavaConfig的方式完成的注册
这时候需要先看看EnableAspectJAutoProxy这个注解

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

	// true则强制使用AspectJ来实现代理
	boolean proxyTargetClass() default false;
	
	// true则可以暴露代理对象,可以用来解决同一个类中调用代理失效的问题
	boolean exposeProxy() default false;
}

我们应该注意到这个注解有个@Import,我们接着看些这个导入的配置类

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	/**
	 * Register, escalate, and configure the AspectJ auto proxy creator based on the value
	 * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
	 * {@code @Configuration} class.
	 */
	@Override
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

        //这里完成了AnnotationAwareAspectJAutoProxyCreator的注册
		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

        //这里完成了上述两个属性的设置
		AnnotationAttributes enableAspectJAutoProxy =
				AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
		if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
			AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
		}
		if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
			AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
		}
	}

}

总体来说,它通过Import导入一个实现了ImportBeanDefinitionRegistrar 接口的对象来完成了注册

创建

创建过程需要进入著名的Refresh方法

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);

				// 我们的处理器正是在这个地方注册
				registerBeanPostProcessors(beanFactory);

				...
			}
			...
			
		}
	}

进入方法registerBeanPostProcessors

public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

		// Register BeanPostProcessorChecker that logs an info message when
		// a bean is created during BeanPostProcessor instantiation, i.e. when
		// a bean is not eligible for getting processed by all BeanPostProcessors.
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

		// Separate between BeanPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.
		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
		List<BeanPostProcessor> internalPostProcessors = new ArrayList<BeanPostProcessor>();
		List<String> orderedPostProcessorNames = new ArrayList<String>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<String>();
		for (String ppName : postProcessorNames) {
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
				priorityOrderedPostProcessors.add(pp);
				if (pp instanceof MergedBeanDefinitionPostProcessor) {
					internalPostProcessors.add(pp);
				}
			}
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// First, register the BeanPostProcessors that implement PriorityOrdered.
		sortPostProcessors(beanFactory, priorityOrderedPostProcessors);
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		// Next, register the BeanPostProcessors that implement Ordered.
		List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>();
		for (String ppName : orderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			orderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		sortPostProcessors(beanFactory, orderedPostProcessors);
		registerBeanPostProcessors(beanFactory, orderedPostProcessors);

		// Now, register all regular BeanPostProcessors.
		List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<BeanPostProcessor>();
		for (String ppName : nonOrderedPostProcessorNames) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			nonOrderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

		// Finally, re-register all internal BeanPostProcessors.
		sortPostProcessors(beanFactory, internalPostProcessors);
		registerBeanPostProcessors(beanFactory, internalPostProcessors);

		// Re-register post-processor for detecting inner beans as ApplicationListeners,
		// moving it to the end of the processor chain (for picking up proxies etc).
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}

上面的逻辑可以简单理解为,通过Class找到合适的beanName,然后根据是否实现了优先级或排序的接口被放入三组,然后排序,这过程中完成了对bean的创建,其过程与普通bean的创建一样,也是调用getBean方法。然后这些处理器就作为beanfactory的属性被存储下来,方便对普通bean的创建的处理。

后置处理器处理过程

如上面所言,我们的后置处理器已经创建完成,那我们开始普通bean的创建,跳过创建生命周期的其它步骤,直接进入后置处理器的方法调用

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
		...
		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}

		if (mbd == null || !mbd.isSynthetic()) {
		    //代理创建正是在这里进行的
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
		return wrappedBean;
	}

现在我们进入AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization

	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (!this.earlyProxyReferences.contains(cacheKey)) {
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

spring的常见操作,缓存,spring中有很多缓存,为了避免重复进行一些很复杂的过程,这里也是如此,它会先检查缓存中是否已经存在,然后才进行真正的处理。我们接着跟入这个wrapIfNecessary方法

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {

        //通过检查缓存来判断是否有必要再次wrap
        //做过包装的目标类名缓存
		if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
			return bean;
		}
		//已经做过包装的缓存
		if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
			return bean;
		}
		//假如是一些基础类是不需要包装的如Aspact等
		if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return bean;
		}

		// Create proxy if we have advice.
		//找到这个bean合适的通知
		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;
	}

spring给方法方法取名字真的很秀,比如这个wrapIfNecessary,为什么是有必要才包装勒,因为它已经为已经做过包装的bean做了缓存,假如可以在缓存中找到就不用再次包装。通过上面的代码我们能知道,创建代理类,大致可以分为两大步
1.找到合适的通知
2.完成代理类的创建
接下来我们开始分别介绍

找到合适的通知

我们进入getAdvicesAndAdvisorsForBean方法

	@Override
	protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {
		List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
		if (advisors.isEmpty()) {
			return DO_NOT_PROXY;
		}
		return advisors.toArray();
	}
	//跟入findEligibleAdvisors
	protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
	    //找到所有合适的advisor
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		//找到能增强目标类的advisor,spring方法命名真的值得借鉴,不在乎长短,在于能否准确表达干了什么,能自解释
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}	

如上方法,返回的是Advisor的数组,简单来说,这个advisor持有advise即我们定义切点时定义的通知,和一个过滤条件即我们定义切面时的切点规则
我们继续跟入

	protected List<Advisor> findCandidateAdvisors() {
		// Add all the Spring advisors found according to superclass rules.
		//查找通过xml注册的通知
		List<Advisor> advisors = super.findCandidateAdvisors();
		// Build Advisors for all AspectJ aspects in the bean factory.
		//构建通过注解注册的通知
		advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
		return advisors;
	}

这里的buildAspectJAdvisors,有兴趣可以跟进去看看,这里面也是有缓存,切面和把通知根据切面分组缓存了起来,当然第一次执行时会找到说有的bean,然后找到这些bean里面被@Aspect修饰的,然后创建Advisor,加入到缓存。至于findAdvisorsThatCanApply方法大致逻辑是反射获取目标类的方法,然后根据Advisor中持有的Pointcut的匹配方法来对目标类方法进行匹配,能通过匹配则添加这个Advisor

代理类的创建

在经过一些对proxyFactroy的配置后我们进入和真的的代理类创建


//DefaultAopProxyFactory
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
		if (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.");
			}
			if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
				return new JdkDynamicAopProxy(config);
			}
			return new ObjenesisCglibAopProxy(config);
		}
		else {
			return new JdkDynamicAopProxy(config);
		}
	}

调用栈如下
在这里插入图片描述
上面的逻辑应该比较清晰了,假如isProxyTargetClass或者目标类没有接口就用cglib的方式进行创建代理
否者用jdk的动态代理

代理方法的执行

致谢

感谢 简书 作者王侦的文章 为我搞清楚spring aop的原理提供的思路
博客 地址
我大致顺着他的思路重写一遍


版权声明:本文为qq_34637782原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。