概述
在基于Spring的应用中,应用对象生存与Spring容器中(container)。Spring容器负责创建、装配(大对象组合关联的小对象)对象,配置它们并管理它们的整个生命周期,从生存到死亡(从new 到finalize())。
Spring容器使用DI(依赖注入)管理构成应用的组件,它会创建相互协作的组件之间的关联。
Spring容器归纳为两类,bean工厂(factory.beanFactory接口定义)和应用上下文(由context.ApplicationContext接口定义)。
bean工厂是最简单的容器,提供基本的DI支持。
应用上下文基于bean工厂构建,并提供应用框架级别的服务,例如从属性文件中解析文本信息已经发布应用事件给感兴趣的事件监听者。
虽然bean工厂和应用上下文都可以使用,但是bean工厂对大多数应用都太低级了,因此,应用上下文比bean工厂更受欢迎。
bean的生命周期
- Spring对bean进行实例化
如何实例化,通过单列模式实例化么? - Spring将值和bean中关联的其他bean的引用注入到对应的属性中。
bean对象初始化。 - 如果bean实现了beanNameAware接口,Spring将bean的ID传递给setBeanName()方法。
- 如bean实现了BeanFactoryAware接口,Spring将调用setBeanFactory()方法,将beanFactory容器实例传入。
- 如果bean实现了ApplicationContextAware接口,Spring将调用setApplicationContext()方法,将bean所在的应用上下文的引用传进来。
- 如果bean实现了BeanPostProcessor接口,Spring将调用它们的postProcessBeforeInitialization()方法。
- 如果bean实现了InitializingBean接口,Spring将调用它们的afterPropertiesSet()方法。类似地,如果bean使用init-method声明了初始化方法,该方法也会被调用。
- 如果bean实现了BeanPostProcessor接口,Spring将调用它们的postProcessAfterInitialization()方法。
- 此时,bean已经准备就绪,可以被应用程序应用了,它们将一直驻留在应用上下文中,直到该应用上下文被销毁。
- 如果bean实现了DisposableBean接口,Spring将调用它们的destroy()接口方法。同样,如果bean使用destroy-method声明了销毁方法,该方法也会被调用。
Spring容器关系
BeanFactory和ApplicationContext都属于Spring的容器。
BeanFactory:定义了最基本的容器设计规范,如果getBean(),containBean(),getType()等基本方法。
ApplicationContext:继承BeanFactory,同时又继承了MessageSource(支持不同的信息源),ResourceLoader(访问资源),ApplicationEventPublisher(支持应用事件)。
容器初始化
容器初始化主要通过refresh()方法完成。
public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
super(parent);
this.setConfigLocations(configLocations);
if (refresh) {
this.refresh();
}
}
public void refresh() throws BeansException, IllegalStateException {
Object var1 = this.startupShutdownMonitor;
synchronized(this.startupShutdownMonitor) {
// 准备被刷新的应用上下文,容器初始化的一些准备工作
this.prepareRefresh();
// 通知该类的子类去刷新内部bean工厂。
// 告知子类初始化BeanFactory,其中BeanDefinition信息的读取是在子类的
// refreshBeanFactory()方法里完成的
// bean的解析注册,生成beanDefinition
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
// 为应用上下文准备bean工厂
this.prepareBeanFactory(beanFactory);
try {
// 设置beanFactory的后置处理
this.postProcessBeanFactory(beanFactory);
// 调用beanFactory的后置处理
this.invokeBeanFactoryPostProcessors(beanFactory);
// 注册beanFactory的后置处理
this.registerBeanPostProcessors(beanFactory);
// 初始化上下文的消息
this.initMessageSource();
// 初始化上下文的事件
this.initApplicationEventMulticaster();
// 初始化一些特殊的bean
this.onRefresh();
// 检查一些监听的bean并注册到容器中
this.registerListeners();
// 初始化非懒加载的bean
this.finishBeanFactoryInitialization(beanFactory);
// 发布容器事件,结束Refesh过程
this.finishRefresh();
} catch (BeansException var9) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}
this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}
}
}
prepareRefresh()方法
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (this.logger.isInfoEnabled()) {
this.logger.info("Refreshing " + this);
}
this.initPropertySources();
this.getEnvironment().validateRequiredProperties();
this.earlyApplicationEvents = new LinkedHashSet();
}
设置Spring上下文的刷新时间,并将active设为true,初始化一些容器启动必要的资源。
obtainFreshBeanFactory()方法
总结:obtainFreshBeanFactory()方法,是进行bean的解析注册的地方。
所谓的bean的解析注册就是指将xml,java config中的配置的bean,转化为Java对象的BeanDefinition,并将它们保存在容器的Map里。返回的beanFacotry里面,就携带着存放beanName和BeanDefiniton的map。这个方法执行完成后,存放的beanName和实例化bean的对象的singleObjections仍然为空。
详情
- obtainFreshBeanFactory()里面的refreshBeanFactory()来完成beanDefinition的生成和注册。
- 注册:将抽象好的beanDefiniton统一注册到IOC容器中,IOC容器是通过ConcurrentHashMap<String,BeanDefinition> 来维护的,Key为beanName,value为BeanDefiniton。
finshBeanInitialization(beanFactory)
这个方法里面,用来初始化非懒加载的单列bean。并非所有bean都在容器初始化,如果lazy-init属性为true就不在容器初始化生成,默认lazy-init为false。
所以默认情况下,单列的非懒加载的bean在容器启动的时候就会实例化。如果懒加载的,那么在getBean的时候,在实例化。
bean实例化
Spring什么时候实例化bean,首先要分两种情况。
BeanFactory作为Spring容器
如果使用BeanFactory作为Spring Bean的工厂类,则所有的bean都在第一次使用该bean时实例化bean。
ApplicationContext作为Spring容器
- 如果bean是singleton的,并且lazy-init为false,则ApplicationContext启动的时候就实例化该Bean,并将实例化的Bean存放在一个ConcurrentHashMap容器中。
- 如果bean的scope是singleton的,并且lazy-init为true,则bean的实例化在第一次使用该bean的时候。
- 如果bean的scope是prototype的,则该Bean的实例化在第一次使用的时候。
容器初始化大体流程
参考
https://blog.csdn.net/qq_39632561/article/details/83070140
https://www.jianshu.com/p/70886997c46b
https://blog.csdn.net/weililansehudiefei/article/details/74178427
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/100372.html