봄 가져 오기 자리

정상적인 상황에서 우리는 Spring 설정 파일에서 사용하는 <import>이 같은입니다 라벨 <import resource="other-beans.xml">. 우리가 구성 파일을 기반으로 스프링 빈 구성 파일의 동적 로딩을위한 자리를 사용해야하는 경우 다음과 같은 방식으로 구성해야합니다.

<context:property-placeholder location="classpath*:config.properties" />

<import resource="classpath:spring-db-${env}.xml" />

지정자 상기 env구성 파일에 의해 값 config.properties을 얻었다. 당신은 프로젝트를 시작할 때 오류가 발생합니다 위의 문구를 사용하는 경우.

구문 분석 봄 봐 import우리가 볼 수있는 소스 코드 라벨 :

DefaultBeanDefinitionDocumentReader.java

    private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
        if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
            importBeanDefinitionResource(ele);
        }
        else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
            processAliasRegistration(ele);
        }
        else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
            processBeanDefinition(ele, delegate);
        }
        else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
            // recurse
            doRegisterBeanDefinitions(ele);
        }
    }

Spring은 호출하여 볼 수 있습니다 importBeanDefinitionResource()구문 분석 방법의 import태그를. 그리고 다음의 논리에 의해 분석 resource속성 :

// Resolve system properties: e.g. "${user.dir}"
location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location);

그것은 해결의 자리 표시 시스템 속성을 의미한다. 그리고 우리는 자리 스프링 빈에 의해 일반적으로 사용되는 대체하기 위해 채택 Spring ioc확산 BeanFactoryPostProcessor서브 클래스 PropertyPlaceholderConfigurer달성하기를. 그러나 대한 import해상도 아직 그 단계에 도달하지 않았습니다. 그래서 우리는 필요 ioc전에로드 할 properites파일.

1 = -Dkey 부가가치 시스템 파라미터

가장 간단한하여 서비스를 시작하는 시간입니다 -Dproperty=value시스템을 설정 属性名/值对, 사용할 수있는이 JVM의 상단에서 응용 프로그램 실행 System.getProperty("property")값에 대한 값을 줄입니다. 값에 공백이있는 경우로, 큰 따옴표로 묶인 값을 사용합니다 -Dname="space string". 이 매개 변수는 일반적으로 특성이 프로그램의 어디에서 액세스 할 수 있습니다 그래서, 이러한 프로파일 경로로 전역 변수 수준의 시스템을 설정하는 데 사용됩니다.

추가하여 부팅시에 Tomcat을 시작 -Denv=dev으로. 같은 우리는 매개 변수를 추가하는 봄의 확장을 사용할 수 있습니다.

2, initPropertySources

우리 모두가 알다시피, 봄은 contextInitialized ContextLoaderListener에 의해 컨테이너의 뿌리를로드하는 것입니다. 부모 ContextLoader를 우리는 다음과 같은 논리를 볼 수 있습니다.

ContextLoader.java

    protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
        if (ObjectUtils.identityToString(wac).equals(wac.getId())) {
            // The application context id is still set to its original default value
            // -> assign a more useful id based on available information
            String idParam = sc.getInitParameter(CONTEXT_ID_PARAM);
            if (idParam != null) {
                wac.setId(idParam);
            }
            else {
                // Generate default id...
                wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +
                        ObjectUtils.getDisplayString(sc.getContextPath()));
            }
        }

        wac.setServletContext(sc);
        String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
        if (configLocationParam != null) {
            wac.setConfigLocation(configLocationParam);
        }

        // The wac environment's #initPropertySources will be called in any case when the context
        // is refreshed; do it eagerly here to ensure servlet property sources are in place for
        // use in any post-processing or initialization that occurs below prior to #refresh
        ConfigurableEnvironment env = wac.getEnvironment();
        if (env instanceof ConfigurableWebEnvironment) {
            ((ConfigurableWebEnvironment) env).initPropertySources(sc, null);
        }

        customizeContext(sc, wac);
        wac.refresh();
    }

위는 ((ConfigurableWebEnvironment) env).initPropertySources(sc, null);결국 initServletPropertySources 방법의 WebApplicationContextUtils를 호출합니다.

    public static void initServletPropertySources(
            MutablePropertySources propertySources, ServletContext servletContext, ServletConfig servletConfig) {

        Assert.notNull(propertySources, "propertySources must not be null");
        if (servletContext != null && propertySources.contains(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME) &&
                propertySources.get(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME) instanceof StubPropertySource) {
            propertySources.replace(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME,
                    new ServletContextPropertySource(StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME, servletContext));
        }
        if (servletConfig != null && propertySources.contains(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME) &&
                propertySources.get(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME) instanceof StubPropertySource) {
            propertySources.replace(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME,
                    new ServletConfigPropertySource(StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME, servletConfig));
        }
    }

이것은 자리 수입하는 ServletContext 초기화 파라미터 초기화 된 ServletConfig 파라미터의 값으로 설정 될 수있다.

2.1의 ServletContext 초기화 파라미터

용기 스프링 스프링 MVC 프로필 경우 정의하면되는 루트 컨테이너 전용의 ServletContext 초기화 파라미터의 초기 설정에 관한 것이다. 루트 컨테이너는 컨테이너 ContextLoaderListener에 의해 초기화되어 있기 때문에,이 범위 ServletConfig를 서블릿이다. ServletContext를 초기화 파라미터는 다음과 같은 구성으로 구성 될 수있다.

