Spring的BeanFactory是什麼?

什麼是BeanFactory?

提到Spring,老是讓人第一時間想起IOC容器,而IOC容器的頂層核心接口就是咱們的BeanFactory,若是可以理解BeanFactory的體系結構想必能讓咱們對Spring總體脈絡有更加清晰的認知,因此,本文的探究方向主要爲如下幾點:java

  • BeanFactory的體系結構是怎樣的?
  • Bean的元信息從何而來?
  • BeanFactory生產Bean的過程是怎樣的?

BeanFactory的體系結構

咱們先來看看有哪些子類實現了它吧spring

在這裏插入圖片描述
其中ApplicationContext這一塊已在上篇文章有詳細說明,而DefaultListableBeanFactory這個底層實現類便理所固然的成爲了咱們這次探究的出發點,爲了讓咱們有個更好的觀感,如下是純粹的BeanFactoryUML圖:設計模式

在這裏插入圖片描述
咱們能夠看到DefaultListableBeanFactory實現的接口有:spring-mvc

  • SingletonBeanRegistry: 定義了對單例緩存池相關的操做,如將bean註冊到單例緩存池中
  • ConfigurableBeanFactory: 可配置的BeanFactory,定義了各類各樣的配置能力,如bean的做用域,bean的classLoader,添加bean的後置處理器,設置bean的建立狀態,銷燬bean等等
  • AutowireCapableBeanFactory: 能進行自動裝配的BeanFactory,這多是咱們最爲熟悉的BeanFactory,定義了自動裝配的類型(byName/byType),createBean, autowireBean, 自動裝配屬性, populateBean, initializeBean, 對於與bean生命週期相關的方法都將在這裏體現
  • ListableBeanFactory: 對BeanFactory的加強,定義了一系列根據beanType獲取bean或者beanName的方法
  • ConfigurableListableBeanFactory: 對ConfigurableBeanFactory的加強,定義了忽略bean的類型、緩存bean定義、預實例化單例bean等方法
  • BeanDefinitionRegistry: bean定義註冊器,定義了與bean定義相關的方法

若是說以上的接口體現了DefaultListableBeanFactory具有的功能,那麼它所繼承的一系列類就是這些功能的實現:緩存

  • DefaultSingletonBeanRegistry: 單例bean註冊器,定義了三級緩存,其實就是三個Map屬性
  • FactoryBeanRegistrySupport: 提供對FactoryBean的支持
  • AbstractBeanFactory: 實現了一系列操做IOC容器的功能,但最終的createBean依舊交由子類AbstractAutowireCapableBeanFactory完成
  • AbstractAutowireCapableBeanFactory: 實現了建立bean的功能,全部與建立bean的相關的功能都在這裏
  • DefaultListableBeanFactory: 在以上父類的功能基礎上實現了ConfigurableBeanFactoryBeanDefinitionRegistry接口,定義了一些存放Bean定義相關信息的Map

看到這裏,想必對DefaultListableBeanFactory已經有一個大體的瞭解了,那麼問題來啦,咱們應該怎麼從容器中獲取一個bean呢?是否是隻要經過BeanDefinitionRegistry註冊一個bean定義,再經過AutowireCapableBeanFactory去createBean就完成了呢?就像下面這樣:mybatis

DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
RootBeanDefinition beanDefinition = new RootBeanDefinition(Wheel.class);
beanFactory.registerBeanDefinition("wheel",beanDefinition);
beanFactory.getBean("wheel", Wheel.class);

Bean的元信息從何而來?

咱們如今已經知道DefaultListableBeanFactory的大體功能了,咱們發現當咱們想要建立一個Bean的時候,老是離不開一個名詞:Bean定義,那麼這個Bean定義到底是什麼呢?mvc

BeanDefinition實際上是一個接口,並非一個具體的類,咱們也能夠看一下它的UML圖:app

在這裏插入圖片描述
能夠發現這裏使用了模板方法的設計模式擴展了許多的子類,其中咱們最經常使用的爲RootBeanDefinition,它主要包含的屬性以下:
在這裏插入圖片描述源碼分析

