继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Spring创建Bean的顺序

西昆仑
关注TA
已关注
手记 7
粉丝 492
获赞 43

一直对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......


打开App,阅读手记
3人推荐
发表评论
随时随地看视频慕课网APP

热门评论

听了老师的课关注了老师,没想到还有干货手记,希望老师能多分享一些干货

听了老师的课关注了老师,没想到还有干货手记,希望老师能多分享一些干货

在看mybatis缓存的课程,非常喜欢您的这种源码谅解方式

查看全部评论