<context-param>
    <param-name>env</param-name>
    <param-value>dev</param-value>
</context-param>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:application-context.xml</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

2.2 ServletConfig를 초기화 파라미터

컨테이너는 스프링 스프링 MVC 프로필에있는 컨테이너 serlvet 경우 정의됩니다. 즉, ServletContext를 초기화 매개 변수를 통해뿐만 아니라 ServletConfig를 매개 변수 초기화가 될 수 있습니다. 따라서 매개 변수는 다음 두 가지 방법으로 수행 할 수 있습니다 :

<context-param>
    <param-name>env</param-name>
    <param-value>dev</param-value>
</context-param>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:application-context.xml</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

이 자리 가져 오기 classpath:application-context.xml파일

또는

 <servlet>
     <servlet-name>dispatcher</servlet-name>
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
     <init-param>
         <param-name>contextConfigLocation</param-name>
         <param-value>classpath:dispatcher-servlet.xml</param-value>
     </init-param>
     <init-param>
         <param-name>env</param-name>
         <param-value>dev</param-value>
     </init-param>
     <load-on-startup>1</load-on-startup>
 </servlet>

이 자리 가져 오기 classpath:dispatcher-servlet.xml파일

3, 사용자 정의 ApplicationContextInitializer

초기화하기 전에 (ConfigurableWebEnvironment 번호의 initPropertySources, 봄 컨테이너를 호출 한 후 wac.refresh()호출) customizeContext(sc, wac)컨테이너 사용자 정의 로직 처리를.

    protected void customizeContext(ServletContext sc, ConfigurableWebApplicationContext wac) {
        List<Class<ApplicationContextInitializer<ConfigurableApplicationContext>>> initializerClasses =
                determineContextInitializerClasses(sc);

        for (Class<ApplicationContextInitializer<ConfigurableApplicationContext>> initializerClass : initializerClasses) {
            Class<?> initializerContextClass =
                    GenericTypeResolver.resolveTypeArgument(initializerClass, ApplicationContextInitializer.class);
            if (initializerContextClass != null && !initializerContextClass.isInstance(wac)) {
                throw new ApplicationContextException(String.format(
                        "Could not apply context initializer [%s] since its generic parameter [%s] " +
                        "is not assignable from the type of application context used by this " +
                        "context loader: [%s]", initializerClass.getName(), initializerContextClass.getName(),
                        wac.getClass().getName()));
            }
            this.contextInitializers.add(BeanUtils.instantiateClass(initializerClass));
        }

        AnnotationAwareOrderComparator.sort(this.contextInitializers);
        for (ApplicationContextInitializer<ConfigurableApplicationContext> initializer : this.contextInitializers) {
            initializer.initialize(wac);
        }
    }

이 논리는 획득 web.xml문서 입니다 하고 하는 클래스가 구현하는 인터페이스의 전체 이름을 입력합니다. 전에 스프링 컨테이너는 초기화 콜백 메소드 호출 컨테이너 로직을 사용자 정의 할 수 있습니다.
<context-param>
<param-name>globalInitializerClassescontextInitializerClasses<param-value>ApplicationContextInitializerinitialize()

이 인터페이스는 봄을 구현하여 ApplicationContextInitializer을 제공합니다. 콜백 인터페이스에서 initialize()컨테이너에 속성을 파일 속성을 추가 할 수 있습니다. 그는 컨테이너에서 구성 파일의 값을 얻을 수있을 때 그런 해석 수입 레이블은 자리를 대체한다.

ApplicationContextInitializer 달성 3.1 인터페이스

ApplicationContextInitializer 인터페이스 호출을 달성 initialize()컨테이너에 속성 파일 속성을 추가 할 수 있습니다.


public class CustomerApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext>{
    private static Logger logger = LoggerFactory.getLogger(CustomerApplicationContextInitializer.class);
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        ResourcePropertySource propertySource = null;
        try {
            propertySource = new ResourcePropertySource("classpath:config.properties");
        } catch (IOException e) {
            logger.error("config.properties is not exists");
        }
        applicationContext.getEnvironment().getPropertySources().addFirst(propertySource);
    }
}

3.2 구성 속성 문맥 PARAM

향상된 다음과 같은 상황에 PARAM 속성 web.xml에 컨테이너를 추가합니다. 때문에 customizeContext(sc, wac)이 모든 호출 방법.contextInitializerClassesinitialize()

<context-param>
    <param-name>globalInitializerClasses</param-name>
    <param-value>cn.carlzone.spring.initializer.CustomerApplicationContextInitializer</param-value>
</context-param>

또는

<context-param>
    <param-name>contextInitializerClasses</param-name>
    <param-value>cn.carlzone.spring.initializer.CustomerApplicationContextInitializer</param-value>
</context-param>

이어서 자리 env구성 파일에 의해 값 config.properties을 얻었다. 스프링 프로젝트에 대한 적절한 구성 파일을로드합니다.

참고 기사 :

发布了173 篇原创文章 · 获赞 221 · 访问量 70万+

추천

출처blog.csdn.net/u012410733/article/details/81322763