咱們向容器中註冊的Bean定義的信息大概就是如此,當BeanFactory生產Bean時,即可以經過beanClass清楚的知道Bean的類是什麼,做用域是怎樣,是否懶加載,init方法是什麼等等等等post

咦,若是一個最簡單的bean,好像能夠直接經過反射就搞定了耶~

具體結構已經清楚了,那咱們來看一下注冊過程吧

先從Demo看起

public static void main(String[] args) {
    //建立一個DefaultListableBeanFactory實例
    DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    //建立一個BeanDefinition
    RootBeanDefinition beanDefinition = new RootBeanDefinition(Wheel.class);
    //將BeanDefinition註冊到容器中
    beanFactory.registerBeanDefinition("wheel",beanDefinition);
}

public static class Wheel {
}

建立BeanDefinition

public RootBeanDefinition(@Nullable Class<?> beanClass) {
    //初始化父類
    super();
    //將beanClass賦值給this.BeanClass
    setBeanClass(beanClass);
}

初始化父類

//將其中一部分屬性賦予默認值
autowireCandidate = true;
primary = false;

protected AbstractBeanDefinition() {
    this(null, null);
}
protected AbstractBeanDefinition(@Nullable ConstructorArgumentValues cargs, @Nullable MutablePropertyValues pvs) {
    this.constructorArgumentValues = cargs;
    this.propertyValues = pvs;
}

將BeanDefinition註冊到容器中

//除去校驗邏輯,註冊時只作了這兩步操做
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);

看到這裏,你們夥可能會充滿疑問?what? 就這樣?沒有填充屬性的步驟嗎?嘿嘿,BeanFactory是一個純粹的工廠,只負責生產Bean,是沒有裝配(設計)BeanDefinition的功能的,專業的事仍是交給專業的人作,設計的事情仍是交由ApplicationContext完成的。

那在ApplicationContext中是怎麼完成一個BeanDefinition的呢?還記得預啓動將配置類註冊到容器中時有這樣一段代碼嗎?如下代碼爲AnnotatedBeanDefinitionReader#doRegisterBean中的摘要部分:

<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
                        @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
	//.......代碼
    //處理普通的bean定義註解,@Lazy @Primary @DependsOn @Role @Description
    AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
    //......代碼
   
}

而非配置的Bean是經過在預啓動時註冊的配置類後置處理器ConfigurationClassPostProcessor#processConfigBeanDefinitions中完成的,如下代碼爲ClassPathBeanDefinitionScanner#doScan中的摘要部分,詳細調用鏈將在後面的文章進行說明

//傳入咱們配置類的包路徑
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
		Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
		for (String basePackage : basePackages) {
            //尋找到全部標識了@Component註解的BeanDefinition
			Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
			for (BeanDefinition candidate : candidates) {
				//....省略代碼
				if (candidate instanceof AbstractBeanDefinition) {
                    //處理BeanDefinition
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
				if (candidate instanceof AnnotatedBeanDefinition) {
 //處理普通的bean定義註解,@Lazy @Primary @DependsOn @Role @Description
                    AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
                //...省略代碼
                //將BeanDefinition註冊到容器中
                registerBeanDefinition(definitionHolder, this.registry);
            }
	}

處理BeanDefinition

protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName) {
	//設置默認值
    beanDefinition.applyDefaults(this.beanDefinitionDefaults);
    //這裏默認爲空
    if (this.autowireCandidatePatterns != null) {
        beanDefinition.setAutowireCandidate(PatternMatchUtils.simpleMatch(this.autowireCandidatePatterns, beanName));
    }
}

設置默認值

public void applyDefaults(BeanDefinitionDefaults defaults) {
    //默認爲null
    Boolean lazyInit = defaults.getLazyInit();
    if (lazyInit != null) {
        setLazyInit(lazyInit);
    }
    //默認爲0
    setAutowireMode(defaults.getAutowireMode());
    //默認爲0
    setDependencyCheck(defaults.getDependencyCheck());
    //默認爲null
    setInitMethodName(defaults.getInitMethodName());
    setEnforceInitMethod(false);
    //默認爲null
    setDestroyMethodName(defaults.getDestroyMethodName());
    setEnforceDestroyMethod(false);
}

處理普通的bean定義註解

public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
    processCommonDefinitionAnnotations(abd, abd.getMetadata());
}

