提到Spring,老是讓人第一時間想起IOC容器,而IOC容器的頂層核心接口就是咱們的BeanFactory
,若是可以理解BeanFactory
的體系結構想必能讓咱們對Spring總體脈絡有更加清晰的認知,因此,本文的探究方向主要爲如下幾點:java
BeanFactory
的體系結構是怎樣的?Bean
的元信息從何而來?BeanFactory
生產Bean
的過程是怎樣的?咱們先來看看有哪些子類實現了它吧spring
其中ApplicationContext
這一塊已在上篇文章有詳細說明,而DefaultListableBeanFactory
這個底層實現類便理所固然的成爲了咱們這次探究的出發點,爲了讓咱們有個更好的觀感,如下是純粹的BeanFactory
UML圖:設計模式
咱們能夠看到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
: 在以上父類的功能基礎上實現了ConfigurableBeanFactory
和BeanDefinitionRegistry
接口,定義了一些存放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,好像能夠直接經過反射就搞定了耶~
具體結構已經清楚了,那咱們來看一下注冊過程吧
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 { }
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; }
//除去校驗邏輯,註冊時只作了這兩步操做 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源碼的認識:
暫定
追更,可掃下面的二維碼,分享純粹爲了樂趣,也有一種成就感吧,筆者這篇文章先就到這