1.13.1 빈 정의 프로파일

빈 정의 프로파일은 다른 환경에서 다른 빈을 등록 할 수있는 핵심 컨테이너에 메커니즘을 제공합니다. "환경"이라는 단어는 다른 사용자에게 다른 것을 의미 할 수 있으며이 기능은 다음을 포함하여 많은 유스 케이스에 도움이 될 수 있습니다.

  • QA 또는 프로덕션 환경에서 JNDI에서 동일한 데이터 소스를 찾아 보는 대신 개발시 메모리 내 데이터 소스에 대해 작업합니다.

  • 성능 환경에 애플리케이션을 배치 할 때만 모니터링 인프라를 등록합니다.

  • 고객 A 배포와 고객 B 배포의 사용자 정의 된 구현을 등록하는 중입니다.

DataSource가 필요한 실용적인 응용 프로그램에서 첫 번째 유스 케이스를 고려해야합니다. 테스트 환경에서 구성은 다음과 유사 할 수 있습니다.

@Bean
public DataSource dataSource() {
    return new EmbeddedDatabaseBuilder()
        .setType(EmbeddedDatabaseType.HSQL)
        .addScript("my-schema.sql")
        .addScript("my-test-data.sql")
        .build();
}

이제 응용 프로그램의 데이터 소스가 프로덕션 응용 프로그램 서버의 JNDI 디렉토리에 등록되었다고 가정하고이 응용 프로그램을 QA 또는 프로덕션 환경에 전개하는 방법을 고려하십시오. 이제 우리 dataSourcebean은 다음 목록과 같습니다.

@Bean(destroyMethod="")
public DataSource dataSource() throws Exception {
    Context ctx = new InitialContext();
    return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
}

문제는 현재 환경에 따라 이 두 가지 변형을 사용하는 방법을 전환하는 방법입니다. 시간이 지남에 따라 Spring 사용자는 값에 따라 올바른 구성 파일 경로를 확인하는 ${placeholder}토큰을 포함하는 XML <import/> 시스템 환경 변수의 조합에 의존하여이를 수행 할 수있는 여러 가지 방법을 고안해 왔습니다. 환경 변수. 빈 정의 프로파일은이 문제점에 대한 해결책을 제공하는 핵심 컨테이너 기능입니다.

환경 특정 bean 정의의 앞의 예제에 나타난 유스 케이스를 일반화하면 특정 bean 정의를 특정 컨텍스트에 등록 할 필요가 있지만 다른 것들은 등록하지 않아도됩니다. 상황 A의 특정 bean 정의 프로파일과 상황 B의 다른 프로파일을 등록하기를 원한다고 말할 수 있습니다. 우리는이 필요성을 반영하기 위해 구성을 업데이트하는 것으로 시작합니다.

@Profile 사용

@Profile 주석은 하나 개 이상의 지정된 프로파일이 활성화 될 때 구성 요소가 등록 자격이 있음을 표시 할 수 있습니다. 위 예제를 사용하여 dataSource다음과 같이 구성을 다시 작성할 수 있습니다 .

@Configuration
@Profile("development")
public class StandaloneDataConfig {

    @Bean
    public DataSource dataSource() {
        return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.HSQL)
            .addScript("classpath:com/bank/config/sql/schema.sql")
            .addScript("classpath:com/bank/config/sql/test-data.sql")
            .build();
    }
}
@Configuration
@Profile("production")
public class JndiDataConfig {

    @Bean(destroyMethod="")
    public DataSource dataSource() throws Exception {
        Context ctx = new InitialContext();
        return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
    }
}

앞서 언급했듯이 @Bean메서드를 사용하면 일반적으로 Spring의 JndiTemplate/ JndiLocatorDelegatehelpers 또는InitialContext이전에 표시된 JNDI 사용 을 사용하여 프로그래밍 방식의 JNDI 조회를 사용하도록 선택 합니다.JndiObjectFactoryBean 변형은 아니므 로 반환 유형을 FactoryBean타입유형으로 선언합니니다.

프로필 문자열에는 간단한 프로필 이름 (예 production:) 또는 프로필식이 포함될 수 있습니다 . 프로파일 표현식을 사용하면보다 복잡한 프로파일 로직을 표현할 수 있습니다 (예 :) production & us-east. 프로파일 표현식에서 다음 연산자가 지원됩니다.

  • !: 논리적 인 "not"의 프로필

  • &: 프로파일의 논리적 "and"

  • |: 프로필의 논리적 "또는"

