IOC(Inversion of Control)极谊,即控制反轉(zhuǎn)什荣,是面向?qū)ο缶幊讨械囊环N設(shè)計(jì)原則,可以用來減低代碼之間的耦合度怀酷。在Spring中,IOC意味著對(duì)象和資源的創(chuàng)建和獲取統(tǒng)一交給了容器嗜闻,由容器控制對(duì)象的生命周期和對(duì)象間的依賴關(guān)系蜕依。
而DI(Dependency Injection),即依賴注入琉雳,是實(shí)現(xiàn)IOC的一種手段样眠。DI意味著組件之間依賴關(guān)系由容器在運(yùn)行期決定,形象的說翠肘,即由容器動(dòng)態(tài)的將某個(gè)依賴關(guān)系注入到組件之中檐束。
要理解Spring IOC的實(shí)現(xiàn),首先需要了解下面兩個(gè)接口:BeanFactory和ApplicationContext束倍。
1. BeanFactory
BeanFactory是Spring中的Bean工廠, 用于Spring中Bean的生命周期管理绪妹。它的主要接口如下:
public interface BeanFactory {
/*
* 四個(gè)不同形式的getBean方法甥桂,獲取實(shí)例
*/
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
Object getBean(String name, Object... args) throws BeansException;
boolean containsBean(String name); // 是否存在
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;// 是否為單例
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;// 是否為原型(多實(shí)例)
boolean isTypeMatch(String name, Class<?> targetType)
throws NoSuchBeanDefinitionException;// 名稱、類型是否匹配
Class<?> getType(String name) throws NoSuchBeanDefinitionException; // 獲取類型
String[] getAliases(String name);// 根據(jù)實(shí)例的名字獲取實(shí)例的別名
//......
}
2. ApplicationContext
ApplicationContext是BeanFactory的子接口邮旷,在擁有所有BeanFactory功能的基礎(chǔ)上黄选,它還繼承了一些其他接口:
因此,ApplicationContext擁有一些高階功能婶肩,例如:
- HierarchicalBeanFactory 是一個(gè)具有層級(jí)關(guān)系的 BeanFactory办陷,擁有屬性 parentBeanFactory。ListableBeanFactory 實(shí)現(xiàn)了枚舉方法可以列舉出當(dāng)前 BeanFactory 中所有的 bean 對(duì)象而不必根據(jù) name 一個(gè)一個(gè)的獲取律歼。
- MessageSource接口提供國際化功能
- ApplicationEventPublisher提供事件發(fā)布訂閱功能
- ResourceLoader提供資源加載功能
- EnvironmentCapable用于獲取 Environment 的功能
ApplicationContext常用實(shí)現(xiàn)類包括:ClassPathXMLApplicationContext民镜, FileSystemXmlApplicationContext,AnnotationConfigApplicationContext和WebApplicationContext苗膝。
3. 容器入口
我們以ClassPathXmlApplicationContext為例殃恒,下面是其構(gòu)造函數(shù):
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
Spring首先讀取Config文件位置,然后調(diào)用refresh方法進(jìn)行BeanFactory的構(gòu)建辱揭。
4. 容器構(gòu)建流程
下面是AbstractApplicationContext
中refresh方法的實(shí)現(xiàn):
public void refresh() throws BeansException, IllegalStateException {
// refresh過程只能一個(gè)線程處理离唐,不允許并發(fā)執(zhí)行
synchronized (this.startupShutdownMonitor) {
prepareRefresh();
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
prepareBeanFactory(beanFactory);
try {
postProcessBeanFactory(beanFactory);
invokeBeanFactoryPostProcessors(beanFactory);
registerBeanPostProcessors(beanFactory);
initMessageSource();
initApplicationEventMulticaster();
onRefresh();
registerListeners();
finishBeanFactoryInitialization(beanFactory);
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
destroyBeans();
cancelRefresh(ex);
throw ex;
}
finally {
resetCommonCaches();
}
}
}
主要的流程圖如下:
4.1 prepareRefresh
執(zhí)行一些初始化操作丙躏,包括記錄當(dāng)前時(shí)間舅世,初始化變量等嫩码。其源碼如下:
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
// Initialize any placeholder property sources in the context environment
initPropertySources();
// Validate that all properties marked as required are resolvable
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();
}
4.2 obtainFreshBeanFactory
創(chuàng)建一個(gè)BeanFactory鳍寂。此方法會(huì)調(diào)用refreshBeanFactory
方法饮怯,其源碼如下:
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}
從源碼上看,refreshBeanFactory方法的主要流程如下:
- 若已經(jīng)存在beanFactory则披,銷毀它
- 創(chuàng)建新的beanFactory(new DefaultListableBeanFactory(getInternalParentBeanFactory()))
- 通過
customizeBeanFactory
定制BeanFactory的屬性搂誉; - 加載BeanDefinition到當(dāng)前BeanFactory中(對(duì)于ClassPathXmlApplicationContext來說,會(huì)調(diào)用XmlBeanDefinitionReader讀取所有的Bean定義熟呛,封裝為BeanDefinition注冊到BeanFactory中)宽档;
ApplicationContext實(shí)現(xiàn)了BeanFactory接口,其內(nèi)部是通過聚合一個(gè)DefaultListableBeanFactory來實(shí)現(xiàn)所有的BeanFactory功能的庵朝。
下面時(shí)BeanDefinition接口的主要定義:
public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
//單例作用域
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
//原型作用域
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
String getParentName();
void setParentName(String parentName);
String getBeanClassName();
void setBeanClassName(String beanClassName);
String getScope();
void setScope(String scope);
boolean isLazyInit();
void setLazyInit(boolean lazyInit);
boolean isPrimary();
void setPrimary(boolean primary);
boolean isSingleton();
boolean isPrototype();
//......
}
DefaultListableBeanFactory
中維護(hù)了一個(gè)Map用于存儲(chǔ)所有的BeanDefinition:
/** Map of bean definition objects, keyed by bean name */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
另外吗冤,DefaultSingletonBeanRegistry
(DefaultListableBeanFactory
的父類)中維護(hù)了一個(gè)Map用于存儲(chǔ)所有的Bean:
/** Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
4.3 prepareBeanFactory
在BeanFactory已經(jīng)創(chuàng)建成功后,Spring會(huì)調(diào)用prepareBeanFactory(beanFactory)
來向已經(jīng)創(chuàng)建的BeanFactory注冊一些特定的Bean九府,包括environment
等:
// 如果沒有定義 "environment" 這個(gè) bean椎瘟,那么 Spring 會(huì) "手動(dòng)" 注冊一個(gè)
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
// 如果沒有定義 "systemProperties" 這個(gè) bean,那么 Spring 會(huì) "手動(dòng)" 注冊一個(gè)
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
// 如果沒有定義 "systemEnvironment" 這個(gè) bean侄旬,那么 Spring 會(huì) "手動(dòng)" 注冊一個(gè)
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
另外肺蔚,還會(huì)注冊一些BeanPostProcessor,包括ApplicationContextAwareProcessor
儡羔,ApplicationListenerDetector
等:
// 添加一個(gè) BeanPostProcessor宣羊,這個(gè) processor 比較簡單,
// 實(shí)現(xiàn)了 Aware 接口的幾個(gè)特殊的 beans 在初始化的時(shí)候汰蜘,這個(gè) processor 負(fù)責(zé)回調(diào)
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 這個(gè) BeanPostProcessor 也很簡單段只,在 bean 實(shí)例化后,如果是 ApplicationListener 的子類鉴扫,
// 那么將其添加到 listener 列表中赞枕,可以理解成:注冊事件監(jiān)聽器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
4.3 postProcessBeanFactory
在BeanFactory基本完成后,Spring調(diào)用postProcessBeanFactory(beanFactory)
來進(jìn)行后續(xù)的針對(duì)BeanFactory的操作坪创。AbstractApplicationContext
中的默認(rèn)實(shí)現(xiàn)為空炕婶。而其子類AnnotationConfigEmbeddedWebApplicationContext
對(duì)應(yīng)的postProcessBeanFactory
方法則會(huì)掃描basePackage下的bean并注冊到BeanFactory中。
4.4 invokeBeanFactoryPostProcessors
在BeanFactory創(chuàng)建完畢后莱预,Spring調(diào)用invokeBeanFactoryPostProcessors(beanFactory)
來運(yùn)行所有已經(jīng)注冊的BeanFactoryPostProcessor柠掂,從而進(jìn)行修改BeanFactory或修改BeanFactory中已經(jīng)存在的BeanDefinition。
public interface BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for overriding or adding
* properties even to eager-initializing beans.
* @param beanFactory the bean factory used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
常見的BeanFactoryPostProcessor
包括ConfigurationClassPostProcessor
依沮,PropertyPlaceholderConfigurer
等涯贞。
ConfigurationClassPostProcessor
用于讀取所有已經(jīng)注冊的Configuration類型的Bean,然后注入Configuration類中定義的Bean危喉,最后判斷該Configuration是否擁有ComponentScan
注解宋渔,如果擁有則掃描basePackage下的所有bean并注冊到BeanFactory中。
如果spring配置文件中包含了<context:annotation-config/> 或 <context:component-scan/>辜限,spring則會(huì)自動(dòng)啟用
ConfigurationClassPostProcessor
皇拣。
invokeBeanFactoryPostProcessors(beanFactory)
方法內(nèi)部首先對(duì)所有的BeanFactoryPostProcessor
進(jìn)行排序,然后依次調(diào)用。
4.5 registerBeanPostProcessors
registerBeanPostProcessors
方法會(huì)對(duì)所有BeanFactory內(nèi)的BeanPostProcessor
類型的Bean進(jìn)行排序氧急,然后調(diào)用registerBeanPostProcessors
注冊這些BeanPostProcessor
颗胡,最終在createBean時(shí)會(huì)依次調(diào)用這些BeanPostProcessor
來customize最終生成的Bean。BeanPostProcessor
和BeanFactoryPostProcessor
的區(qū)別在于吩坝,BeanPostProcessor
用于實(shí)例化bean后再customize bean毒姨,而BeanFactoryPostProcessor
則用于BeanFactory創(chuàng)建完成后customize BeanFactory。
BeanPostProcessor
接口如下:
public interface BeanPostProcessor {
// inti方法調(diào)用之前的操作
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
// init方法調(diào)用之后的操作
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
BeanPostProcessor調(diào)用時(shí)bean已經(jīng)被實(shí)例化钉寝,并且所有該注入的屬性都已經(jīng)被注入手素,是一個(gè)完整的Bean。下面是postProcessBeforeInitialization
和postProcessAfterInitialization
的調(diào)用時(shí)間:
- 在Bean實(shí)例化完成后調(diào)用
BeanPostProcessor.postProcessBeforeInitialization
- 如果Bean實(shí)現(xiàn)了InitializingBean接口瘩蚪,則調(diào)用
InitializingBean.afterPropertiesSet
方法 - 如果Bean中配置了init-method,則調(diào)用init-method
- 調(diào)用
BeanPostProcessor.postProcessAfterInitialization
InitializingBean接口的定義如下:
public interface InitializingBean {
/**
* Invoked by a BeanFactory after it has set all bean properties supplied
* (and satisfied BeanFactoryAware and ApplicationContextAware).
* <p>This method allows the bean instance to perform initialization only
* possible when all bean properties have been set and to throw an
* exception in the event of misconfiguration.
* @throws Exception in the event of misconfiguration (such
* as failure to set an essential property) or if initialization fails.
*/
void afterPropertiesSet() throws Exception;
}
常見的BeanPostProcessor
包括ApplicationContextAwareProcessor
稿黍,ApplicationListenerDetector
疹瘦,AutowiredAnnotationBeanPostProcessor
等。
ApplicationContextAwareProcessor
用于調(diào)用Bean的Aware的接口(包括ApplicationContextAware巡球,MessageSourceAware言沐,ApplicationEventPublisherAware等)。例如如果Bean實(shí)現(xiàn)了ApplicationContextAware
接口酣栈,在Bean實(shí)例化結(jié)束后险胰,會(huì)調(diào)用ApplicationContextAware
接口的setApplicationContext(ApplicationContext applicationContext)
方法來cutomize實(shí)例化后的Bean。
ApplicationListenerDetector
用于如果Bean實(shí)現(xiàn)了ApplicationListener
接口矿筝,那么它會(huì)將這個(gè)Bean加入ApplicationEventMulticaster的listener列表中起便。
AutowiredAnnotationBeanPostProcessor
用于注入所有使用了@Autowired注解的屬性。
4.6 initMessageSource
MessageSource是Spring提供國際化的接口窖维。ApplicationContext實(shí)現(xiàn)了MessageSource接口榆综,其內(nèi)部是通過聚合一個(gè)MessageSource對(duì)象來實(shí)現(xiàn)的。initMessageSource
方法主要是為了初始化ApplicationContext內(nèi)部的MessageSource對(duì)象铸史。如果BeanFactory中存在一個(gè)MessageSource Bean鼻疮,那么直接將這個(gè)Bean賦值給ApplicationContext內(nèi)部的MessageSource對(duì)象。如果沒有琳轿,則會(huì)構(gòu)造一個(gè)new DelegatingMessageSource()
對(duì)象判沟。
4.7 initApplicationEventMulticaster
initApplicationEventMulticaster
顧名思義,是為了初始化ApplicationEventMulticaster
崭篡。ApplicationContext實(shí)現(xiàn)了ApplicationEventPublisher
接口挪哄,從而具備了事件發(fā)布功能。其內(nèi)部是通過聚合一個(gè)ApplicationEventMulticaster
實(shí)現(xiàn)的琉闪。下面是初始化代碼:
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isDebugEnabled()) {
logger.debug("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate ApplicationEventMulticaster with name '" +
APPLICATION_EVENT_MULTICASTER_BEAN_NAME +
"': using default [" + this.applicationEventMulticaster + "]");
}
}
}
和initMessageSource
方法類似中燥,如果BeanFactory中存在一個(gè)名為applicationEventMulticaster
的對(duì)象,則將其賦值給內(nèi)部的this.applicationEventMulticaster
塘偎。否則疗涉,直接通過new SimpleApplicationEventMulticaster(beanFactory)
實(shí)例化一個(gè)ApplicationEventMulticaster拿霉。之后ApplicationContext所有事件發(fā)布功能都會(huì)轉(zhuǎn)交給內(nèi)部的applicationEventMulticaster對(duì)象。
ApplicationEventMulticaster主要負(fù)責(zé)事件的發(fā)布和監(jiān)聽者的注冊咱扣。主要接口如下:
// 注冊監(jiān)聽者
void addApplicationListener(ApplicationListener<?> listener);
//發(fā)布事件
void multicastEvent(ApplicationEvent event);
//......
ApplicationEventMulticaster的實(shí)現(xiàn)類內(nèi)部擁有一個(gè)Set<ApplicationListener<?>> applicationListeners
監(jiān)聽者集合绽淘。在掃描出所有實(shí)現(xiàn)了ApplicationListener接口的類后,通過以下方法創(chuàng)建一個(gè)ApplicationListener<?>
對(duì)象闹伪,然后添加到Set<ApplicationListener<?>> applicationListeners
監(jiān)聽者集合中沪铭。
public ApplicationListener<?> createApplicationListener(String beanName, Class<?> type, Method method) {
return new ApplicationListenerMethodAdapter(beanName, type, method);
}
4.8 onRefresh
擴(kuò)展方法,由子類實(shí)現(xiàn)用于初始化其他的特殊Bean偏瓤。AbstractApplicationContext
默認(rèn)實(shí)現(xiàn)為空杀怠。
4.9 registerListeners
注冊事件監(jiān)聽器。將BeanFactory中存在的ApplicationListener類型的Bean注冊到ApplicationContext內(nèi)部的ApplicationEventMulticaster中厅克。
4.10 finishBeanFactoryInitialization
通過調(diào)用beanFactory.preInstantiateSingletons()
實(shí)例化所有非懶加載的單例Bean赔退。beanFactory.preInstantiateSingletons()
則會(huì)遍歷所有的Bean并調(diào)用getBean(beanName)
方法。
下面是getBean(beanName)
方法的流程:
- 首先通過
getSingleton(beanName)
從signleton緩存池中獲取Bean - 如果獲取不到证舟,則根據(jù)當(dāng)前的beanfactory獲取父一級(jí)的beanfactory硕旗,然后逐級(jí)遞歸的查找我們需要的bean
- 獲取仍然不到則根據(jù)
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName)
拿到BeanDefinition,然后通過createBean(beanName, mbd, args)
進(jìn)行Bean的創(chuàng)建女责。 -
createBean(beanName, mbd, args)
方法調(diào)用doCreateBean(beanName, mbdToUse, args)
方法來創(chuàng)建Bean漆枚。 -
doCreateBean(beanName, mbdToUse, args)
方法主要分為四步:
(1)instanceWrapper = createBeanInstance(beanName, mbd, args)
通過反射創(chuàng)建出一個(gè)Bean實(shí)例
(2)applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName)
調(diào)用所有的MergedBeanDefinitionPostProcessor
來customize創(chuàng)建出的Bean。
(3)populateBean(beanName, mbd, instanceWrapper)
填充所有的屬性
(4)exposedObject = initializeBean(beanName, exposedObject, mbd)
調(diào)用applyBeanPostProcessorsBeforeInitialization
(即BeanPostProcessor.beforeInitialization)抵知,invokeInitMethods
(即配置文件中配置的init-method)和applyBeanPostProcessorsAfterInitialization
(即BeanPostProcessor.afterInitialization)
上文中我們提到的AutowiredAnnotationBeanPostProcessor
是一種BeanPostProcessor
(然而它的beforeInitialization和afterInitialization都為空)墙基,它還實(shí)現(xiàn)了MergedBeanDefinitionPostProcessor
接口。因此上述第(2)步會(huì)調(diào)用AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition
方法刷喜,然而這個(gè)方法并不會(huì)直接向Bean中注入所有的@Autowired屬性碘橘。下面是這個(gè)方法的實(shí)現(xiàn):
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
if (beanType != null) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
}
AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition
的作用僅僅是緩存此Bean的所有@Autowired屬性信息。
在執(zhí)行第(3)步populateBean(beanName, mbd, instanceWrapper)
時(shí)吱肌,會(huì)調(diào)用其AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues
方法痘拆,從而完成了所有@Autowired屬性的注入:
@Override
public PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeanCreationException {
InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
try {
metadata.inject(bean, beanName, pvs);
}
catch (BeanCreationException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
return pvs;
}
更多Bean初始化流程,請參考:https://www.shangyang.me/2017/04/01/spring-core-container-sourcecode-analysis-beans-instantiating-process/
4.11 finishRefresh
執(zhí)行refresh收尾工作氮墨。包括初始化LifecycleProcessor纺蛆,發(fā)布ContextRefreshedEvent事件等。其源碼如下:
protected void finishRefresh() {
// Clear context-level resource caches (such as ASM metadata from scanning).
clearResourceCaches();
// Initialize lifecycle processor for this context.
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();
// Publish the final event.
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}