Spring是通过IOC容器来管理对象的,该容器不仅仅只是帮我们创建了对象那么简单,它负责了对象的整个生命周期-创建、装配、销毁。这种方式成为控制反转(组件对象控制权的转移,从程序代码本身转移到了外部容器,容器创建完对象后注入组件中)。
Spring的核心的是容器,不过这个容器并不是唯一的,框架本身就提供了很多个容器的实现,大概分为两种类型:
简单说说这两种方式的区别:
如果说BeanFactory是Sping的心脏,那么ApplicationContext就是完整的身躯了。ApplicationContext由BeanFactory派生而来,提供了更多面向实际应用的功能。在Beanfactory中,很多功能需要以编程的方式实现,而在ApplicationContext中则可以通过配置的方式实现。
在上一篇源码阅读WebContextApplication初始化中说到实际创建的对象为XmlWebApplicationContext
,该类继承了AbstractRefreshableWebApplicationContext
(上图的左下角),也是ApplicationContext体系。那么该对象读取配置文件后是如何创建bean对象的呢?
大致分为两步:
实例化BeanDefinition对象(下面分析该对象的作用) 。
实例化bean对象。
WebContextApplication初始化说到初始化的步骤是在ContextLoader
中完成,创建完XmlWebApplicationContext
对象后,通过configureAndRefreshWebApplicationContext()
设置配置文件的位置。
protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
String configLocationParam;
if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
configLocationParam = sc.getInitParameter("contextId");
if (configLocationParam != null) {
wac.setId(configLocationParam);
} else {
wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX + ObjectUtils.getDisplayString(sc.getContextPath()));
}
}
//设置ServletContext环境。
wac.setServletContext(sc);
/*读取Servlet对象中的contextConfigLocation. ServletContext在创建的时候就读取了
标签,并将该标签中的配置文件的信息通过键值对的形式保存进来了。
*/
configLocationParam = sc.getInitParameter("contextConfigLocation");
if (configLocationParam != null) {
//保存配置文件信息的位置。
wac.setConfigLocation(configLocationParam);
}
//刷新环境
wac.refresh();
}
配置文件位置设置完成后就需要读取该文件的配置信息,并创建相应的bean对象,这一过程就是在refresh()
中完成的。
通过图中的继承关系往上寻找在AbstractApplicationContext
中发现·refresh
方法,
该方法进行一些初始化操作。
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
// 1.刷新前的预处理,包含设置启动时间、设置状态...
this.prepareRefresh();
//实现刷新BeanFactory,将配置文件解析为BeanDefinition并注册到BeanFactory,此时Bean还未被初始化
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
// BeanFactory的预准备工作
this.prepareBeanFactory(beanFactory);
try {
this.postProcessBeanFactory(beanFactory);
// 执行BeanFactoryPostProcessor的方法,BeanFactory的后置处理器
// 在BeanFactory标准初始化之后执行的
this.invokeBeanFactoryPostProcessors(beanFactory);
// 注册BeanPostProcessor(Bean的后置处理器),用于拦截bean创建过程
this.registerBeanPostProcessors(beanFactory);
// 初始化MessageSource组件(做国际化功能;消息绑定,消息解析).
this.initMessageSource();
// 初始化上下文的事件机制
this.initApplicationEventMulticaster();
// 可以用于子类实现在容器刷新时自定义逻辑初始化
this.onRefresh();
// 注册时间监听器,将ApplicationListener注册到容器中来
this.registerListeners();
// 初始化所有剩下的单实例bean,单例bean在初始化容器时创建。
this.finishBeanFactoryInitialization(beanFactory);
// 发布完成事件,结束初始化过程
this.finishRefresh();
} catch (BeansException var5) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt", var5);
this.destroyBeans();
this.cancelRefresh(var5);
throw var5;
}
}
}
obtainFreshBeanFactory
将配置文件解析为BeanDefinition并注册到BeanFactory中
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
// 主要是通过该方法完成IoC容器的刷新
this.refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
if (this.logger.isDebugEnabled()) {
this.logger.debug("Bean factory for " + this.getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
refreshBeanFactory
完成IOC容器的刷新,具体实现是在AbstractRefreshableApplicationContext
中,实际创建的的IOC容器为:DefaultListableBeanFactory
protected final void refreshBeanFactory() throws BeansException {
//首先检查是否已经有beanFactory了,有就销毁
if (this.hasBeanFactory()) {
this.destroyBeans();
this.closeBeanFactory();
}
try {
// 创建IoC容器,也就是DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = this.createBeanFactory();
beanFactory.setSerializationId(this.getId());
this.customizeBeanFactory(beanFactory);
//载入刚创建的IOC容器,具体实现在子类XmlWebApplicationCpntext中
this.loadBeanDefinitions(beanFactory);
synchronized(this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
} catch (IOException var5) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
}
}
loadBeanDefinitions
装载刚创建的IOC容器,具体实现在XmlWebApplicationCpntext
中。
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// 创建一个BeanDefinition阅读器,通过阅读XML文件,真正完成BeanDefinition的加载和注册
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
//beanDefinitionReaderde 初始化操作
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
this.initBeanDefinitionReader(beanDefinitionReader);
this.loadBeanDefinitions(beanDefinitionReader);
}
//方法重载
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
/*在上一篇文章中ContextLoader中的configureAndRefreshWebApplicationContext方法有这一段代码
configLocationParam = sc.getInitParameter("contextConfigLocation");
if (configLocationParam != null) {
//保存配置文件信息的位置。
wac.setConfigLocation(configLocationParam);
}
这里就是读取配置文件的信息,保存进数组中。
*/
String[] configLocations = this.getConfigLocations();
if (configLocations != null) {
String[] var3 = configLocations;
int var4 = configLocations.length;
for(int var5 = 0; var5 < var4; ++var5) {
String configLocation = var3[var5];
//具体的装载方法在XmlBeanDefinitionReader
reader.loadBeanDefinitions(configLocation);
}
}
}
接下来看XmlBeanDefinitionReader
中的loadBeanDefinitions()
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
// 对配置文件进行编码处理
return this.loadBeanDefinitions(new EncodedResource(resource));
}
//截取主要代码
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
try {
//将配置文件转换成流对象
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
// 从InputStream中得到XML的解析源
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
// 这里是具体的读取过程,var5等于新注册的BeanDefintion数量
var5 = this.doLoadBeanDefinitions(inputSource, encodedResource.getResource());
} finally {
inputStream.close();
}
}
具体的读取过程在doLoadBeanDefinitions()
中,该方法的主要作用就是:
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException {
try {
//把资源文件转换成Document对象
Document doc = this.doLoadDocument(inputSource, resource);
// 通过对Document对象的操作,完成BeanDefinition的加载和注册工作
return this.registerBeanDefinitions(doc, resource);
}Catch(){
}
}
看看registerBeanDefinitions()
具体完成了哪些操作:
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
// 1.
BeanDefinitionDocumentReader documentReader = this.createBeanDefinitionDocumentReader();
documentReader.setEnvironment(this.getEnvironment());
// 2.
int countBefore = this.getRegistry().getBeanDefinitionCount();
// 3. 解析过程入口,BeanDefinitionDocumentReader只是个接口,具体的实现过程在DefaultBeanDefinitionDocumentReader完成
documentReader.registerBeanDefinitions(doc, this.createReaderContext(resource));
// 4.
return this.getRegistry().getBeanDefinitionCount() - countBefore;
}
接着看DefaultBeanDefinitionDocumentReader
中的registerBeanDefinitions()
该方法:
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
this.logger.debug("Loading bean definitions");
//获取文档对象的子节点。
Element root = doc.getDocumentElement();
//真正的解析注册方法
this.doRegisterBeanDefinitions(root);
}
到这一步接下来就是对解析文档中的每一个标签节点,获取标签中的属性。创建AbstractBeanDefinition
对象,并将标签中属性保存进对象中。具体的步骤就不展示了。
综上步骤具体完成了以下操作:
创建IoC容器(DefaultListableBeanFactory)
加载解析XML文件(最终存储到Document对象中)
读取Document对象,并完成BeanDefinition的加载和注册工作
BeanDefinition 在 spring 中贯穿始终,spring 要根据 BeanDefinition 对象来实
例化 bean,只有把解析的标签,扫描的注解类封装成 BeanDefinition 对象,spring
**才能实例化 bean **
上面的步骤只是完成了AbstractApplicationContext中refresh()
这句话(心累…)
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
进入AbstractApplicationContext
中的finishBeanFactoryInitialization()
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
beanFactory.setTempClassLoader((ClassLoader)null);
beanFactory.freezeConfiguration();
// 实例化剩余的单例bean(非懒加载方式)
// 注意事项:Bean的IoC、DI和AOP都是发生在此步骤
beanFactory.preInstantiateSingletons();
}
进入DefaultListableBeanFactory中的preInstantiateSingletons()方法:
@Override
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Pre-instantiating singletons in " + this);
}
// 得到Bean定义名称
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// 触发所有非懒加载方式的单例bean的创建
for (String beanName : beanNames) {
// 遍历得到对应的bean定义信息
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
// 如果bean不是抽象的,而且是单例的,同时还不是懒加载的,则进行下面的操作
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
// 如果bean是一个工厂bean,则走下面的方法 ,和普通bean区别就是还可以生成bean
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else { // 普通bean走下面的方法
getBean(beanName);
}
}
}
进入AbstractBeanFactory通过doGetBean()方法获取Bean的实例(只展示关键代码)
通过getSingleton(beanName)方法去缓存中获取单例Bean(第一次初始化,缓存中不存在)
如果取出来的bean实例是factoryBean的实例,则需要从factoryBean中产生一个Bean对象
根据当前的beanfactory获取父一级的beanFactory,递归查找我们需要的Bean(Bean是早不到的,第一次初始化)
获取实例化Bean的BeanDefinition对象
一般是单例Bean,用匿名内部类的写法,创建单例Bean
@Override
public Object getBean(String name) throws BeansException {
// 获取Bean的实例
return doGetBean(name, null, null, false);
}
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 获取bean名称
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
// 从缓存中获取单例bean
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) { //如果获取到单例bean,则走下面代码
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 如果取出来的Bean实例是FactoryBean的Bean实例,则需要从FactoryBean实例中产生一个对象实例。
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {//如果没有获取到单例bean,则走下面代码
try {
// 获取要实例化的bean的BeanDefinition对象
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 检查该BeanDefinition对象对应的Bean是否是抽象的
checkMergedBeanDefinition(mbd, beanName, args);
// 如果是单例的Bean,请下面的代码
if (mbd.isSingleton()) { //匿名内部类的写法
sharedInstance = getSingleton(beanName, () -> {
try {
// 创建单例Bean的主要方法
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
return (T) bean;
}
进一步看看createBean()
具体实现在AbstractAutowireCapableBeanFactory
中
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
//省略一些代码
try {
// 完成Bean实例的创建(实例化、填充属性、初始化)
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
****
doCreateBean完成Bean实例的创建(实例化、填充属性、初始化)
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
// 用BeanWrapper来持有创建出来的Bean对象
BeanWrapper instanceWrapper = null;
// 如果是单例的话,则先把缓存中的bean清除
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
// bean初始化第一步:默认调用无参构造实例化Bean
// 构造参数依赖注入,就是发生在这一步
// 为了下一步populateBean方法的属性注入做准备
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 实例化后的Bean对象
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
// 解决循环依赖的关键步骤
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
// 如果需要提前暴露单例Bean,则将该Bean放入三级缓存中
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 将刚创建的bean放入三级缓存中singleFactories(key是beanName,value是FactoryBean)
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// bean初始化第二步:填充属性(DI依赖注入发生在此步骤)
populateBean(beanName, mbd, instanceWrapper);
// bean初始化第三步:调用初始化方法,完成bean的初始化操作(AOP发生在此步骤)
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
******************************************
}
进入上面的initializeBean()方法:
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
/*判断beanName是哪个接口的的实现类
如果bean是BeanNameAware接口的实现类会调用setBeanName方法、
如果bean是BeanClassLoaderAware接口的实现类会调用setBeanClassLoader方法、
如果是BeanFactoryAware接口的实现类会调用setBeanFactory方法,注入对应的属性值。*/
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//应用BeanPostProcessor的postProcessBeforeInitialization方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//执行初始化方法(先调用InitializingBean的afterPropertiesSet,再调用init-method属性指定的初始化方法)
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
//应用BeanPostProcessor的postProcessAfterInitialization方法(AOP代理对象生成)
// AOP是等着对象创建完毕,在进行增强
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
调用初始化方法invokeInitMethods()
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
// 如果是InitializingBean接口的实现类,则先初始化InitializingBean的实现类
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isDebugEnabled()) {
logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction
在initializeBean方法中调用BeanPostProcessor的applyBeanPostProcessorsAfterInitialization方法
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
Iterator var4 = this.getBeanPostProcessors().iterator();
do {
if (!var4.hasNext()) {
return result;
}
BeanPostProcessor beanProcessor = (BeanPostProcessor)var4.next();
//bean初始化后调用
result = beanProcessor.postProcessAfterInitialization(result, beanName);
} while(result != null);
return result;
}
BeanPostProcessor是Spring IOC容器给我们提供的一个扩展接口。接口声明如下:
public interface BeanPostProcessor {
//bean初始化方法调用前被调用
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
//bean初始化方法调用后被调用
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
至此bean的初始化就完成了。
tProcessor)var4.next();
//bean初始化后调用
result = beanProcessor.postProcessAfterInitialization(result, beanName);
} while(result != null);
return result;
}
BeanPostProcessor是Spring IOC容器给我们提供的一个扩展接口。接口声明如下:
```java
public interface BeanPostProcessor {
//bean初始化方法调用前被调用
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
//bean初始化方法调用后被调用
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
至此bean的初始化就完成了。
参考:https://www.jianshu.com/p/32dacf644062 作者:GGarrett