Spring 原始碼閱讀 一
終於,有一天我也來看Spring的原始碼了,看了一陣之後感覺心情那叫一個舒暢,對Spring底層的實現也有了進一步的瞭解, 最直觀的感受就是Spring的命名風格很贊,很長,真的長到使人見名知意, 閒言少敘,開始整理筆記了
程式的入口
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
跟進這個AnnotationConfigApplicationContext()
程式的啟動入口, 註解配置的應用上下文.主要做了下面的三件事
- 呼叫本類無參構造方法
- 呼叫
register(annotatedClasses)
將我們傳遞進來的配置類註冊進BeanFactory
的BeanDefinitionMap
- 重新整理容器
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
register(annotatedClasses);
refresh();
}
建立BeanFactory
首先呼叫本類的無參構造方法,,通過上圖,可以看到,AnnotationConfigAllicationContext
GenericApplicationContext
但是,在執行本類的無參構造方法時會先執行父類的無參構造方法.它父類的無參構造方法我貼在下面,就做了一件事,初始化了Spring的BeanFactory,沒錯就是Spring的Bean工廠,由於兩者的繼承關係,我們就任務,AnnotationConfigApplicationContext
的Bean工廠被初始化了
public GenericApplicationContext() {
this.beanFactory = new DefaultListableBeanFactory();
}
建立AnnotatedBeanDefinitionReader
載入
接著回到這個構造方法的原始碼我貼在下面, 這個構造方法主要做了兩件事
- 為應用的上下文建立reader讀取器, 讀取被添加了註解的類資訊
- 例項化了一個Scanner, 這個Scanner可以用去做包掃描的工作,但是Spring根據我們的配置資訊去進行包掃描的工作時,並沒有使用這個掃描器,而是自己new 了一個,當前的掃描器可以理解成是方便程式設計師使用而建立的
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
下面跟進AnnotatedBeanDefinitionReader
掃描器的建立過程,經過幾個沒有重要邏輯的方法,我們會進入registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source)
,下面是原始碼: 這算是Spring初始化的一個小高潮了!!!,為啥這樣說呢? 因下面的邏輯中,為Spring
初始化過程中,構建BeanFactory提供了幾個開天闢地性質的RootBeanDefinition
``
- 首先是在為
BeanFactory
添加了兩個大元件AnnotationAwareOrderComparator
用於解析@Order
和@Priorty
註解ContextAnnotationAutowireCandidateResolver
提供了懶載入的支援
- 然後就是往
BeanFactory
中的BeanDefinitionMap
中添加了6個RootBeanDefinition
ConfigurationClassPostProcessor
AutowiredAnnotationBeanPostProcessor
- ...
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source) {
// 得到bean工廠
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null) {
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
// 給Bean工廠新增原材料
// AnnotationAwareOrderComparator 主要能解析@Order註解和@Priority
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
}
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
// ContextAnnotationAutowireCandidateResolver 提供處理懶載入(Lazy)相關的功能
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
}
}
// 作用是方便傳遞引數BeanDefinitionHolder
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
// BeanDefinition的註冊,這裡很重要,需要理解註冊每個bean的型別
// 就是判斷工廠中有沒有包含 CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME 名稱的bean, Spring在啟動時,工廠肯定是空的返回false , 加上! 表示ture
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {//configuration_annotation_processor_bean_name
// 注意: 下面的ConfigurationClassPostProcessor實現了BeanDefinitionRegistryPostProcessor,間接實現了 BeanFactoryPostProcessor bean工廠的後置處理器
// RootBeanDefinition可以理解成 描述Spring內部類的Definition
// 除了通過AnnotationedBeanDefinitionReader把 加上了註解的類載入成bean,下面的第二種方式, 通過new RootBeanDefinition, 進而將 XXX.class起來註冊進bean工廠
// 這是使用第二種方式, 通過new Spring自己實現的BeanDefinition介面的類,將java轉換成 Bean 然後put進BeanFactory的BeanDefinitionMap中
// 下面的111-666 就是最先放置進去的6個Spring的RootBean物件
// ---111---------------------------
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
// 跟進去 registerPostProcessor
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
//AutowiredAnnotationBeanPostProcessor 實現了 MergedBeanDefinitionPostProcessor
//MergedBeanDefinitionPostProcessor 最終實現了 BeanPostProcessor
// ---222---------------------------
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
// ---333---------------------------
RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
}
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
// ---444---------------------------
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)) {
// ---555---------------------------
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)) {
// ---666---------------------------
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
}
return beanDefs;
}
上面的程式碼中有來如下兩個亮點:
亮點1:RootBeanDefinition
首先涉及到的知識點就是,Spring有哪幾種方式將物件轉成BeanDefinition
? 其實是有兩種,第一種就是讓Spring通過Scanner去掃描包解析程式設計師提供的添加了註解的類,這是個自動完成的過程,第二種就是Spring
通過new RootBeanDefinition
等諸多的BeanDefinition
介面的實現類, 然後將Spring原生的物件當成引數傳遞進去進而轉換成BeanDefinition
, 當然,Spring
在這裡選擇的就是第二種方法
亮點2:ConfigurationClassPostProcessor
這個類很牛,為什麼這麼說呢? 先看一下他的繼承類圖
沒錯,他是6個RootBeanDefinition
中唯一的一個實現BeanFactoryPostProcessor
的,其他的五個RootBeanDifinition
實現的都是BeanPostProcessor
, 其實也不用懵逼,只要我們整明白這裡說的BeanPostProcessor
和BeanFactoryPostProcessor
的作用就好了,然後在這裡我用下面的兩個模組解釋
BeanPostProcessor
介面的抽象方法原始碼如下:
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
兩個方法名,見名知意: 第一個會在 物件的 constructor
之後,init()
方法之前呼叫
第二個會在init()
方法之後呼叫
但是,大家可以發現,它的呼叫時機都是在構造方法執行之後進行攔截,這時候BeanDefinition
已經被例項化了
BeanFactoryPostProcessor
@FunctionalInterface
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
它就比較厲害了, 這也是Spring牛的地方,它不僅僅會替我們維護這些Bean,而且還通過當前的BeanFactoryPostProcessor
,為程式設計師開放一個缺口,讓程式設計師可以參與到Bean的建立過程中來,為什麼這樣說呢, 其實大家可以看到,它唯一的抽象方法中的入參位置上是誰? 沒錯,就是BeanFactory, Bean工廠都給我們了,那不是想幹啥幹啥?
其次,它的作用時機是執行Bean的構造方法之前
最直接的應用場景: 當一個單例的Bean依賴 多例的Bean時,我們多次通過 應用的上下文獲取出來的單例bean的hashcode都是唯一的這沒錯,但是緊接著列印它依賴的多例物件的hashcode同樣是相同的,這種單例失效的問題,就可以根據這個知識點從容解決
前面說的ConfigurationClassPostProcessor
就是BeanFactoryPostProcessor
的實現類,並且它也不辱使命, 完美的使用作用時機不同的特點,在程式設計師提供的配置類的構造方法呼叫之前,就先入為主,圍棋生成了 cglib代理物件
接著看程式碼,回到上面的程式碼,我們看如何將RootBeanDefinition
註冊進BeanFactory
, 我從上面擷取一行程式碼放在這裡
// 跟進去 registerPostProcessor
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
跟進這個registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)
private static BeanDefinitionHolder registerPostProcessor(
BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// registerBeanDefinition()
registry.registerBeanDefinition(beanName, definition);
return new BeanDefinitionHolder(definition, beanName);
}
我們關注這個registry.registerBeanDefinition(beanName, definition);
, 可以看到,其實這個registerBeanDefinition()
是BeanDefinitionRegistry
的抽象方法,我們要找的是它的實現類,那問題來了, 是誰實現他呢? 可以回到部落格頂部,看看第一個圖,沒錯Spring的BeanFactory,也就是DefualtListableBeanFactory
實現了這個介面,雖然有點意外,一個工廠竟然還是一個註冊器,但是這也是事實情況, 看看這個工廠是如何做的吧 .原函式很長,我截取了部分原始碼如下: 它的解釋我寫在原始碼的下面
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
...
else {
// 新增進入容器中, 最終的結果就是,這個map中存在哪些類,Spring的IOC中就有哪些類
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
// 單獨使用一個list存放名字
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
可以看到,他將一開始的6個RootBeanDefinition
全都都put進了一個map中, 下面這個map
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
key就是beanName, value就是BeanDefinition
這也是迄今為止我們遇到的第一個map, 這個map是BeanFactory的一個元件,但是它可不是傳說中的IOC容器,大家也看到了它裡面存放的是BeanDefinition,而不是Bean
將配置類註冊進BeanFactory
回到一開始AnnotationConfigApplicationContext
的register(annotatedClasses);
方法,然後一路往下跟,會經過幾個沒有什麼重要邏輯的方法, 然後來到這裡
public void register(Class<?>... annotatedClasses) {
for (Class<?> annotatedClass : annotatedClasses) {
// 繼續跟進去
registerBean(annotatedClass);
}
}
通過上面的程式碼,我們可以回想,annotatedClasses
這個可變長度的引數,其實就是我們在AnnotationConfigApplicationContext
中傳遞進來的主配置類MainConfig
, 也就是說,這個主配置類是可以存在多個的
接著往下跟
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
// 可以將當前類理解成一個方便引數傳遞的封裝類
// 意為: 被加上註解的通用的BD
// 將傳遞進來的 主配置類封裝進 這個AnnotatedGenericBeanDefinition
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
abd.setInstanceSupplier(instanceSupplier);
// 解析出它的元資料
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
// 設定它的作用域
abd.setScope(scopeMetadata.getScopeName());
// 名稱生成器, 目的是為BeanDefinition取個名字,因為這個BD最終被存放到一個map中,
// 預設情況下@Configuration(value = "XXX") 這個value有值,就是使用這個當成名字
// 都這就使用 類名首字母小寫當成名字
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
// 處理bean上的通用註解, @Lazy @Dependon @Primary role等
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
//懶載入,前面加過
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
customizer.customize(abd);
}
// 理解成方便引數傳遞的封裝類
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd,beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 我們關注的重點, 註冊BeanDefinition
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
上面的函式的主要作用如下: 將我們通過AnnotationConfigApplicationContext
建構函式傳遞進來的主配置類封裝進了AnnotatedGenericBeanDefinition中,然後解析它身上的其他註解完成屬性的賦值
接著跟進registerBeanDefinition()
方法
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// 再來這個方法之前封裝了一個 difinitionHolder , 然後在這裡又把它拆分開傳遞給了下面的函式
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
// 在當前的BeanDefinitionReaderUtils中使用
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
繼續跟進
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
於是有回到了上面註冊6大RootBeanDefinition
的邏輯中,將我們的主配置類註冊進BeanFactory
的BeanDefinitionMap
中
未完待續