天天看點

Spring 5.x 源碼之旅一AnnotatedBeanDefinitionReader前言簡單注解例子簡單思考AnnotationConfigApplicationContext注解配置上下文AnnotatedBeanDefinitionReader讀取器

Spring 5.x 源碼之旅一AnnotatedBeanDefinitionReader

  • 前言
  • 簡單注解例子
  • 簡單思考
  • AnnotationConfigApplicationContext注解配置上下文
    • 先看下大緻建立了什麼
  • AnnotatedBeanDefinitionReader讀取器
    • getOrCreateEnvironment獲得或者建立環境
    • AnnotatedBeanDefinitionReader構造方法
    • 重要屬性
    • AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)注冊注解配置處理器
    • AnnotationConfigUtils的registerPostProcessor注冊後置處理器
      • GenericApplicationContext的registerBeanDefinition注冊bean定義
        • DefaultListableBeanFactory的registerBeanDefinition注冊bean定義
    • BeanDefinitionHolder封裝bean定義而已

前言

前面寫了一些

netty

的源碼解析,雖然覆寫不了所有的内容,但是大部分核心的内容都講到了,主要還是要自己去看,去了解,然後寫點小

demo

,領會

netty

的設計意圖,為什麼能高性能,從線程的分工明确,多路複用到記憶體配置設定的分而治之,讓多線程之間減少競争,讓記憶體使用效率提高,等等一些思想。現在想再分析下

Spirng 5.2.1.RELEASE

的源碼,雖然這個很複雜,但是我們還是可以大緻了解一些原理,對以後使用和問題定位都有所幫助,而且還可以學到一些思想,一些處理方法,一些設計模式等等。我們主要是研究注解使用的一些原理。

簡單注解例子

首先我們建立一個配置類

MyConfig

@Configuration
public class MyConfig {
    
}

           

然後寫一個測試方法,友善我們調試:

@Test
    public void BeanDefinitionRegistryPostProcessorTest0() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
    }
           

啥都不幹,就分析他對配置類做了什麼。

簡單思考

先不看源碼,我們自己思考下我們把一個配置類放進去,他可能會做點什麼。假設我們都用過

Spring

,哪怕最簡單的那種,很明顯我們可以猜到,他裡面應該是對我們注解

@Configuration

的類進行了解析,分析他裡面有點什麼,然後進行相應的處理。确實大緻思路就這樣,但是具體就比較複雜了,我們還是看源碼慢慢分析吧。

AnnotationConfigApplicationContext注解配置上下文

先看下大緻建立了什麼

Spring 5.x 源碼之旅一AnnotatedBeanDefinitionReader前言簡單注解例子簡單思考AnnotationConfigApplicationContext注解配置上下文AnnotatedBeanDefinitionReader讀取器

首先我們看名字隻知道他是注解配置的上下文,也就是一個環境,那環境裡面應該有好多東西,可以處理我們傳進去的類。我們剛才調用的構造方法就是這個:

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
		this();
		register(componentClasses);
		refresh();
	}
	
	public AnnotationConfigApplicationContext() {
		this.reader = new AnnotatedBeanDefinitionReader(this);
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}
	public GenericApplicationContext() {
		this.beanFactory = new DefaultListableBeanFactory();
	}

           

首先他先建立了一個

DefaultListableBeanFactory

,這個就是後面一直要用的

bean

工廠,裡面放着所有和

bean

相關的東西,比如

bean

定義,bean後置處理器等等,其實spring的思想就是把你給他的類都需要一個

bean

定義來描述,這樣才可以進行處理。然後再建立

AnnotatedBeanDefinitionReader

ClassPathBeanDefinitionScanner

,一個是注解的

bean

定義讀取器,一個是

bean

定義的掃描器。這裡要注意

ClassPathBeanDefinitionScanner

其實是提供給使用者用的,并不是他内部使用,内部後面他會再建立一個來用。我們先來看下

AnnotatedBeanDefinitionReader

建立做了什麼。

AnnotatedBeanDefinitionReader讀取器

看這個構造方法,傳入的是一個

BeanDefinitionRegistry

類型,就是可以注冊

bean

定義的,内部要注冊就需要用到。

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
		this(registry, getOrCreateEnvironment(registry));
	}
           

getOrCreateEnvironment獲得或者建立環境

如果

BeanDefinitionRegistry

EnvironmentCapable

的話就可以直接擷取,否則就建立一個标準環境,其實就是擷取一些系統的變量。比如可以配置

dev

環境,

test

環境,

online

環境等等。

private static Environment getOrCreateEnvironment(BeanDefinitionRegistry registry) {
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		if (registry instanceof EnvironmentCapable) {
			return ((EnvironmentCapable) registry).getEnvironment();
		}
		return new StandardEnvironment();
	}
           

AnnotatedBeanDefinitionReader構造方法

BeanDefinitionRegistry

進行了儲存和把

environment

封裝進了

ConditionEvaluator

ConditionEvaluator

可以了解成一個條件過濾器,與

@Conditional

有關,如果有了這個注解,就先判斷條件成不成立,不成立的話有些操作就不做了。

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
		Assert.notNull(environment, "Environment must not be null");
		this.registry = registry;
		this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
		AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
	}
           

重要屬性

另外有三個屬性後面會用到,比如

bean

的名字生成器

BeanNameGenerator

