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類是怎麼起做用的。

相關文章
相關標籤/搜索