一个Spring框架的应用中会有涉及到多个bean,各种各样配置形式的bean。 这些bean是按照什么顺序加载的?
如果在执行一些初始化或者其他操作时需要依赖这些bean的执行顺序,那么就得对这些bean的加载顺序有所了解。
网上查阅相关资料转发如下:
总结性话语见:http://wolfdream.iteye.com/blog/1172821
spring加载Bean顺序【转】
一,单一Bean
- 装载
1. 实例化;
2. 设置属性值;
3. 如果实现了BeanNameAware接口,调用setBeanName设置Bean的ID或者Name;
4. 如果实现BeanFactoryAware接口,调用setBeanFactory 设置BeanFactory;
5. 如果实现ApplicationContextAware,调用setApplicationContext设置ApplicationContext
6. 调用BeanPostProcessor的预先初始化方法;
7. 调用InitializingBean的afterPropertiesSet()方法;
8. 调用定制init-method方法;
9. 调用BeanPostProcessor的后初始化方法;
- spring容器关闭
1. 调用DisposableBean的destroy();
2. 调用定制的destroy-method方法;
二,多个Bean的先后顺序
- 优先加载BeanPostProcessor的实现Bean
- 按Bean文件和Bean的定义顺序按bean的装载顺序(即使加载多个spring文件时存在id覆盖)
- “设置属性值”(第2步)时,遇到ref,则在“实例化”(第1步)之后先加载ref的id对应的bean
- AbstractFactoryBean的子类,在第6步之后,会调用createInstance方法,之后会调用getObjectType方法
- BeanFactoryUtils类也会改变Bean的加载顺序
以下内容转自:http://blog.csdn.net/sky_ground/article/details/63688397
解答以下疑惑:
- Spring配置文件里bean,究竟是按什么样的顺序加载呢?
- Spring项目在部署时,究竟创建了多少个beanFactory呢?按什么顺序创建?
长话短说,总结成如下几点:
Rule1:
首先读取WEB-INF/web.xml文件,该文件内一般会配置spring-config和spring-mvc。按顺序加载对应的xml文件。
Rule2:
若web.xml中还有除springmvc和默认的servlet之外的servlet(如servlet-test),那么这些servlet会按照定义的顺序执行,但一定是在默认servlet之后,springmvc之前执行,并且,若这些servlet都会分别对应一个ApplicationContext,当然也意味着分别拥有一个beanFactory。这些ApplicationContext(包括springmvc的那个),他们的parent ApplicationContext均是默认servlet对应的那个ApplicationContext(Root ApplicationContext)。
因此,若springmvc里的某个Controller尝试通过auto wire注解来注入servlet-test里面的service,那么在运行时会抛出”Could not autowire field …”异常,因为spring从springmvc那个servlet中的beanFactory(包括其父beanFactory)中找不到对应的bean。
Rule3:
在加载某个包含bean的xml文件时,按照bean的类型1)BeanFactoryPostProcessor类的bean;2)BeanPostProcessor类的bean;3)普通bean,包括import进来的(bean标签和scan标签指定的);的顺序进行加载。同类型的bean按照定义顺序加载。所有bean默认是单例的。
因此,对于BeanFactoryPostProcessor和BeanPostProcessor类型的bean,即使被放置在最后面,也会先加载哦。这种设计还是挺人性化的^_^
Rule4:
component-scan生成的bean的默认id是类名(首字母小写),例如testService1。
<bean>标签生成的bean的默认id是: 包名.类名#数字,例如qk.spring.beanFactory.service1.TestService1#0
如果component-scan和bean标签生成的bean有冲突(即bean的id相同),并且都是单例(默认是单例),那么不会重复创建,只保留最先创建出来的那个。