SpringAop源码分析(基于注解)一

在以前的文章中,我学习了Spring Ioc的源码,对Spring原理有了初步了解,因此准备趁热打铁,把SpringAop的源码也看一遍,接下来的文章都会围绕Aopjava

1、AOP原理

关于Aop的原理,简单来说无非就是用代理模式为目标对象生产代理对象,对原有的方法进行加强。看上去挺简单,但在Spring中,有许多细节是要注意到的。好比:spring

  • AOP是怎么触发的?
  • 代理对象是何时生成的?
  • 怎么发现目标对象?
  • 怎么判断目标对象的哪些方法须要加强?
  • 怎么实现前置通知,后置通知,环绕通知?
  • 一个方法有多个切面代理怎么处理?

咱们能够带着这些疑问来看源码,有助于咱们的理解。缓存

2、AOP术语

AOP的术语有不少而且很重要,看源码以前仍是要对术语有所了解,这里就不一一介绍了,感兴趣的同窗能够移步SpringAOP术语并发

3、demo

先来一个注解方式实现AOP的demo,而后咱们后面根据这个demo来分析源码。app

@Aspect
@Component
@EnableAspectJAutoProxy
public class LogAspect {

	@Before("execution(* com.mydemo.work.StudentController.getName(..))")
	public void doBefore() {
		System.out.println("========before");
	}

	@After("execution(* com.mydemo.work.StudentController.getName(..))")
	public void doAfter() {
		System.out.println("========after");
	}
}
复制代码

这是一个简单的日志AOP,对StudentController类的getName(..)方法进行加强,在这个方法执行先后会打印不一样的信息。ide

4、准备

能够看到,在最开始的demo工程中,为了开启AOP功能,我使用了一个@EnableAspectJAutoProxy注解,代码以下:post

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

	/** * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed * to standard Java interface-based proxies. The default is {@code false}. */
	//代理的实现方式,true为CGLIB,false为JDK,默认false
	boolean proxyTargetClass() default false;

	/** * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal} * for retrieval via the {@link org.springframework.aop.framework.AopContext} class. * Off by default, i.e. no guarantees that {@code AopContext} access will work. * @since 4.3.1 */
	//代理的暴露方式,解决内部调用不能使用代理的场景,默认为false
	boolean exposeProxy() default false;

}
复制代码

能够看到这个注解有2个属性proxyTargetClassexposeProxy。除此以外还使用@Import注解引入了一个配置类AspectJAutoProxyRegistrar
咱们来看下这个关键的类:学习

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) {

<1>     //注册一个专门管理AOP的Bean到IOC容器中
	AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

	//获取@EnableAspectJAutoProxy注解
<2>	AnnotationAttributes enableAspectJAutoProxy =
			AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
	if (enableAspectJAutoProxy != null) {
		//处理该注解的2个属性
		if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
			AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
		}
		if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
			AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
		}
	}
	}

}
复制代码

这段代码看起来不难,咱们确定要有一个处理AOP逻辑的代码类,那在Spring中就要把这个类交给Spring容器来管理,因此有了第<1>步。咱们来看下详细逻辑, 直接追踪到最后调用的地方:ui

//AopConfigUtils.java

/** * The bean name of the internally managed auto-proxy creator. */
public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
			"org.springframework.aop.config.internalAutoProxyCreator";

@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {

	Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
	
	//检查容器中是否已经注册过该Bean
	if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
		//注册过,判断Bean的ClassName是否为AnnotationAwareAspectJAutoProxyCreator
		BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
		if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
			int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
			int requiredPriority = findPriorityForClass(cls);
			if (currentPriority < requiredPriority) {
				apcDefinition.setBeanClassName(cls.getName());
			}
		}
		return null;
	}
	//没有注册过,则注册
	//cls = AnnotationAwareAspectJAutoProxyCreator.class
	RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
	beanDefinition.setSource(source);
	beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
	beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
	registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
	return beanDefinition;
}
复制代码

这段代码就是把AnnotationAwareAspectJAutoProxyCreator这个类注册到SpringIOC容器中,实际上AnnotationAwareAspectJAutoProxyCreator这个类的BeanName就是org.springframework.aop.config.internalAutoProxyCreatorthis

5、注册BeanPostProcessor

如今咱们已经有了处理AOP的类AnnotationAwareAspectJAutoProxyCreator, 先来看下这个类的继承图:

能够看出,这个类间接实现了 BeanPostProcessor接口,这个接口你们应该很熟悉,是Spring的一个后置处理器接口。

public interface BeanPostProcessor {

