• 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

  • 相关阅读:
    String.Format( )用法
    Androidstudio中添加jar包的方法
    Qt SQLite 批量插入优化(SQLite默认将每条语句看成单独的事务)good
    aravel 之父 Taylor Otwell :我是如何工作的
    【码云周刊第 22 期】GO :互联网时代的 C 语言!
    2017 JavaScript 开发者的学习图谱
    【码云周刊第 29 期】构建高性能微服务架构
    SOA和微服务
    NET Core Web 应用部署到 Docker 中运行
    Expression Trees
  • 原文地址:https://www.cnblogs.com/kevin-yuan/p/6404702.html
Copyright © 2020-2023  润新知