Spring源码情操陶冶-AbstractApplicationContext#finishBeanFactoryInitialization
承接前文Spring源码情操陶冶-AbstractApplicationContext#registerListeners
约定web.xml
配置的contextClass
为默认值XmlWebApplicationContext
AbstractRefreshableWebApplicationContext#finishBeanFactoryInitialization()
笔者直接去查看相应的的源码
/**
* Finish the initialization of this context's bean factory,
* initializing all remaining singleton beans.
*/
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.我们关注此方法即可
beanFactory.preInstantiateSingletons();
}
从上述的注释可知,spring会提前初始化那些作用域为singleton类型的bean对象,当然并不包括lazy-init属性的bean对象
DefaultListableBeanFactory#preInstantiateSingletons()
具体实现preInstantiateSingletons()方法便只有DefaultListableBeanFactory类,直接去翻阅代码
public void preInstantiateSingletons() throws BeansException {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Pre-instantiating singletons in " + this);
}
//获取解析过的所有beanNames
List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
//获取对应的RootBeanDefinition,其内部就含有BeanDefinition
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//非抽象、单例模式、非lay-init,满足以上条件的进入到实例化(默认情况下Bean为singleton单例模式)
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//对FactoryBean的类型实例化
if (isFactoryBean(beanName)) {
final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
@Override
public Boolean run() {
return ((SmartFactoryBean<?>) factory).isEagerInit();
}
}, getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
else {
//getBean方法主要进行了对相应的beanName的实例化
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames) {
//获取上述的实例化的静态对象,如果为SmartInitializingSingleton的实现类进行afterSingletonInstantiated()方法调用
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton) {
final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
smartSingleton.afterSingletonsInstantiated();
return null;
}
}, getAccessControlContext());
}
else {
//会调用InitializingBean的afterPropertiesSet()方法
smartSingleton.afterSingletonsInstantiated();
}
}
}
笔者提示这里的实例化指的是对beanFactory中beanName对应的RootBeanDefinition中的beanClass进行准确的实例化,包括属性以及方法复用等等,主要是通过DefaultListableBeanFactory#getBean()
方法,因为其很复杂,我们后续再分析
需要注意的是,默认情况下Bean对象的作用域一般为singleton,所以默认情况下bean工厂上的bean都会进行实例化。除了以下情况先不参与
1.使用@Lazy注解修饰Bean对象,指定@Lazy(value=true)2.使用@Scope注解修饰Bean对象,指定@Scope(value="prototype")
小结
主要是实例化RootDefinition中的beanClass类,并完成相应的属性设置,方法调用等等(默认情况下Bean的Scope类型为singleton单例模式)。即使当中的属性如果没有提前被初始化的话,其也会被调用
getBean()
方法来进行初始化后再被设置调用所有实现InitializingBean接口的afterPropertiesSet()方法
调用BeanPostProcessors接口,比如
postProcessBeforeInitialization()
和postProcessAfterInitialization()
实例化前后方法。其中涉及@Resource
、@Autowired
等注解的解析并进行相应的实例注入此处插一句:BeanPostProcessors接口处理,优先处理
InstantiationAwareBeanPostProcessor.class
接口实现类,一旦其内部方法postProcessBeforeInstantiation(Class,String)
执行后返回null,则不执行postProcessAfterInitialization()
方法;随后处理其他BeanPostProcessor接口的postProcessBeforeInitialization()
和postProcessAfterInitialization()
方法
附上springBean的生命周期图(含lazy-init的Bean)
上图示的第八步骤与第九步骤需要替换下,通过阅读源码发现执行InitializingBean#afterPropertiesSet()前还得优先执行BeanPostProcessors集合的postProcessBeforeInitialization()方法,也就是设置ApplicationContext以及Environment变量均在InitializingBean前
Bean销毁的触发机制:
1.实例化@Scope(value="singleton")类型的Bean对象过程中(默认),如果出现异常则会执行AbstractBeanFactory#destorySingleton()方法,当然也支持直接调用
2.在上述销毁的过程中也会去默认执行@Scope(value="prototype")类型Bean的close/destory()方法(倘若存在)
3.同样在上述的销毁过程中,如果对应的Bean对象为DisposableBean类型,则会调用destory()方法来进行销毁操作
Bean对象中指定Scope为singleton和prototype的小区别
1.前者是指定Bean对象为单例模式, 即初始化一次后便会保存在内存中,专门由相应的集合去保存;后者则是实例模式,在主动销毁以及被动被回收之后再获取的时候则会被新建
2.前者是Spring的默认模式,后者是需要用户去指定的。前者比较节省资源
3.前者进行销毁时,优先先销毁依赖此Bean的Bean集合,然后再销毁自己,最后再销毁其内含的关联Bean属性;后者想销毁要么直接调用对应的销毁方法要么就是被前者波及进行销毁
下节预告
Spring源码情操陶冶-AbstractApplicationContext#finishRefresh
Spring源码情操陶冶-AbstractApplicationContext#finishBeanFactoryInitialization的更多相关文章
- Spring源码情操陶冶-AbstractApplicationContext#registerListeners
承接前文Spring源码情操陶冶-AbstractApplicationContext#onRefresh 约定web.xml配置的contextClass为默认值XmlWebApplicationC ...
- Spring源码情操陶冶-AbstractApplicationContext#finishRefresh
承接前文Spring源码情操陶冶-AbstractApplicationContext#finishBeanFactoryInitialization 约定web.xml配置的contextClass ...
- Spring源码情操陶冶-AbstractApplicationContext#onRefresh
承接前文Spring源码情操陶冶-AbstractApplicationContext#initApplicationEventMulticaster 约定web.xml配置的contextClass ...
- Spring源码情操陶冶-AbstractApplicationContext#initApplicationEventMulticaster
承接前文Spring源码情操陶冶-AbstractApplicationContext#initMessageSource 约定web.xml配置的contextClass为默认值XmlWebAppl ...
- Spring源码情操陶冶-AbstractApplicationContext#initMessageSource
承接前文Spring源码情操陶冶-AbstractApplicationContext#registerBeanPostProcessors 约定web.xml配置的contextClass为默认值X ...
- Spring源码情操陶冶-AbstractApplicationContext#registerBeanPostProcessors
承接前文Spring源码情操陶冶-AbstractApplicationContext#invokeBeanFactoryPostProcessors 瞧瞧官方注释 /** * Instantiate ...
- Spring源码情操陶冶-AbstractApplicationContext#invokeBeanFactoryPostProcessors
阅读源码有利于陶冶情操,承接前文Spring源码情操陶冶-AbstractApplicationContext#postProcessBeanFactory 约定:web.xml中配置的context ...
- Spring源码情操陶冶-AbstractApplicationContext#postProcessBeanFactory
阅读源码有利于陶冶情操,承接前文Spring源码情操陶冶-AbstractApplicationContext#prepareBeanFactory 约定:web.xml中配置的contextClas ...
- Spring源码情操陶冶-AbstractApplicationContext#prepareBeanFactory
阅读源码有助于陶冶情操,本文承接Spring源码情操陶冶-AbstractApplicationContext#obtainFreshBeanFactory 瞧瞧官方注释 /** * Configur ...
随机推荐
- Mac 上所有的命令行相关问题的总结
1. java 系列命令 jdk,jar,war等等文件的执行方式 2. brew 系列命令 安装各种其他程序的命令例如:jenkins,MySQL,openssl brew list 列出所有的 ...
- Spring学习(19)--- Schema-based AOP(基于配置的AOP实现) --- 配置切面aspect
Spring所有的切面和通知器都必须放在一个<aop:config>内(可以配置包含多个<aop:config>元素),每个<aop:config>包含pointc ...
- Azure经典门户创建VM,如何设置使用静态IP地址?
使用 Azure 经典管理门户中创建的虚拟机,无法使用静态IP 地址,在管理界面没有该设置.在新的管理门户中虽然有使用静态IP的设置,但是选项是灰色,无法修改,提示错误:This virtual ma ...
- Ubuntu下Tomcat初始配置
1.下载tomcat安装包 从tomcat官方网站http://tomcat.apache.org下载安装包,然后解压到某个目录,比如: ~/opt/apache-tomcat-7.0.63官方文档中 ...
- Java IO学习笔记七
System对IO的支持 System是系统的类,其中的方法都是在控制台的输入和输出,但是通过重定向也是可以对文件的输入输出 System中定义了标准输入.标准输出和错误输出流,定义如下: stati ...
- Python pycrypto 加密与解密
参考: python 使用 pycrypto 实现 AES 加密解密 参考: 分组对称加密模式:ECB/CBC/CFB/OFB 代码示例 : import hashlib from Crypto.C ...
- GA代码中的细节
GA-BLX交叉-Gaussion变异 中的代码细节: 我写了一个GA的代码,在2005测试函数上一直不能得到与实验室其他同学类似的数量级的结果.现在参考其他同学的代码,发现至少有如下问题: 1.在交 ...
- ecshop加入购物车效果(各个页面)
ecshop中点击加入购物车出现下图 通过以下代码改成下图效果 1.后台网店设置 购物车确定提示 选择为“提示用户,点击“确定”进购物车” 2.打开js/common.js 104行就是funct ...
- 实现一个javascript手势库 -- base-gesture.js
现在移动端这么普及呢,我们在手机上可以操作更多了.对于网页来说实现一些丰富的操作感觉也是非常有必要的,对吧(如果你仅仅需要click,,那就当我没说咯...)~~比如实现上下,左右滑动,点击之类的,加 ...
- Vulkan Tutorial 22 Index buffer
操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 Introduction 在实际产品的运行环境中3D模型的数据往往共享多个三角形之间 ...