spring父子容器
spring總的上下文容器有父子之分傅蹂,父容器和子容器纷闺。** 父容器對子容器可見算凿,子容器對父容器不可見 **。
對于傳統(tǒng)的spring mvc來說犁功,spring mvc容器為子容器氓轰,也就是說ServletDispatcher對應(yīng)的容器為子容器,而web.xml中通過ConextLoaderListener的contextConfigLocation屬性配置的為父容器浸卦。
父子容器的使用場景
父子容器的主要用途是上下文隔離署鸡。考慮以下一種場景镐躲。
- project-service.jar為服務(wù)層模塊储玫。包含一些數(shù)據(jù)庫service方法。其對應(yīng)的spring配置文件為project-service.xml萤皂。
- project-api為api服務(wù)器代碼撒穷。它依賴于project-service.jar。其對應(yīng)的配置文件為project-api.xml裆熙。
project-api需要對project-service里的某些方法進(jìn)行decorate端礼,進(jìn)行裝飾,比如給CustomerService進(jìn)行裝飾入录。裝飾后的類為CachedCustomerService蛤奥。于是,現(xiàn)在project-api里面包含兩個CustomerService僚稿,一個是來自project-service的CustomerService凡桥,另一個是CachedCustomerService。這個時候蚀同,如果project-api工程所有的配置文件都通過一個上下文進(jìn)行加載缅刽,勢必出現(xiàn)問題(通常的做法是用import標(biāo)簽全部給import進(jìn)來)。因為蠢络,project里的PayService里通過@Resource標(biāo)準(zhǔn)注入了CustomerService衰猛,類似如下
@Serivce
public class PayService{
@Resource
private CustomerService cusService;
}
解決方式
這時,由于上下文在注入customerService屬性的時候刹孔,遇到了兩個CustomService啡省。它無法判讀注入哪個Service。
當(dāng)然了髓霞,有人會說卦睹,改一下PayService的Resource屬性,指定下具體注入哪個酸茴。但是分预,project-service.jar是第三方庫的話,改動代碼變得不可行薪捍,除非拿到源碼笼痹。
這個時候配喳,就可以通過父子容器的方式解決這個問題。
將project-service放在父容器中凳干,project-api所有的bean用子容器加載晴裹。
假設(shè)project-api的上下文配置文件為project-api.xml,實現(xiàn)方法如下救赐。
1涧团、定義project-total.xml
<bean id = "serviceContext" class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg>
<value>
classpath:project-service.xml
</value>
</constructor-arg>
</bean>
<bean id = "apiContext" class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg>
<value>
classpath:project-api.xml
</value>
</constructor-arg>
<constructor-arg>
<ref bean="serviceContext"/>
</constructor-arg>
</bean>
2、在web.xml的上下文配置中如下经磅。
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value> classpath*:project-total.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
serviceContext為父容器,apiContext為子容器泌绣,從而實現(xiàn)serviceContext看不到apiContext,而apiContext可以看見serviceContext的效果预厌。