Spring父容器與子容器


在使用spring+springMVC的web工程中,我們一般會在web.xml中做如下配置:

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:application.xml</param-value>
    </context-param>

    <!-- spring context listener -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- spring mvc dispatcher servlet -->
    <servlet>
        <servlet-name>spring</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>spring</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

這樣就會產生兩個spring容器,一個父容器,一個子容器。

父容器Root WebApplicationContext由ContextLoaderListener加載
子容器WebApplicationContext for namespace 'spring-servlet'由DispatcherServlet加載('spring-servlet'子容器的contextConfigLocation,web.xml中配置的)
從容器里面getBean的時候,先從本容器取,如果取不到再從父容器取

 

原碼跟蹤得到如下結果:

ContextLoaderListener:
beanFactory : org.springframework.beans.factory.support.DefaultListableBeanFactory@501af69e: defining beans [commonService,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,propertyConfigurer,messageSource,exceptionHandler,compositeFilter,dataSource,sqlSessionFactory,transactionManager,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor,org.mybatis.spring.mapper.MapperScannerConfigurer#0,tokenClient,formTokenManager,formTokenAspect,formTokenPointCut,org.springframework.aop.aspectj.AspectJPointcutAdvisor#0,responseAspect,responsePointCut,org.springframework.aop.aspectj.AspectJPointcutAdvisor#1,multiViewResolver,excelView]; root of factory hierarchy

applicationContext:(對象地址:6be04fe1,父容器:null)
(org.springframework.web.context.support.XmlWebApplicationContext@6be04fe1) Root WebApplicationContext: startup date [Thu Feb 16 09:42:54 CST 2017]; root of context hierarchy
contextId : org.springframework.web.context.WebApplicationContext:


beanFactory.registerResolvableDependency(ApplicationContext.class, this);將父容器(根容器)注冊到父容器的beanFactory中

 

DispatcherServlet:
ServletContext : org.apache.catalina.core.ApplicationContextFacade@78d9af50
applicationContext : ( 對象地址:8323ee8,父容器:ContextLoaderListener加載的 applicationContext,即 Root WebApplicationContext)
(org.springframework.web.context.support.XmlWebApplicationContext@8323ee8) WebApplicationContext for namespace 'spring-servlet': startup date [Thu Jan 01 08:00:00 CST 1970]; parent: Root WebApplicationContext
contextId : org.springframework.web.context.WebApplicationContext:/spring

beanFactory.registerResolvableDependency(ApplicationContext.class, this); 將子容器注冊到子容器的beanFactory中

 

 

父容器的ListableBeanFactory中注冊的bean:(由ContextLoadListener初始化的容器)

(java.lang.String[]) [commonService
initService
pageService
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
propertyConfigurer
messageSource
exceptionHandler
compositeFilter
dataSource
sqlSessionFactory
transactionManager
org.springframework.aop.config.internalAutoProxyCreator
org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0
org.springframework.transaction.interceptor.TransactionInterceptor#0
org.springframework.transaction.config.internalTransactionAdvisor
org.mybatis.spring.mapper.MapperScannerConfigurer#0
tokenClient
formTokenManager
formTokenAspect
formTokenPointCut
org.springframework.aop.aspectj.AspectJPointcutAdvisor#0
responseAspect
responsePointCut
org.springframework.aop.aspectj.AspectJPointcutAdvisor#1
multiViewResolver
excelView
org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor
org.springframework.context.annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor
ICommonDao
IPageDao]

 

子容器的ListableBeanFactory中注冊的bean:(由DispatcherServlet初始化的容器)

(java.lang.String[]) [baseTestController
captchaController
errorPageTestController
excelExportController
exceptionHandlerTestController
paramProcessController
tokenTestController
validatorTestController
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.aop.config.internalAutoProxyCreator
mvcContentNegotiationManager
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#0
org.springframework.format.support.FormattingConversionServiceFactoryBean#0
org.springframework.validation.beanvalidation.OptionalValidatorFactoryBean#0
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#0
mvcUriComponentsContributor
org.springframework.web.servlet.handler.MappedInterceptor#0
org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver#0
org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver#0
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver#0
org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter
org.springframework.web.servlet.resource.DefaultServletHttpRequestHandler#0
org.springframework.web.servlet.handler.SimpleUrlHandlerMapping#0
org.springframework.web.servlet.view.InternalResourceViewResolver#0]

 

 

補充:bean中如果依賴注入了ApplicationContext,那么這個bean中注入的容器為持有這個bean的容器

web工程,web.xml配置如上
application.xml加載除了Controller之外的bean

<!-- 加載@Component, @Service, @Repository -->
    <context:component-scan base-package="com.cn.kvn.usage">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
    </context:component-scan>
View Code

spring-servlet.xml加載Controller bean

<!-- 加載@Controller -->
    <context:component-scan base-package="com.cn.kvn.usage.controller" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
    </context:component-scan>
View Code

那么在Controller bean中注入ApplicationContext拿到的是子容器,而在Service bean中注入ApplicationContext拿到的是父容器

@Controller
@RequestMapping("/base")
public class BaseTestController {
    
    @Resource
    ApplicationContext applicationContext;
    
    ......
}


@Service
public class CommonService implements ICommonService{

    @Resource
    ApplicationContext applicationContext;
    
    .......
}

 

斷點跟蹤,在Display窗口中打出的信息如下:

this
(org.springframework.web.context.support.XmlWebApplicationContext) Root WebApplicationContext: startup date [Thu Feb 16 13:50:53 CST 2017]; root of context hierarchy

org.springframework.util.ObjectUtils.getIdentityHexString(this)
(java.lang.String) 11667308 // 父容器的地址

this
(org.springframework.web.context.support.XmlWebApplicationContext) WebApplicationContext for namespace 'spring-servlet': startup date [Thu Feb 16 13:53:47 CST 2017]; parent: Root WebApplicationContext

org.springframework.util.ObjectUtils.getIdentityHexString(this)
(java.lang.String) 3be4f169 // 子容器的地址

applicationContext
(org.springframework.web.context.support.XmlWebApplicationContext) WebApplicationContext for namespace 'spring-servlet': startup date [Thu Feb 16 13:53:47 CST 2017]; parent: Root WebApplicationContext
org.springframework.util.ObjectUtils.getIdentityHexString(applicationContext)
(java.lang.String) 3be4f169 // Controller 中注入的ApplicationContext

applicationContext
(org.springframework.web.context.support.XmlWebApplicationContext) Root WebApplicationContext: startup date [Thu Feb 16 13:50:53 CST 2017]; root of context hierarchy
org.springframework.util.ObjectUtils.getIdentityHexString(applicationContext)
(java.lang.String) 11667308 // Service 中注入的ApplicationContext


免責聲明!

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



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