괄호를 사용하지 않고 연산자 &|연산자를 섞을 수 없습니다 . 예를 들어, production & us-east | eu-central유효한 표현식이 아닙니다. 그것은으로 표현되어야합니다 production & (us-east | eu-central).

사용자 정의 작성 주석을 작성하기 위해@Profile을 메타 주석으로 사용할 수 있습니다. 다음 예제는 @Profile("production")의 드롭 인 대체품으로 사용할 수있는 사용자 정의 @Production 주석을 정의합니다.

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Profile("production")
public @interface Production {
}

@Configuration 클래스가 @Profile로 표시되어 있는 경우, 하나 이상의 지정된 프로필이 활성화되어 있지 않으면 해당 클래스와 연결된 @Bean 메서드 및 @Import 주석이 모두 무시됩니다. @Component 또는 @Configuration 클래스가 @Profile ({ "p1", "p2"})으로 표시된 경우 프로필 'p1'또는 'p2'가 활성화되어 있지 않으면 해당 클래스가 등록되거나 처리되지 않습니다. 주어진 프로파일에 접두어 NOT 연산자 (!)가 있으면 주석이 ☽린 요소는 프로파일이 활성 상태가 아닌 경우에만 등록됩니다. 예를 들어 @Profile ({ "p1", "! p2"})을 사용하면 프로필 'p1'이 활성화되어 있거나 프로필 'p2'가 활성화되어 있지 않으면 등록이 수행됩니다.

@Profile 또한 다음 예제와 같이 구성 수준의 특정 빈 (예 : 특정 빈의 대체 변형)을 포함하도록 메서드 수준에서 선언 할 수 있습니다.

@Configuration
public class AppConfig {

    @Bean("dataSource")
    @Profile("development") 
    public DataSource standaloneDataSource() {
        return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.HSQL)
            .addScript("classpath:com/bank/config/sql/schema.sql")
            .addScript("classpath:com/bank/config/sql/test-data.sql")
            .build();
    }

    @Bean("dataSource")
    @Profile("production") 
    public DataSource jndiDataSource() throws Exception {
        Context ctx = new InitialContext();
        return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
    }
}

standaloneDataSource메서드는 development프로필 에서만 사용할 수 있습니다 .

jndiDataSource메서드는 production프로필 에서만 사용할 수 있습니다 .

@Bean 메서드에서 @Profile을 사용하면 특별한 시나리오가 적용될 수 있습니다. 동일한 자바 메서드 이름의 @Bean 메서드가 오버로드 된 경우 (생성자 오버로드와 유사), 오버로드 된 모든 메서드에서 @Profile 조건을 일관되게 선언해야합니다. 조건이 일치하지 않으면 오버로드 된 메서드 중 첫 번째 선언의 조건 만 중요합니다. 따라서 @Profile은 다른 인수에 대해 특정 인수 서명이있는 오버로드 된 메서드를 선택하는 데 사용할 수 없습니다. 같은 bean에 대한 모든 팩토리 메소드 간의 해결은 작성시 Spring의 생성자 분석 알고리즘을 따릅니다.

다른 프로파일 조건을 가진 대체 빈을 정의하려면 앞의 예제와 같이 @Bean name 속성을 사용하여 동일한 bean 이름을 가리키는 고유 한 Java 메소드 이름을 사용하십시오. 인수 시그너처가 모두 같은 경우 (예 : 모든 변형에 인수가없는 팩터 리 메소드가있는 경우), 유효한 Java 클래스에서 이러한 정렬을 가장 먼저 나타낼 수있는 유일한 방법입니다 (이후에만 하나의 특정 이름 및 인수 서명 방법).

XML Bean 정의 프로파일

XML 대응 요소 profile<beans>요소 의 속성입니다 . 앞의 샘플 구성은 다음과 같이 두 개의 XML 파일로 다시 작성할 수 있습니다.

<beans profile="development"
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xsi:schemaLocation="...">

    <jdbc:embedded-database id="dataSource">
        <jdbc:script location="classpath:com/bank/config/sql/schema.sql"/>
        <jdbc:script location="classpath:com/bank/config/sql/test-data.sql"/>
    </jdbc:embedded-database>
