Spring創建Bean的順序


一直對Spring創建bean的順序很好奇,現在總算有時間寫個代碼測試一下。不想看過程的小伙伴可以直接看結論

目錄結構:

其中: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會被優先創建。但是如果存在相互依賴的情況,則會發生異常。

例如:

@Component
public 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");
    }
}
@Component
public 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......

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM