为了账号安全,请及时绑定邮箱和手机立即绑定

Spring创建Bean的顺序

标签:
Java Spring

一直对Spring创建bean的顺序很好奇,现在总算有时间写个代码测试一下。不想看过程的小伙伴可以直接看结论

目录结构:

5cea0822000124c103170467.jpg

其中:bean4、bean5包下的class没有注解@Component,测试过程中,这两个包的class会直接通过<bean class="XXXXX"/>的方式创建。bean1、bean2、bean3包下的class注解了@Component,以便component-scan扫描。另外,bean创建之间没有依赖关系,例如bean1的创建不依赖于其他bean。

applicationContext1.xml

<bean class="com.luych.test.springBeanCreateOrderTest.bean5.Bean5_2"/>
<context:component-scan base-package="com.luych.test.springBeanCreateOrderTest.bean2" />
<bean class="com.luych.test.springBeanCreateOrderTest.bean5.Bean5_1"/>

applicationContext2.xml

<bean class="com.luych.test.springBeanCreateOrderTest.bean4.Bean4_1"/>
<context:component-scan base-package="com.luych.test.springBeanCreateOrderTest.bean1" />
<bean class="com.luych.test.springBeanCreateOrderTest.bean4.Bean4_2"/>

springMVC-servlet.xml

<context:component-scan base-package="com.luych.test.springBeanCreateOrderTest.bean3" />

web.xml

<servlet>
    <servlet-name>springMVC</servlet-name>    
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>    
    <init-param> 
           <param-name>contextConfigLocation</param-name>        
           <param-value>classpath*:springMVC-servlet.xml</param-value>    
     </init-param>
     <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
     <servlet-name>springMVC</servlet-name>    
     <url-pattern>/</url-pattern>
 </servlet-mapping>
 <listener>
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>
 <context-param>
     <param-name>contextConfigLocation</param-name>    
     <param-value>
             classpath*:applicationContext*.xml    
     </param-value>
 </context-param>

 运行结果

class com.luych.test.springBeanCreateOrderTest.bean5.Bean5_2 has been created
class com.luych.test.springBeanCreateOrderTest.bean2.Bean2_1 has been created
class com.luych.test.springBeanCreateOrderTest.bean2.Bean2_2 has been created
class com.luych.test.springBeanCreateOrderTest.bean5.Bean5_1 has been created
class com.luych.test.springBeanCreateOrderTest.bean4.Bean4_1 has been created
class com.luych.test.springBeanCreateOrderTest.bean1.Bean1_1 has been created
class com.luych.test.springBeanCreateOrderTest.bean1.Bean1_2 has been created
class com.luych.test.springBeanCreateOrderTest.bean4.Bean4_2 has been created
class com.luych.test.springBeanCreateOrderTest.bean3.Bean3_1 has been created
class com.luych.test.springBeanCreateOrderTest.bean3.Bean3_2 has been created

结论一:

1. 在web.xml中,ContextLoaderListener和DispatcherServlet的书写顺序不会影响相应的xml文件加载顺序。ContextLoaderListener中的xml先加载,DispatcherServlet中的xml后加载。

2. ContextLoaderListener中如果contextConfigLocation通过模糊匹配到多个xml文件时,xml按照文件命名顺序加载。但是如果contextConfigLocation逐个指定了具体加载某个xml,则会按照其指定顺序加载。

本例中可以改为(注意下面代码中蓝色部分):

<listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>    
</listener>    
<context-param>        
        <param-name>contextConfigLocation</param-name>
        <param-value>
                    classpath*:applicationContext2.xml,classpath*:applicationContext1.xml        
        </param-value>    
</context-param>

则其加载顺序为:

class com.luych.test.springBeanCreateOrderTest.bean4.Bean4_1 has been created
class com.luych.test.springBeanCreateOrderTest.bean1.Bean1_1 has been created
class com.luych.test.springBeanCreateOrderTest.bean1.Bean1_2 has been created
class com.luych.test.springBeanCreateOrderTest.bean4.Bean4_2 has been created
class com.luych.test.springBeanCreateOrderTest.bean5.Bean5_2 has been created
class com.luych.test.springBeanCreateOrderTest.bean2.Bean2_1 has been created
class com.luych.test.springBeanCreateOrderTest.bean2.Bean2_2 has been created
class com.luych.test.springBeanCreateOrderTest.bean5.Bean5_1 has been created
class com.luych.test.springBeanCreateOrderTest.bean3.Bean3_1 has been created
class com.luych.test.springBeanCreateOrderTest.bean3.Bean3_2 has been created

3. 同一个spring的xml文件中,bean的加载顺序按照书写顺序加载

4. 通过component-scan扫描的方式加载bean,在扫描范围内按照class的命名顺序加载


以上的测试过程中,bean的创建是没有依赖关系的,那么如果bean之间的创建存在依赖关系,则被依赖的bean会被优先创建。但是如果存在相互依赖的情况,则会发生异常。

例如:

@Componentpublic class Bean2_1 {    private final Bean2_2 bean2_2;    @Autowired    public Bean2_1(Bean2_2 bean2_2) {        this.bean2_2 = bean2_2;        System.out.println(Bean2_1.class + " has been created");    }}
@Componentpublic class Bean2_2 {    private final Bean2_1 bean2_1;    @Autowired    public Bean2_2(Bean2_1 bean2_1) {        this.bean2_1 = bean2_1;        System.out.println(Bean2_2.class + " has been created");    }}

异常信息:

Error creating bean with name 'bean2_1' defined in file......


点击查看更多内容
3人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
492
获赞与收藏
43

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消