</beans>
<beans profile="production"
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="...">

    <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/datasource"/>
</beans>

다음 예제와 같이 동일한 파일에서 <beans/>요소를 분할 및 중첩하는 것을 피할 수도 있습니다 .

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="...">

    <!-- other bean definitions -->

    <beans profile="development">
        <jdbc:embedded-database id="dataSource">
            <jdbc:script location="classpath:com/bank/config/sql/schema.sql"/>
            <jdbc:script location="classpath:com/bank/config/sql/test-data.sql"/>
        </jdbc:embedded-database>
    </beans>

    <beans profile="production">
        <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/datasource"/>
    </beans>
</beans>

The spring-bean.xsd요소는 파일의 마지막 요소와 같은 요소 만 허용하도록 제한되었습니다. 이렇게하면 XML 파일에 혼란을주지 않으면 서 유연성을 제공 할 수 있습니다.

XML 카운터 파트는 앞에서 설명한 프로필 식을 지원하지 않습니다. 그러나 !연산자 를 사용하여 프로필을 무효화하는 것은 가능합니다 . 다음 예제와 같이 프로필을 중첩하여 논리적 "and"를 적용 할 수도 있습니다.

앞의 예에서 production 및 us-east 프로파일이 모두 활성화되어 있으면 dataSource bean이 노출됩니다.

프로파일 활성화

이제 설정을 업데이트 했으므로, Spring에게 어떤 프로파일이 활성 상태인지를 지시해야합니다. 샘플 애플리케이션을 지금 시작했다면 NoSuchBeanDefinitionException,가 던져진다. 컨테이너가 dataSource라고 이름 붙여진 Spring bean을 찾을 수 없기 때문에 던져진 것을 볼 수있다.

프로필 활성화는 여러 가지 방법으로 수행 할 수 있지만 가장 직접적으로 EnvironmentAPI를 통해 ApplicationContext프로그래밍 할 수 있습니다. 다음 예제에서는이를 수행하는 방법을 보여줍니다.

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.getEnvironment().setActiveProfiles("development");
ctx.register(SomeConfig.class, StandaloneDataConfig.class, JndiDataConfig.class);
ctx.refresh();

또한 spring.profiles.active시스템 환경 변수, JVM 시스템 등록 정보, 서블릿 컨텍스트 매개 변수 web.xml또는 JNDI의 항목 ( PropertySourceAbstraction 참조 )을 통해 지정할 수도있는 속성을 통해 프로파일을 선언적으로 활성화 할 수 있습니다 . 통합 테스트에서 활성 프로파일은 모듈 spring-test@ActiveProfiles주석 을 사용하여 선언 할 수 있습니다 ( 환경 프로파일을 사용한 컨텍스트 구성 참조 ).

프로파일은 "어느 것인가"또는 "하나의 명제"가 아닙니다. 한 번에 여러 프로필을 활성화 할 수 있습니다. 프로그래밍방식으로 setActiveProfiles()메서드에 여러 프로필 이름을 제공 할 수 있습니다.이 프로필 이름 은 String…​varargs 를 허용 합니다. 다음 예제에서는 여러 프로필을 활성화합니다.

ctx.getEnvironment().setActiveProfiles("profile1", "profile2");

다음 예제와 같이 spring.profiles.active선언적 으로 쉼표로 구분 된 프로필 이름 목록을 허용 할 수 있습니다.

-Dspring.profiles.active="profile1,profile2"

기본 프로필

기본 프로파일은 기본적으로 사용 가능한 프로파일을 나타냅니다. 다음 예제를 고려하십시오.

@Configuration
@Profile("default")
public class DefaultDataConfig {

    @Bean
    public DataSource dataSource() {
        return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.HSQL)
            .addScript("classpath:com/bank/config/sql/schema.sql")
            .build();
    }
}

활성화 된 프로파일이 없으면이 프로파일 dataSource이 작성됩니다. 하나 이상의 빈에 대한 기본 정의를 제공하는 방법으로 이것을 볼 수 있습니다. 사용 가능한 프로파일이 있으면 기본 프로파일이 적용되지 않습니다.

환경에서 setDefaultProfiles ()를 사용하거나, 선언적으로 spring.profiles.default 속성을 사용하여 기본 프로필의 이름을 변경할 수 있습니다..

Last updated