	//在Bean的初始化前回调
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	
	//在Bean的初始化以后回调
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}
复制代码

BeanPostProcessor 能够理解为是 Spring 的一个工厂钩子(其实 Spring 提供一系列的钩子,如 Aware 、InitializingBean、DisposableBean),它是 Spring 提供的对象实例化阶段强有力的扩展点,容许 Spring 在实例化 bean 的先后对其进行修改,比较常见的使用场景是处理标记接口实现类或者为当前对象提供代理实现(例如 AOP)。
通常普通的 BeanFactory 是不支持自动注册 BeanPostProcessor 的,须要咱们手动调用addBeanostProcessor()方法进行注册。以下:

beanFactory.addBeanPostProcessor(BeanPostProcessor beanPostProcessor)
复制代码

注册后的 BeanPostProcessor 适用于全部该 BeanFactory 建立的 bean,可是 ApplicationContext 能够在其 bean 定义中自动检测全部的 BeanPostProcessor 并自动完成注册,同时将他们应用到随后建立的任何 Bean 中。

在这里咱们的容器是ApplicationContext,因此会自动检测全部BeanPostProcessor并完成注册。接下来咱们就看下自动注册的逻辑。

咱们都知道在 ApplicationContext 中有一个重要的方法refresh(),会在容器启动时执行,代码以下:

//AbstractApplicationContext.java

public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
	// Prepare this context for refreshing.
	//一、调用spring容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识
	prepareRefresh();

	// Tell the subclass to refresh the internal bean factory.
	//二、建立并初始化 BeanFactory ----> 获取IOC容器
	ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

	// Prepare the bean factory for use in this context.
	//三、填充BeanFactory功能。 配置容器特性,例如类加载器、事件处理器等
	prepareBeanFactory(beanFactory);

	try {
		// Allows post-processing of the bean factory in context subclasses.
		//四、提供子类覆盖的额外处理,即子类处理自定义的BeanFactoryPostProcess
		postProcessBeanFactory(beanFactory);

		// Invoke factory processors registered as beans in the context.
		//五、激活各类BeanFactory处理器。 调用全部注册的BeanFactoryPostProcessor的Bean
		invokeBeanFactoryPostProcessors(beanFactory);

		// Register bean processors that intercept bean creation.
		//六、注册BeanPostProcessor后置处理器.
		//AutowiredAnnotationBeanPostProcessor(处理被@Autowired注解修饰的bean并注入)
		//RequiredAnnotationBeanPostProcessor(处理被@Required注解修饰的方法)
		//CommonAnnotationBeanPostProcessor(处理@PreDestroy、@PostConstruct、@Resource等多个注解的做用)等
		//AutoProxyCreator(aop代理 @Aspect)
		registerBeanPostProcessors(beanFactory);

		// Initialize message source for this context.
		//七、初始化信息源,和国际化相关.
		initMessageSource();

		// Initialize event multicaster for this context.
		//八、初始化容器事件传播器.
		initApplicationEventMulticaster();

		// Initialize other special beans in specific context subclasses.
		//九、调用子类的某些特殊Bean初始化方法
		onRefresh();

		// Check for listener beans and register them.
		//十、为事件传播器注册事件监听器.
		registerListeners();

		// Instantiate all remaining (non-lazy-init) singletons.
		//十一、初始化剩下的单例Bean(非延迟加载的)
		finishBeanFactoryInitialization(beanFactory);

		// Last step: publish corresponding event.
		//十二、初始化容器的生命周期事件处理器,并发布容器的生命周期事件
		finishRefresh();
	}

	catch (BeansException ex) {
		if (logger.isWarnEnabled()) {
			logger.warn("Exception encountered during context initialization - " +
					"cancelling refresh attempt: " + ex);
		}

		// Destroy already created singletons to avoid dangling resources.
		//1三、销毁已建立的Bean
		destroyBeans();

		// Reset 'active' flag.
		//1四、取消refresh操做,重置容器的同步标识。
		cancelRefresh(ex);

		// Propagate exception to caller.
		throw ex;
	}

	finally {
		// Reset common introspection caches in Spring's core, since we
		// might not ever need metadata for singleton beans anymore...
		//1五、重设公共缓存
		resetCommonCaches();
	}
	}
	}
复制代码

代码很长,其余的暂时先无论,直接看第6步registerBeanPostProcessors(beanFactory),这行代码是须要咱们关注的,它就是对 BeanPostProcessors 进行自动注册的方法。

//PostProcessorRegistrationDelegate.java

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