,可以自定義怎麼生成,預設是簡單類名首字母小寫,還有一個是範圍注解的解析器

ScopeMetadataResolver

,解析出範圍,是單例,還是原型,另一個就是條件評估器了

ConditionEvaluator

private final BeanDefinitionRegistry registry;
	//類名生成器
	private BeanNameGenerator beanNameGenerator = AnnotationBeanNameGenerator.INSTANCE;
	//socpe注解解析器
	private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();
	//條件評估器
	private ConditionEvaluator conditionEvaluator;
           

AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)注冊注解配置處理器

這個一看方法就知道要加一些處理器,來處理我們的注解,也就是說,

spring

有些内部的處理器需要注冊進來,這裡可以想到

spring

應該是為了統一處理處理器,是以也是按注冊,處理這樣的流程來,無論是自己内部的,還是使用者自定義的,我們來看看裡面是怎麼做的。

public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
		registerAnnotationConfigProcessors(registry, null);
	}
           

主要流程就是擷取

DefaultListableBeanFactory

,然後注冊

AnnotationAwareOrderComparator

順序比較器,排序用的,

ContextAnnotationAutowireCandidateResolver

自動裝配解析器,解析自動裝配相關配置用。然後建立一些後置處理器的

bean

定義,内部一般用

RootBeanDefinition

來定義,比如這個類

ConfigurationClassPostProcessor

,他是前面配置類處理的關鍵,是以這裡先添加

bean

定義,還有

AutowiredAnnotationBeanPostProcessor

,處理自動裝配的,另外還有

EventListenerMethodProcessor

DefaultEventListenerFactory

CommonAnnotationBeanPostProcessor

暫時不講,後面用到會說。

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
			BeanDefinitionRegistry registry, @Nullable Object source) {
		//擷取beanFactory
		DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
		if (beanFactory != null) {
			if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
				beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);//設定依賴比較器
			}
			if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
				beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());//設定自動裝配解析器
			}
		}
		//建立BeanDefinitionHolder集合
		Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
		//設定ConfigurationClassPostProcessor後置處理器
		if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
		}
		//自動裝配注解處理器
		if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
		if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
		if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition();
			try {
				def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
						AnnotationConfigUtils.class.getClassLoader()));
			}
			catch (ClassNotFoundException ex) {
				throw new IllegalStateException(
						"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
			}
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
		}
		//事件監聽方法處理器
		if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
		}
		//預設事件監聽器工廠
		if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
		}

		return beanDefs;
	}
           

AnnotationConfigUtils的registerPostProcessor注冊後置處理器

注冊後置處理器,其實是注冊對應的

bean

定義,對于一些内部處理器的

bean

定義,會設定角色屬性

setRole

,然後向

registry

裡注冊

beanName

bean

定義,最後封裝成

BeanDefinitionHolder

傳回。

private static BeanDefinitionHolder registerPostProcessor(
			BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {

		definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		registry.registerBeanDefinition(beanName, definition);//注冊進registry
		return new BeanDefinitionHolder(definition, beanName);
	}
           

GenericApplicationContext的registerBeanDefinition注冊bean定義

可以看到,這裡出現了

beanFactory

,就是我們開始獲得的

DefaultListableBeanFactory

,注冊

bean

定義是交給他的。

@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {

		this.beanFactory.registerBeanDefinition(beanName, beanDefinition);
	}
           

DefaultListableBeanFactory的registerBeanDefinition注冊bean定義

其他非核心的暫時略過了,剩下就兩行,最終是把他放入

ConcurrentHashMap

中,名字放入

ArrayList

中。放在

map

裡是為了後面可以友善映射擷取,名字在

list

中則是為了友善擷取周遊。

...
	this.beanDefinitionMap.put(beanName, beanDefinition);//名字和bean定義對應
				this.beanDefinitionNames.add(beanName);//名字
...
           

BeanDefinitionHolder封裝bean定義而已

這個類其實就是對

beanName

bean

定義和别名做了封裝:

Spring 5.x 源碼之旅一AnnotatedBeanDefinitionReader前言簡單注解例子簡單思考AnnotationConfigApplicationContext注解配置上下文AnnotatedBeanDefinitionReader讀取器

最後注解配置處理器注冊完成,注冊了比較器和解析器,注冊了注解處理器

bean

定義:

Spring 5.x 源碼之旅一AnnotatedBeanDefinitionReader前言簡單注解例子簡單思考AnnotationConfigApplicationContext注解配置上下文AnnotatedBeanDefinitionReader讀取器
Spring 5.x 源碼之旅一AnnotatedBeanDefinitionReader前言簡單注解例子簡單思考AnnotationConfigApplicationContext注解配置上下文AnnotatedBeanDefinitionReader讀取器

可以看到,内部的

bean

定義全部都是用

RootBeanDefinition

,關于

bean

定義的類型後面會說,先了解就行。至此讀取器建立完成,其實就是注冊了需要處理注解的處理器

bean

定義,此時還沒有建立

bean

哦。後面

ConfigurationClassPostProcessor

發揮着很大的作用,用來解析配置類。後面我們要先了解下

spring

裡的

bean

定義到是定義什麼。

好了,今天就到這裡了,希望對學習了解有幫助,大神看見勿噴,僅為自己的學習了解,能力有限,請多包涵。

繼續閱讀