IOC(Inversion of Control),即控制反转,是面向对象编程中的一种设计原则,可以用来减低代码之间的耦合度。在Spring中,IOC意味着对象和资源的创建和获取统一交给了容器,由容器控制对象的生命周期和对象间的依赖关系。
而DI(Dependency Injection),即依赖注入,是实现IOC的一种手段。DI意味着组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。
要理解Spring IOC的实现,首先需要了解下面两个接口:BeanFactory和ApplicationContext。
1. BeanFactory
BeanFactory是Spring中的Bean工厂, 用于Spring中Bean的生命周期管理。它的主要接口如下:
public interface BeanFactory {
/*
* 四个不同形式的getBean方法,获取实例
*/
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;// 是否为原型(多实例)
boolean isTypeMatch(String name, Class<?> targetType)
throws NoSuchBeanDefinitionException;// 名称、类型是否匹配
Class<?> getType(String name) throws NoSuchBeanDefinitionException; // 获取类型
String[] getAliases(String name);// 根据实例的名字获取实例的别名
//......
}
2. ApplicationContext
ApplicationContext是BeanFactory的子接口,在拥有所有BeanFactory功能的基础上,它还继承了一些其他接口:
因此,ApplicationContext拥有一些高阶功能,例如:
- HierarchicalBeanFactory 是一个具有层级关系的 BeanFactory,拥有属性 parentBeanFactory。ListableBeanFactory 实现了枚举方法可以列举出当前 BeanFactory 中所有的 bean 对象而不必根据 name 一个一个的获取。
- MessageSource接口提供国际化功能
- ApplicationEventPublisher提供事件发布订阅功能
- ResourceLoader提供资源加载功能
- EnvironmentCapable用于获取 Environment 的功能
ApplicationContext常用实现类包括:ClassPathXMLApplicationContext, FileSystemXmlApplicationContext,AnnotationConfigApplicationContext和WebApplicationContext。
3. 容器入口
我们以ClassPathXmlApplicationContext为例,下面是其构造函数:
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
Spring首先读取Config文件位置,然后调用refresh方法进行BeanFactory的构建。
4. 容器构建流程
下面是AbstractApplicationContext
中refresh方法的实现:
public void refresh() throws BeansException, IllegalStateException {
// refresh过程只能一个线程处理,不允许并发执行
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
执行一些初始化操作,包括记录当前时间,初始化变量等。其源码如下:
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
创建一个BeanFactory。此方法会调用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方法的主要流程如下:
- 若已经存在beanFactory,销毁它
- 创建新的beanFactory(new DefaultListableBeanFactory(getInternalParentBeanFactory()))
- 通过
customizeBeanFactory
定制BeanFactory的属性; - 加载BeanDefinition到当前BeanFactory中(对于ClassPathXmlApplicationContext来说,会调用XmlBeanDefinitionReader读取所有的Bean定义,封装为BeanDefinition注册到BeanFactory中);
ApplicationContext实现了BeanFactory接口,其内部是通过聚合一个DefaultListableBeanFactory来实现所有的BeanFactory功能的。
下面时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
中维护了一个Map用于存储所有的BeanDefinition:
/** Map of bean definition objects, keyed by bean name */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
另外,DefaultSingletonBeanRegistry
(DefaultListableBeanFactory
的父类)中维护了一个Map用于存储所有的Bean:
/** Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
4.3 prepareBeanFactory
在BeanFactory已经创建成功后,Spring会调用prepareBeanFactory(beanFactory)
来向已经创建的BeanFactory注册一些特定的Bean,包括environment
等:
// 如果没有定义 "environment" 这个 bean,那么 Spring 会 "手动" 注册一个
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
// 如果没有定义 "systemProperties" 这个 bean,那么 Spring 会 "手动" 注册一个
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
// 如果没有定义 "systemEnvironment" 这个 bean,那么 Spring 会 "手动" 注册一个
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
另外,还会注册一些BeanPostProcessor,包括ApplicationContextAwareProcessor
,ApplicationListenerDetector
等:
// 添加一个 BeanPostProcessor,这个 processor 比较简单,
// 实现了 Aware 接口的几个特殊的 beans 在初始化的时候,这个 processor 负责回调
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
// 这个 BeanPostProcessor 也很简单,在 bean 实例化后,如果是 ApplicationListener 的子类,
// 那么将其添加到 listener 列表中,可以理解成:注册事件监听器
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
4.3 postProcessBeanFactory
在BeanFactory基本完成后,Spring调用postProcessBeanFactory(beanFactory)
来进行后续的针对BeanFactory的操作。AbstractApplicationContext
中的默认实现为空。而其子类AnnotationConfigEmbeddedWebApplicationContext
对应的postProcessBeanFactory
方法则会扫描basePackage下的bean并注册到BeanFactory中。
4.4 invokeBeanFactoryPostProcessors
在BeanFactory创建完毕后,Spring调用invokeBeanFactoryPostProcessors(beanFactory)
来运行所有已经注册的BeanFactoryPostProcessor,从而进行修改BeanFactory或修改BeanFactory中已经存在的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
用于读取所有已经注册的Configuration类型的Bean,然后注入Configuration类中定义的Bean,最后判断该Configuration是否拥有ComponentScan
注解,如果拥有则扫描basePackage下的所有bean并注册到BeanFactory中。
如果spring配置文件中包含了<context:annotation-config/> 或 <context:component-scan/>,spring则会自动启用
ConfigurationClassPostProcessor
。
invokeBeanFactoryPostProcessors(beanFactory)
方法内部首先对所有的BeanFactoryPostProcessor
进行排序,然后依次调用。
4.5 registerBeanPostProcessors
registerBeanPostProcessors
方法会对所有BeanFactory内的BeanPostProcessor
类型的Bean进行排序,然后调用registerBeanPostProcessors
注册这些BeanPostProcessor
,最终在createBean时会依次调用这些BeanPostProcessor
来customize最终生成的Bean。BeanPostProcessor
和BeanFactoryPostProcessor
的区别在于,BeanPostProcessor
用于实例化bean后再customize bean,而BeanFactoryPostProcessor
则用于BeanFactory创建完成后customize BeanFactory。
BeanPostProcessor
接口如下:
public interface BeanPostProcessor {
// inti方法调用之前的操作
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
// init方法调用之后的操作
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
BeanPostProcessor调用时bean已经被实例化,并且所有该注入的属性都已经被注入,是一个完整的Bean。下面是postProcessBeforeInitialization
和postProcessAfterInitialization
的调用时间:
- 在Bean实例化完成后调用
BeanPostProcessor.postProcessBeforeInitialization
- 如果Bean实现了InitializingBean接口,则调用
InitializingBean.afterPropertiesSet
方法 - 如果Bean中配置了init-method,则调用init-method
- 调用
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
用于调用Bean的Aware的接口(包括ApplicationContextAware,MessageSourceAware,ApplicationEventPublisherAware等)。例如如果Bean实现了ApplicationContextAware
接口,在Bean实例化结束后,会调用ApplicationContextAware
接口的setApplicationContext(ApplicationContext applicationContext)
方法来cutomize实例化后的Bean。
ApplicationListenerDetector
用于如果Bean实现了ApplicationListener
接口,那么它会将这个Bean加入ApplicationEventMulticaster的listener列表中。
AutowiredAnnotationBeanPostProcessor
用于注入所有使用了@Autowired注解的属性。
4.6 initMessageSource
MessageSource是Spring提供国际化的接口。ApplicationContext实现了MessageSource接口,其内部是通过聚合一个MessageSource对象来实现的。initMessageSource
方法主要是为了初始化ApplicationContext内部的MessageSource对象。如果BeanFactory中存在一个MessageSource Bean,那么直接将这个Bean赋值给ApplicationContext内部的MessageSource对象。如果没有,则会构造一个new DelegatingMessageSource()
对象。
4.7 initApplicationEventMulticaster
initApplicationEventMulticaster
顾名思义,是为了初始化ApplicationEventMulticaster
。ApplicationContext实现了ApplicationEventPublisher
接口,从而具备了事件发布功能。其内部是通过聚合一个ApplicationEventMulticaster
实现的。下面是初始化代码:
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中存在一个名为applicationEventMulticaster
的对象,则将其赋值给内部的this.applicationEventMulticaster
。否则,直接通过new SimpleApplicationEventMulticaster(beanFactory)
实例化一个ApplicationEventMulticaster。之后ApplicationContext所有事件发布功能都会转交给内部的applicationEventMulticaster对象。
ApplicationEventMulticaster主要负责事件的发布和监听者的注册。主要接口如下:
// 注册监听者
void addApplicationListener(ApplicationListener<?> listener);
//发布事件
void multicastEvent(ApplicationEvent event);
//......
ApplicationEventMulticaster的实现类内部拥有一个Set<ApplicationListener<?>> applicationListeners
监听者集合。在扫描出所有实现了ApplicationListener接口的类后,通过以下方法创建一个ApplicationListener<?>
对象,然后添加到Set<ApplicationListener<?>> applicationListeners
监听者集合中。
public ApplicationListener<?> createApplicationListener(String beanName, Class<?> type, Method method) {
return new ApplicationListenerMethodAdapter(beanName, type, method);
}
4.8 onRefresh
扩展方法,由子类实现用于初始化其他的特殊Bean。AbstractApplicationContext
默认实现为空。
4.9 registerListeners
注册事件监听器。将BeanFactory中存在的ApplicationListener类型的Bean注册到ApplicationContext内部的ApplicationEventMulticaster中。
4.10 finishBeanFactoryInitialization
通过调用beanFactory.preInstantiateSingletons()
实例化所有非懒加载的单例Bean。beanFactory.preInstantiateSingletons()
则会遍历所有的Bean并调用getBean(beanName)
方法。
下面是getBean(beanName)
方法的流程:
- 首先通过
getSingleton(beanName)
从signleton缓存池中获取Bean - 如果获取不到,则根据当前的beanfactory获取父一级的beanfactory,然后逐级递归的查找我们需要的bean
- 获取仍然不到则根据
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName)
拿到BeanDefinition,然后通过createBean(beanName, mbd, args)
进行Bean的创建。 -
createBean(beanName, mbd, args)
方法调用doCreateBean(beanName, mbdToUse, args)
方法来创建Bean。 -
doCreateBean(beanName, mbdToUse, args)
方法主要分为四步:
(1)instanceWrapper = createBeanInstance(beanName, mbd, args)
通过反射创建出一个Bean实例
(2)applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName)
调用所有的MergedBeanDefinitionPostProcessor
来customize创建出的Bean。
(3)populateBean(beanName, mbd, instanceWrapper)
填充所有的属性
(4)exposedObject = initializeBean(beanName, exposedObject, mbd)
调用applyBeanPostProcessorsBeforeInitialization
(即BeanPostProcessor.beforeInitialization),invokeInitMethods
(即配置文件中配置的init-method)和applyBeanPostProcessorsAfterInitialization
(即BeanPostProcessor.afterInitialization)
上文中我们提到的AutowiredAnnotationBeanPostProcessor
是一种BeanPostProcessor
(然而它的beforeInitialization和afterInitialization都为空),它还实现了MergedBeanDefinitionPostProcessor
接口。因此上述第(2)步会调用AutowiredAnnotationBeanPostProcessor.postProcessMergedBeanDefinition
方法,然而这个方法并不会直接向Bean中注入所有的@Autowired属性。下面是这个方法的实现:
@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属性信息。
在执行第(3)步populateBean(beanName, mbd, instanceWrapper)
时,会调用其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
执行refresh收尾工作。包括初始化LifecycleProcessor,发布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);
}