學(xué)java必學(xué)spring仗处,java程序員就是spring程序員,spring作為java開發(fā)的基礎(chǔ)設(shè)施(infrastructure)吨拍,在大多數(shù)java程序員看來最重要的功能就是IOC和AOP褪猛,實際上spring最重要的功能是它提供的各種擴展點,方便我們整合其它框架密末,今天來聊聊spring創(chuàng)建bean的過程中各種擴展接口的調(diào)用
????話不多說握爷,先上一張我在看源碼過程中畫的流程圖,大家可以先看看有個總體印象严里。
?流程圖在線查看地址:
https://www.processon.com/view/link/615c4965f346fb69a724dc8c
Bean創(chuàng)建過程擴展點詳解:
擴展點一:
InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
這是實例化之前第一次調(diào)用Bean后置處理器新啼,它的主要設(shè)計目的就是在實例化之前我們可以按照我們自己的邏輯創(chuàng)建任意的對象(一般是代理對象),如果這一步返回的對象不為空刹碾,則直接返回我們自己創(chuàng)建的對象燥撞,不會走剩下的創(chuàng)建流程,代碼如下圖:
擴展點二:
SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors
這是實例化之前的第二次調(diào)用迷帜,用來推斷調(diào)用哪個構(gòu)造器來實例化我們的對象物舒,這個擴展點主要提供給spring自己使用,不做過多展開戏锹,代碼如下圖:
擴展點三:
MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
這是實例化之后第一次調(diào)用冠胯,允許后置處理器修改合并后的BeanDefinition,比如設(shè)置初始化方法锦针,@Autowired荠察、@Resource和@Value注解就是在這里解析的置蜀,解析后封裝到InjectionMetadata,供后面屬性注入使用悉盆,代碼如下圖:
擴展點四:
SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference
這是實例化之后第二次調(diào)用盯荤,主要是用來處理循環(huán)依賴,會把創(chuàng)建的對象 放到earlySingletonObjects焕盟,代碼如下圖:
擴展點五:
InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation
這是進入屬性填充方法后執(zhí)行的方法秋秤,在這里我們可以自己為bean填充屬性,此方法的返回值為boolean脚翘,如果返回為false灼卢,則直接返回,不繼續(xù)后面的屬性注入邏輯来农,代碼如下圖:
擴展點六:
InstantiationAwareBeanPostProcessor#postProcessPropertyValues
主要是CommonAnnotationBeanPostProcessor(用來處理@Resource注解)和AutowiredAnnotationConigApplication(處理@Autowired和@Value注解)芥玉;如果是自動注入(AutowireMode不為null),是無需通過后置處理器來進行屬性注入的备图,代碼如下圖:
擴展點七:調(diào)用Aware接口的方法
下面是初始化階段了,如果我們的bean實現(xiàn)了各種Aware接口赶袄,則spring就會調(diào)用Aware接口對應(yīng)的方法揽涮,比如實現(xiàn)了BeanNameAware,我們可以拿到bean的名字饿肺,實現(xiàn)了BeanClassLoaderAware可以拿到bean的類加載器蒋困,實現(xiàn)了BeanFactoryAware,可以拿到bean的工廠敬辣,實現(xiàn)了ApplicationContextAware可以拿到應(yīng)用上下文雪标,代碼如下圖:
擴展點八:
BeanPostProcessor#postProcessBeforeInitialization
這里是初始化前調(diào)用后置處理器的地方,@postconstruct注解的方法就是在這里被后置處理器調(diào)用的溉跃,代碼如下圖:
擴展點九:
InitializingBean#afterPropertiesSet
如果我們的bean實現(xiàn)了InitializingBean接口村刨,會在這里調(diào)用,工作中我經(jīng)常用這個接口來進行一些初始化工作撰茎,比如布隆過濾器的初始化嵌牺,微服務(wù)中網(wǎng)關(guān)統(tǒng)一認(rèn)證授權(quán)時公鑰的拿取,代碼如下圖:
擴展點十:調(diào)用用戶自己注解的InitMethod
擴展點十一:
BeanPostProcessor#postProcessAfterInitialization
大名鼎鼎的AOP就是在這里生成的