<1>	//获取容器中全部的BeanPostProcessor名称
	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;
	//注册BeanPostProcessorChecker到容器中
	beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

	// Separate between BeanPostProcessors that implement PriorityOrdered,
	// Ordered, and the rest.
	List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
	List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
	List<String> orderedPostProcessorNames = new ArrayList<>();
	List<String> nonOrderedPostProcessorNames = new ArrayList<>();
<2>	//遍历全部BeanPostProcessor名称
	for (String ppName : postProcessorNames) {
		//判断当前BeanPostProcessor是否实现PriorityOrdered接口
		if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			priorityOrderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		//判断当前BeanPostProcessor是否实现Ordered接口
		else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
			orderedPostProcessorNames.add(ppName);
		}
		else {
			nonOrderedPostProcessorNames.add(ppName);
		}
	}

	// First, register the BeanPostProcessors that implement PriorityOrdered.
<3>	//对实现PriorityOrdered接口的BeanPostProcessors进行排序
	sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
	//注册
	registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

	// Next, register the BeanPostProcessors that implement Ordered.
	List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
	for (String ppName : orderedPostProcessorNames) {
		BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
		orderedPostProcessors.add(pp);
		if (pp instanceof MergedBeanDefinitionPostProcessor) {
			internalPostProcessors.add(pp);
		}
	}
<4>	//对实现Ordered接口的BeanPostProcessors进行排序
	sortPostProcessors(orderedPostProcessors, beanFactory);
	//注册
	registerBeanPostProcessors(beanFactory, orderedPostProcessors);

	// Now, register all regular BeanPostProcessors.
	List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
	for (String ppName : nonOrderedPostProcessorNames) {
		BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
		nonOrderedPostProcessors.add(pp);
		if (pp instanceof MergedBeanDefinitionPostProcessor) {
			internalPostProcessors.add(pp);
		}
	}
<5>	//注册没有实现排序接口的BeanPostProcessors
	registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

	// Finally, re-register all internal BeanPostProcessors.
<6>	//排序并注册内部BeanPostProcessors
	sortPostProcessors(internalPostProcessors, beanFactory);
	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));
	}
复制代码
//PostProcessorRegistrationDelegate.java

//具体注册方法
private static void registerBeanPostProcessors( ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {

	for (BeanPostProcessor postProcessor : postProcessors) {
	        //核心
		beanFactory.addBeanPostProcessor(postProcessor);
	}
}
复制代码

这段代码看起来很长,但其实很简单。

  • <1>处,先从容器中获取全部BeanPostProcessors类型的BeanName。
    在上一步咱们已经经过@EnableAspectJAutoProxy注解把处理AOP的Bean->internalAutoProxyCreator给注册到容器中了,因此这里能够拿到。

  • <2>处,遍历全部BeanName,进行分类,分为4类。

    • 实现PriorityOrdered接口的BeanPostProcessors
    • 实现Ordered接口的BeanPostProcessors
    • 没有实现排序接口的BeanPostProcessors
    • Spring内部的BeanPostProcessors

    咱们经过@EnableAspectJAutoProxy注解注册的internalAutoProxyCreator是属于第2类。

  • <3>处,排序并注册实现PriorityOrdered接口的BeanPostProcessors

  • <4>处,排序并注册实现Ordered接口的BeanPostProcessors

  • <5>处,注册没有实现排序接口的BeanPostProcessors

  • <6>处,排序并注册Spring内部的BeanPostProcessors

至此,咱们已经把全部的BeanPostProcessors注册到了容器ApplicationContext中,包括咱们专门处理AOP的BeanPostProcessors,接下来就可使用了。

总结

总结一下到目前位置的步骤:

  • 经过@EnableAspectJAutoProxy注解把专门处理AOP的Bean注册到IOC容器中
  • 经过ApplicationContext.refresh()方法把专门处理AOP的BeanPostProcessors注册到IOC容器中。

那这两步之间有什么关联呢?

  • 首先,咱们要把专门处理AOP的Bean注册到IOC容器中,交给spring来管理。-->@EnableAspectJAutoProxy

  • 而后,经过IOC容器的getBean()方法生成实例AnnotationAwareAspectJAutoProxyCreator。-->refresh()

  • 最后,由于该实例间接实现了BeanPostProcessors,而BeanPostProcessors想起做用的话,必需要调用beanFactory.addBeanPostProcessor()方法注册到容器中。-->refresh()

下篇文章咱们将分析AnnotationAwareAspectJAutoProxyCreator类是怎么起做用的。

相关文章
相关标签/搜索