static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
    	//從元數據中取出該註解的屬性列表,不爲空說明有標識該註解
		AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
		if (lazy != null) {
			abd.setLazyInit(lazy.getBoolean("value"));
		}
		else if (abd.getMetadata() != metadata) {
			lazy = attributesFor(abd.getMetadata(), Lazy.class);
			if (lazy != null) {
				abd.setLazyInit(lazy.getBoolean("value"));
			}
		}
		//判斷元數據中是否有該註解
		if (metadata.isAnnotated(Primary.class.getName())) {
			abd.setPrimary(true);
		}
		AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
		if (dependsOn != null) {
			abd.setDependsOn(dependsOn.getStringArray("value"));
		}
		AnnotationAttributes role = attributesFor(metadata, Role.class);
		if (role != null) {
			abd.setRole(role.getNumber("value").intValue());
		}
		AnnotationAttributes description = attributesFor(metadata, Description.class);
		if (description != null) {
			abd.setDescription(description.getString("value"));
		}
	}

attributesFor(metadata, Lazy.class)

static AnnotationAttributes attributesFor(AnnotatedTypeMetadata metadata, Class<?> annotationClass) {
    return attributesFor(metadata, annotationClass.getName());
}
static AnnotationAttributes attributesFor(AnnotatedTypeMetadata metadata, String annotationClassName) {
    //metadata爲beanClass的註解元數據,存放了該類所配置的全部註解
    //annotationClassName爲須要尋找的註解名稱
    return AnnotationAttributes.fromMap(metadata.getAnnotationAttributes(annotationClassName, false));
}
default Map<String, Object> getAnnotationAttributes(String annotationName,
                                                    boolean classValuesAsString) {
    //遍歷元數據中的全部註解
    MergedAnnotation<Annotation> annotation = getAnnotations().get(annotationName,
                                                                   null, MergedAnnotationSelectors.firstDirectlyDeclared());
    //不存在則返回null,不然返回一個map
    if (!annotation.isPresent()) {
        return null;
    }
    return annotation.asAnnotationAttributes(Adapt.values(classValuesAsString, true));
}

以上爲掃描@Component註解類進行解析元數據填充屬性的邏輯,在配置類中以@Bean方式註冊的BeanDefinition填充屬性過程在ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(configClasses)

BeanFactory生產Bean的過程是怎樣的?

如今,咱們已經知道了一個BeanDefinition的具體結構以及是如何產生並註冊到BeanFactory的,那麼BeanFactory又是如何使用它生產Bean的呢?如下附上createBean的粗略流程圖,具體細節將放在IOC容器啓動流程中詳細說明

在這裏插入圖片描述

那麼關於BeanFactory的相關內容就到這裏了,但願你們有所收穫,下篇將正式進入Spring IOC容器的啓動流程!

準備花個30天時間,系統的來整理一下我對spring源碼的認識:

Spring 源碼系列
  1. Spring源碼分析之 IOC 容器預啓動流程(已完結)
  2. Spring源碼分析之BeanFactory體系結構(已完結)
  3. Spring源碼分析之BeanFactoryPostProcessor調用過程(已完結)
  4. Spring源碼分析之Bean的建立過程
  5. Spring源碼分析之什麼是循環依賴及解決方案
  6. Spring源碼分析之AOP從解析到調用
  7. Spring源碼分析之事務管理(上),事物管理是spring做爲容器的一個特色,總結一下他的基本實現與原理吧
  8. Spring源碼分析之事務管理(下) ,關於他的底層事物隔離與事物傳播原理,重點分析一下
Spring Mvc 源碼系列
  1. SpringMvc體系結構
  2. SpringMvc源碼分析之Handler解析過程
  3. SpringMvc源碼分析之請求鏈過程
Mybatis 源碼系列

暫定


追更,可掃下面的二維碼,分享純粹爲了樂趣,也有一種成就感吧,筆者這篇文章先就到這
在這裏插入圖片描述

相關文章
相關標籤/搜索