2024. 11. 14. 14:19ㆍSpring Framework/Spring IoC
Spring의 Java 기반 구성 기능을 사용하면 어노테이션을 작성할 수 있어 구성의 복잡성을 줄일 수 있습니다.
Using the @Import Annotation
<import/> 엘리먼트가 Spring XML 파일 내에서 구성의 모듈화를 돕기 위해 사용되는 것처럼, @Import 어노테이션을 사용하면 다음 예제와 같이 다른 구성 클래스에서 @Bean 정의를 로드할 수 있습니다.
@Configuration
public class ConfigA {
@Bean
public A a() {
return new A();
}
}
@Configuration
@Import(ConfigA.class)
public class ConfigB {
@Bean
public B b() {
return new B();
}
}
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class);
// now both beans A and B will be available...
A a = ctx.getBean(A.class);
B b = ctx.getBean(B.class);
}
이 접근 방식은 컨테이너 인스턴스화를 간소화합니다. 컨테이너를 생성하는 동안 잠재적으로 많은 수의 @Configuration 클래스를 기억할 필요가 없고, 하나의 클래스만 처리하면 되기 때문입니다.
Spring Framework 4.2부터 @Import 애노테이션은 일반 컴포넌트 클래스에 대한 참조도 지원하게 되었습니다. 이는 AnnotationConfigApplicationContext.register 메서드와 유사한 방식으로 작동하며, 컴포넌트 스캐닝을 피하고 몇 개의 구성 클래스를 사용하여 모든 컴포넌트를 명시적으로 정의하고자 할 때 특히 유용합니다.
기본 개념 설명
@Import는 구성 클래스에 다른 구성 클래스나 컴포넌트 클래스를 포함시킬 때 사용됩니다. 이를 통해 여러 구성 클래스를 하나의 중앙 구성 클래스로 묶을 수 있으며, 이로 인해 구성의 모듈화가 가능해집니다.
Spring 4.2 이전에는 @Import 애노테이션이 다른 @Configuration 클래스만 참조할 수 있었지만, Spring 4.2부터는 일반적인 컴포넌트 클래스 (@Component, @Service, @Repository, @Controller 등)도 참조할 수 있게 되었습니다. 이를 통해 명시적으로 관리하고 싶은 컴포넌트만 등록하여 구성할 수 있습니다.
코드 예제
아래 예제는 @Import를 사용하여 컴포넌트 클래스를 명시적으로 등록하는 방법을 보여줍니다.
1. 일반 컴포넌트 클래스 정의
2. 설정 클래스 정의 및 @Import 사용import org.springframework.stereotype.Component; @Component public class MyService { public void performService() { System.out.println("Service is being performed."); } } @Component public class MyRepository { public void performRepositoryAction() { System.out.println("Repository action performed."); } }
3. 메인 메서드에서 Spring 컨텍스트 사용import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @Configuration @Import({MyService.class, MyRepository.class}) public class AppConfig { // 다른 설정이 있을 경우 여기에 추가 }
import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class MainApp { public static void main(String[] args) { // ApplicationContext 초기화 및 설정 클래스 로드 ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); // MyService와 MyRepository 빈을 가져와서 사용 MyService myService = context.getBean(MyService.class); myService.performService(); MyRepository myRepository = context.getBean(MyRepository.class); myRepository.performRepositoryAction(); } }
코드 설명
⦁ MyService와 MyRepository: 각각 @Component` 애노테이션이 붙은 일반 컴포넌트 클래스입니다. 이 클래스들은 서비스 로직과 리포지토리 동작을 담당합니다.
⦁ AppConfig 클래스: Spring 구성 클래스입니다. @Import 애노테이션을 사용하여 MyService와 MyRepository 컴포넌트 클래스를 명시적으로 등록합니다. 이 방식으로 컴포넌트 스캐닝 없이도 필요한 컴포넌트만 설정에 포함할 수 있습니다.
⦁ MainApp 클래스: AnnotationConfigApplicationContext를 사용하여 AppConfig 설정 클래스를 로드하고, 등록된 빈을 가져와서 사용합니다. MyService와 MyRepository 빈이 정상적으로 인스턴스화되고, 메서드를 호출하여 각각의 동작을 수행합니다.
이 접근 방식은 특히 대규모 프로젝트에서 명시적인 구성 관리가 필요할 때 유용합니다. @Import를 사용하면 구성 클래스 간의 의존성을 명확히 할 수 있고, 컴포넌트 스캐닝에 의존하지 않고도 필요한 컴포넌트를 명시적으로 구성할 수 있습니다. 이는 구성의 명시성과 예측 가능성을 높이며, 컴포넌트 스캐닝에서 발생할 수 있는 잠재적인 문제를 회피하는 데 도움을 줍니다.
Injecting Dependencies on Imported @Bean Definitions
앞의 예제는 작동하지만 단순합니다. 대부분의 실제 시나리오에서 빈은 구성 클래스 간에 서로 종속성이 있습니다. XML을 사용하는 경우 컴파일러가 관여하지 않기 때문에 문제가 되지 않으며 ref="someBean"을 선언하고 컨테이너 초기화 중에 Spring이 이를 해결하도록 신뢰할 수 있습니다. @Configuration 클래스를 사용하는 경우 Java 컴파일러는 구성 모델에 제약 조건을 두므로 다른 빈에 대한 참조는 유효한 Java 구문이어야 합니다.
다행히도 이 문제를 해결하는 것은 간단합니다. 이미 논의했듯이 @Bean 메서드는 빈 종속성을 설명하는 임의의 수의 파라미터를 가질 수 있습니다. 각각 다른 빈에 선언된 빈에 따라 달라지는 여러 @Configuration 클래스가 있는 다음과 같은 보다 현실적인 시나리오를 고려하세요.
@Configuration
public class ServiceConfig {
@Bean
public TransferService transferService(AccountRepository accountRepository) {
return new TransferServiceImpl(accountRepository);
}
}
@Configuration
public class RepositoryConfig {
@Bean
public AccountRepository accountRepository(DataSource dataSource) {
return new JdbcAccountRepository(dataSource);
}
}
@Configuration
@Import({ServiceConfig.class, RepositoryConfig.class})
public class SystemTestConfig {
@Bean
public DataSource dataSource() {
// return new DataSource
}
}
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
// everything wires up across configuration classes...
TransferService transferService = ctx.getBean(TransferService.class);
transferService.transfer(100.00, "A123", "C456");
}
// SpringTransactionManager 참조
같은 결과를 얻는 또 다른 방법이 있습니다. @Configuration 클래스는 궁극적으로 컨테이너의 또 다른 빈일 뿐이라는 점을 기억하세요. 즉, 다른 빈과 마찬가지로 @Autowired 및 @Value 주입과 다른 기능을 활용할 수 있습니다.
※ 구성 클래스내에 @Autowired를 사용한 의존성 주입
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import javax.sql.DataSource;
@Configuration
public class ServiceConfig {
@Autowired
private AccountRepository accountRepository; // 자동 주입
@Bean
public TransferService transferService() {
return new TransferServiceImpl(accountRepository); // 필드에서 가져온 빈 사용
}
}
@Configuration
public class RepositoryConfig {
@Autowired
private DataSource dataSource; // 자동 주입
@Bean
public AccountRepository accountRepository() {
return new JdbcAccountRepository(dataSource); // 필드에서 가져온 빈 사용
}
}
@Configuration
@Import({ServiceConfig.class, RepositoryConfig.class})
public class SystemTestConfig {
@Bean
public DataSource dataSource() {
// DataSource 구현체 반환
// 예를 들어, HikariDataSource 등
}
}
public class MainApp {
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
// 모든 설정 클래스가 적절하게 연결됨
TransferService transferService = ctx.getBean(TransferService.class);
transferService.transfer(100.00, "A123", "C456");
}
}
이런 방식으로 주입하는 종속성이 가장 단순한 종류인지 확인하세요. @Configuration 클래스는 컨텍스트 초기화 중에 매우 일찍 처리되며, 이런 방식으로 종속성을 강제로 주입하면 예상치 못한 조기 초기화가 발생할 수 있습니다. 가능하면 앞의 예와 같이 매개변수 기반 주입을 사용하세요.
동일한 구성 클래스의 @PostConstruct 메서드 내에서 로컬로 정의된 빈에 액세스하지 마세요. 비정적 @Bean 메서드는 의미적으로 완전히 초기화된 구성 클래스 인스턴스가 호출되어야 하기 때문에 순환 참조가 발생합니다. 순환 참조가 허용되지 않으면(예: Spring Boot 2.6+) BeanCurrentlyInCreationException이 발생할 수 있습니다.
또한 @Bean을 통한 BeanPostProcessor 및 BeanFactoryPostProcessor 정의에 특히 주의하세요. 이러한 정의는 일반적으로 정적 @Bean 메서드로 선언해야 하며, 포함된 구성 클래스의 인스턴스화를 트리거하지 않아야 합니다. 그렇지 않으면 @Autowired와 @Value가 구성 클래스 자체에서 작동하지 않을 수 있습니다. AutowiredAnnotationBeanPostProcessor보다 일찍 빈 인스턴스로 생성할 수 있기 때문입니다.
위 설명에 해당하는 샘플 코드 예시
1. 파라미터 기반 주입 사용: @Autowired를 사용한 필드 주입 대신, 파라미터 기반 주입을 권장합니다.
2. @PostConstruct 주의: @PostConstruct 메서드 내에서 동일한 구성 클래스의 non-static @Bean 메서드에 접근하지 않도록 합니다.
3. BeanPostProcessor와 BeanFactoryPostProcessor 정의: 이러한 클래스들은 일반적으로 static @Bean 메서드로 정의해야 하며, 그렇지 않으면 예상치 못한 초기화 문제가 발생할 수 있습니다.
샘플 코드
1. 기본 구성 및 주입 예제
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.annotation.PostConstruct; @Configuration public class AppConfig { private final TransferService transferService; // 매개변수 기반 주입을 사용하여 TransferService를 초기화 public AppConfig(TransferService transferService) { this.transferService = transferService; } @Bean public TransferService transferService(AccountRepository accountRepository) { return new TransferServiceImpl(accountRepository); } @Bean public AccountRepository accountRepository(DataSource dataSource) { return new JdbcAccountRepository(dataSource); } @Bean public DataSource dataSource() { // 데이터베이스 연결을 위한 DataSource 설정 // 예를 들어, HikariDataSource 또는 다른 구현체를 반환 } @PostConstruct public void init() { // 이 메서드 내에서 동일한 구성 클래스의 비정적 @Bean 메서드에 접근하지 마세요 // 예: transferService(); (비정적 메서드 접근 금지) System.out.println("AppConfig initialized"); } }
2. BeanPostProcessor 및 BeanFactoryPostProcessor 정의 예제import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.stereotype.Component; @Configuration public class ProcessorConfig { // 정적 @Bean 메서드로 BeanPostProcessor 정의 @Bean public static BeanPostProcessor customBeanPostProcessor() { return new CustomBeanPostProcessor(); } // 정적 @Bean 메서드로 BeanFactoryPostProcessor 정의 @Bean public static BeanFactoryPostProcessor customBeanFactoryPostProcessor() { return new CustomBeanFactoryPostProcessor(); } } @Component class CustomBeanPostProcessor implements BeanPostProcessor { // BeanPostProcessor 구현 } @Component class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor { // BeanFactoryPostProcessor 구현 }
설명
1. 파라미터 기반 주입:
⦁ AppConfig 클래스에서는 TransferService를 생성자 주입 방식으로 받아 초기화합니다. 이렇게 하면 Spring 컨텍스트 초기화 중에 발생할 수 있는 조기 초기화 문제를 피할 수 있습니다.
2. @PostConstruct 주의사항:
⦁ @PostConstruct 메서드에서 non-static @Bean 메서드를 호출하지 않도록 주의해야 합니다. 순환 참조가 발생할 수 있으며, Spring Boot 2.6+에서는 BeanCurrentlyInCreationException이 발생할 수 있습니다.
3. static @Bean 메서드를 통한 BeanPostProcessor 및 BeanFactoryPostProcessor 정의:
⦁ ProcessorConfig 클래스에서는 BeanPostProcessor와 BeanFactoryPostProcessor를 static 메서드로 정의하여 Spring이 해당 클래스의 인스턴스화를 조기에 트리거하지 않도록 합니다. 이렇게 하면 @Autowired와 @Value가 예상대로 동작합니다.
이 코드는 Spring에서 의존성 주입을 처리하는 올바른 방법을 보여줍니다. 특히, Spring 컨텍스트 초기화 중 발생할 수 있는 조기 초기화 문제를 피하기 위해 파라미터 기반 주입과 static @Bean 메서드를 사용하여 BeanPostProcessor 및 BeanFactoryPostProcessor를 정의하는 방법을 강조합니다. 이러한 패턴을 따르면 예상치 못한 초기화 문제를 방지할 수 있습니다.
다음 예제는 어떻게 한 빈이 다른 빈에 자동으로 연결될 수 있는지 보여줍니다.
@Configuration
public class ServiceConfig {
@Autowired
private AccountRepository accountRepository;
@Bean
public TransferService transferService() {
return new TransferServiceImpl(accountRepository);
}
}
@Configuration
public class RepositoryConfig {
// @Configuration 클래스의 생성자 주입은 Spring Framework 4.3부터만 지원됩니다.
// 또한 대상 빈이 생성자를 하나만 정의하는 경우 @Autowired를 지정할 필요가 없다는 점에 유의하세요.
private final DataSource dataSource;
public RepositoryConfig(DataSource dataSource) {
this.dataSource = dataSource;
}
@Bean
public AccountRepository accountRepository() {
return new JdbcAccountRepository(dataSource);
}
}
@Configuration
@Import({ServiceConfig.class, RepositoryConfig.class})
public class SystemTestConfig {
@Bean
public DataSource dataSource() {
// return new DataSource
}
}
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
// everything wires up across configuration classes...
TransferService transferService = ctx.getBean(TransferService.class);
transferService.transfer(100.00, "A123", "C456");
}
@Configuration 클래스의 생성자 주입은 Spring Framework 4.3부터만 지원됩니다. 또한 대상 빈이 생성자를 하나만 정의하는 경우 @Autowired를 지정할 필요가 없다는 점에 유의하세요.
이전 시나리오에서 @Autowired를 사용하면 잘 작동하고 원하는 모듈성을 제공하지만 자동 와이어링된 빈 정의가 정확히 어디에 선언되는지 확인하는 것은 여전히 다소 모호합니다. 예를 들어 ServiceConfig를 살펴보는 개발자로서 @Autowired AccountRepository 빈이 정확히 어디에 선언되는지 어떻게 알 수 있을까요? 코드에 명시적으로 나와 있지 않지만, 이것으로 충분할 수 있습니다. Eclipse용 Spring Tools는 모든 것이 어떻게 와이어링되는지 보여주는 그래프를 렌더링할 수 있는 도구를 제공(스프링 부트 프로젝트에서만 지원)하며, 이것만으로도 충분할 수 있습니다. 또한 Java IDE는 AccountRepository 타입의 모든 선언과 사용을 쉽게 찾고 해당 타입을 리턴하는 @Bean 메서드의 위치를 빠르게 보여줄 수 있습니다.
이러한 모호성이 허용되지 않고 IDE 내에서 한 @Configuration 클래스에서 다른 @Configuration 클래스로 직접 이동하려는 경우 구성 클래스 자체를 자동 와이어링하는 것을 고려하세요. 다음 예는 그 방법을 보여줍니다.
@Configuration
public class ServiceConfig {
@Autowired
private RepositoryConfig repositoryConfig;
@Bean
public TransferService transferService() {
// navigate 'through' the config class to the @Bean method!
return new TransferServiceImpl(repositoryConfig.accountRepository());
}
}
이전 상황에서 AccountRepository가 정의된 위치는 완전히 명시적입니다. 그러나 ServiceConfig는 이제 RepositoryConfig에 밀접하게 결합되었습니다. 이것이 트레이드오프입니다. 이러한 밀접 결합은 인터페이스 기반 또는 추상 클래스 기반 @Configuration 클래스를 사용하여 다소 완화할 수 있습니다. 다음 예를 고려하세요.
@Configuration
public class ServiceConfig {
@Autowired
private RepositoryConfig repositoryConfig;
@Bean
public TransferService transferService() {
return new TransferServiceImpl(repositoryConfig.accountRepository());
}
}
@Configuration
public interface RepositoryConfig {
@Bean
AccountRepository accountRepository();
}
@Configuration
public class DefaultRepositoryConfig implements RepositoryConfig {
@Bean
public AccountRepository accountRepository() {
return new JdbcAccountRepository(...);
}
}
@Configuration
@Import({ServiceConfig.class, DefaultRepositoryConfig.class}) // import the concrete config!
public class SystemTestConfig {
@Bean
public DataSource dataSource() {
// return DataSource
}
}
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
TransferService transferService = ctx.getBean(TransferService.class);
transferService.transfer(100.00, "A123", "C456");
}
이제 ServiceConfig는 구체적인 DefaultRepositoryConfig와 관련하여 느슨하게 결합되었으며, 내장된 IDE 툴링은 여전히 유용합니다. RepositoryConfig 구현의 타입 계층을 쉽게 얻을 수 있습니다. 이런 식으로 @Configuration 클래스와 해당 의존성을 탐색하는 것은 인터페이스 기반 코드를 탐색하는 일반적인 프로세스와 다르지 않습니다.
특정 빈의 시작 시 생성 순서에 영향을 주고 싶다면, 일부 빈을 @Lazy(시작 시가 아닌 첫 번째 액세스 시 생성)로 선언하거나, 다른 특정 빈에 @DependsOn(현재 빈의 직접적인 의존성이 의미하는 것 이상으로, 다른 특정 빈이 현재 빈보다 먼저 생성되도록 함)으로 선언하는 것을 고려하세요.
Conditionally Include @Configuration Classes or @Bean Methods
임의의 시스템 상태에 따라 전체 @Configuration 클래스 또는 개별 @Bean 메서드를 조건부로 활성화하거나 비활성화하는 것이 종종 유용합니다. 이에 대한 일반적인 예 중 하나는 @Profile을 사용하여 Spring 환경에서 특정 프로필이 활성화된 경우에만 Bean을 활성화하는 것입니다(자세한 내용은 Bean 정의 프로필 참조).
@Profile은 실제로 @Conditional이라는 훨씬 더 유연한 어노테이션을 사용하여 구현됩니다. @Conditional은 @Bean이 등록되기 전에 참조해야 하는 특정 org.springframework.context.annotation.Condition 구현을 나타냅니다.
Condition 인터페이스의 구현은 true 또는 false를 반환하는 matches(…) 메서드를 제공합니다. 예를 들어, 다음 목록은 @Profile에 사용된 실제 Condition 구현을 보여줍니다.
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// Read the @Profile annotation attributes
MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
if (attrs != null) {
for (Object value : attrs.get("value")) {
if (context.getEnvironment().acceptsProfiles(((String[]) value))) {
return true;
}
}
return false;
}
return true;
}
See the @Conditional javadoc for more detail.
위 설명에 기반하여, @Conditional 애노테이션을 사용해 특정 조건에 따라 @Configuration 클래스나 @Bean 메서드를 포함하거나 제외하는 방법을 보여주는 샘플 코드를 만들어보겠습니다. 이 코드는 @Profile 애노테이션을 사용해 특정 프로파일이 활성화된 경우에만 빈을 등록하는 방법을 예시로 들고, 나아가 사용자 정의 Condition 인터페이스를 구현하여 @Conditional을 사용하는 방법도 포함합니다.
1. HikariCP 디펜던시 추가
pom.xml
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.0.1</version>
</dependency>
2. @Profile 애노테이션을 사용한 샘플 코드
AppConfig.java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import com.zaxxer.hikari.HikariDataSource;
@Configuration
public class AppConfig {
@Bean
@Profile("dev")
public DataSource devDataSource() {
// 개발 환경용 데이터소스 설정
SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
dataSource.setDriverClass(com.mysql.cj.jdbc.Driver.class);
dataSource.setUrl("jdbc:mysql://localhost:3306/sbdt_db?characterEncoding=UTF-8");
dataSource.setUsername("root");
dataSource.setPassword("1234");
return dataSource;
}
@Bean
@Profile("prod")
public DataSource prodDataSource() {
// 프로덕션 환경용 데이터소스 설정
return new HikariDataSource(); // 다른 데이터베이스 설정
}
}
MainApp.java
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MainApp {
public static void main(String[] args) {
// 프로파일 설정: "dev" 또는 "prod"
System.setProperty("spring.profiles.active", "dev");
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
DataSource dataSource = ctx.getBean(DataSource.class);
System.out.println("Using DataSource: " + dataSource.getClass().getName());
}
}
3. @Conditional 애노테이션을 사용한 사용자 정의 Condition 구현
CustomCondition.java
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
public class CustomCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// 예를 들어 특정 시스템 속성이 존재하는 경우에만 true 반환
String expectedProperty = "my.custom.property";
String propertyValue = context.getEnvironment().getProperty(expectedProperty);
return propertyValue != null && propertyValue.equals("enabled");
}
}
AppConfig.java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean
@Conditional(CustomCondition.class)
public MyService myService() {
return new MyServiceImpl();
}
}
MainApp.java
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MainApp {
public static void main(String[] args) {
// 조건에 맞는 시스템 속성 설정
System.setProperty("my.custom.property", "enabled");
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
if (ctx.containsBean("myService")) {
MyService myService = ctx.getBean(MyService.class);
System.out.println("MyService Bean is available: " + myService.getClass().getName());
} else {
System.out.println("MyService Bean is not available");
}
}
}
4. 주요 클래스 정의
MyService.java
public interface MyService {
void performService();
}
MyServiceImpl.java
public class MyServiceImpl implements MyService {
@Override
public void performService() {
System.out.println("Service is being performed.");
}
}
설명
1. @Profile 사용:
⦁ AppConfig 클래스는 @Profile 애노테이션을 사용하여 특정 프로파일이 활성화된 경우에만 빈을 등록합니다.
⦁ MainApp에서는 spring.profiles.active 속성을 설정하여 "dev" 또는 "prod" 프로파일을 활성화할 수 있습니다.
2. @Conditional 사용:
⦁ CustomCondition 클래스는 Condition 인터페이스를 구현하여, 특정 시스템 속성이 설정된 경우에만 빈을 등록하도록 합니다.
⦁ AppConfig 클래스의 myService 빈은 @Conditional을 사용하여 CustomCondition이 참일 경우에만 등록됩니다.
⦁ MainApp에서 시스템 속성을 설정하고, 해당 조건에 맞는 빈이 등록되었는지 확인합니다.
이 샘플 코드는 @Profile과 @Conditional 애노테이션을 사용하여 Spring에서 조건부로 @Configuration 클래스나 @Bean 메서드를 포함하거나 제외하는 방법을 보여줍니다. 이러한 기능을 사용하면 특정 환경이나 조건에 맞게 애플리케이션 구성을 유연하게 제어할 수 있습니다.
Combining Java and XML Configuration
생략
'Spring Framework > Spring IoC' 카테고리의 다른 글
Classpath Scanning and Managed Components (1) | 2024.11.14 |
---|---|
Customizing the Nature of a Bean (0) | 2024.11.14 |
Using the @Configuration annotation (0) | 2024.11.14 |
Using the @Bean Annotation (0) | 2024.11.14 |
Instantiating the Spring Container by Using AnnotationConfigApplicationContext (0) | 2024.11.14 |