1. 程式人生 > >Spring創建Bean的順序

Spring創建Bean的順序

XML col 通過 分享 -o 信息 pattern 依賴關系 str

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

Spring創建Bean的順序