@Autowired
어노테이션
1. @Autowired
어노테이션의 개요
@Autowired
어노테이션은 Spring에서 의존성 주입(Dependency Injection)을 처리하는 중요한 도구입니다. 이 어노테이션은 필드, 메서드, 생성자에 붙여 사용되며, Spring 컨테이너가 관리하는 빈(bean) 중에서 해당 타입의 빈을 자동으로 주입하게 됩니다.
2. @Autowired
어노테이션 사용 예시
2.1. 생성자 주입(Constructor Injection)
@Component
public class MovieRecommender {
private final CustomerPreferenceDao customerPreferenceDao;
@Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
}
- 이 코드에서
MovieRecommender
클래스는CustomerPreferenceDao
라는 의존성을 생성자를 통해 주입받습니다. - Spring 4.3 이후, 클래스에 생성자가 하나만 있을 경우
@Autowired
를 생략해도 됩니다. 그러나 여러 생성자가 있을 경우, Spring이 어느 생성자를 사용할지 알 수 있도록 하나 이상의 생성자에@Autowired
를 지정해야 합니다.
2.2. 세터 주입(Setter Injection)
@Component
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Autowired
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}
setMovieFinder
메서드에@Autowired
를 붙여, Spring이 해당 메서드를 통해MovieFinder
빈을 주입합니다.- 이는 전통적인 세터 주입 방식으로, 메서드 이름과 상관없이 주입할 수 있습니다.
2.3. 메서드 주입(Method Injection) - 복수 인자 지원
@Component
public class MovieRecommender {
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public void prepare(MovieCatalog movieCatalog, CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
}
prepare
메서드처럼 여러 인자를 가진 메서드에@Autowired
를 사용해 복수의 의존성을 주입할 수 있습니다.
2.4. 필드 주입(Field Injection)
@Component
public class MovieRecommender {
private final CustomerPreferenceDao customerPreferenceDao;
@Autowired
private MovieCatalog movieCatalog;
@Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
}
- 필드에 직접
@Autowired
를 붙여 주입할 수도 있습니다. 필드 주입은 간편하지만, 테스트가 어렵고, 클래스가 Spring에 강하게 결합된다는 단점이 있습니다.
3. 특수한 상황에서의 @Autowired
사용
3.1. 배열 및 컬렉션 타입의 주입
@Component
public class MovieRecommender {
@Autowired
private MovieCatalog[] movieCatalogs;
}
@Component
public class MovieRecommender {
private Set<MovieCatalog> movieCatalogs;
@Autowired
public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {
this.movieCatalogs = movieCatalogs;
}
}
- 배열이나 컬렉션 형태로 여러 빈을 주입받을 수 있습니다. 이때,
MovieCatalog
타입의 모든 빈이 주입됩니다. - 이러한 주입에서
@Order
나@Priority
를 사용하여 배열이나 컬렉션의 순서를 지정할 수도 있습니다.
3.2. 맵(Map) 타입의 주입
@Component
public class MovieRecommender {
private Map<String, MovieCatalog> movieCatalogs;
@Autowired
public void setMovieCatalogs(Map<String, MovieCatalog> movieCatalogs) {
this.movieCatalogs = movieCatalogs;
}
}
Map
형태로 주입받을 수도 있습니다. 이 경우, 키는 빈의 이름(String), 값은 해당 타입의 빈이 됩니다.- 이러한 방법은 각 빈에 이름을 붙여 관리할 때 유용합니다.
4. 선택적 의존성 주입
4.1. @Autowired(required = false)
@Component
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Autowired(required = false)
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}
@Autowired
의required
속성을false
로 설정하면, 해당 빈이 없어도 애플리케이션이 정상적으로 동작할 수 있도록 할 수 있습니다.- 이 옵션을 통해 선택적으로 의존성을 주입받을 수 있습니다.
4.2. Optional
사용
@Component
public class SimpleMovieLister {
@Autowired
public void setMovieFinder(Optional<MovieFinder> movieFinder) {
// ...
}
}
- Java 8의
Optional
을 사용하여, 주입받을 빈이 선택적임을 명시적으로 표현할 수 있습니다.
4.3. @Nullable
사용
@Component
public class SimpleMovieLister {
@Autowired
public void setMovieFinder(@Nullable MovieFinder movieFinder) {
// ...
}
}
@Nullable
어노테이션을 사용하여, 해당 의존성이 없을 때 null 값이 주입되도록 할 수 있습니다. 이는 선택적 의존성을 처리하는 또 다른 방법입니다.
5. 특별한 타입의 자동 주입
@Component
public class MovieRecommender {
@Autowired
private ApplicationContext context;
public MovieRecommender() {
}
}
ApplicationContext
,BeanFactory
,Environment
등의 Spring 내장 인터페이스들도 자동 주입이 가능합니다.- 이러한 인터페이스들은 Spring의 내부 동작에 깊이 관여하므로, 특별한 설정 없이도 자동으로 주입됩니다.
@Primary
어노테이션을 사용한 Spring의 자동 주입 세밀 조정
1. @Primary
어노테이션의 필요성
Spring에서 의존성 주입을 할 때, 같은 타입의 빈이 여러 개 있을 경우 어떤 빈을 주입할지 결정해야 하는 상황이 발생할 수 있습니다. 기본적으로, Spring은 타입 기반으로 자동 주입을 시도하지만, 여러 후보가 있는 경우에는 특정한 빈을 우선적으로 주입할 방법이 필요합니다. 이때 사용하는 것이 바로 @Primary
어노테이션입니다.
@Primary
어노테이션은 여러 후보 빈 중에서 특정 빈을 우선적으로 선택하게 만듭니다. 만약 여러 빈 중에 하나의 @Primary
빈이 존재한다면, 해당 빈이 자동으로 주입됩니다.
2. @Primary
어노테이션의 사용 예시
다음은 @Primary
어노테이션을 사용하여 두 개의 MovieCatalog
빈 중 첫 번째 빈을 우선적으로 주입하는 예제입니다.
2.1. 자바 설정(Java Configuration) 예제
@Configuration
public class MovieConfiguration {
@Bean
@Primary
public MovieCatalog firstMovieCatalog() {
// 첫 번째 MovieCatalog 빈 설정
return new FirstMovieCatalog();
}
@Bean
public MovieCatalog secondMovieCatalog() {
// 두 번째 MovieCatalog 빈 설정
return new SecondMovieCatalog();
}
}
MovieConfiguration
클래스에서firstMovieCatalog
빈이@Primary
로 지정되었습니다.- 이 설정에 따라,
MovieCatalog
타입의 빈을 자동 주입할 때, Spring은firstMovieCatalog
를 우선적으로 선택합니다.
2.2. @Primary
를 사용한 자동 주입
@Primary
로 설정된 빈이 실제로 어떻게 주입되는지 확인해보겠습니다.
@Component
public class MovieRecommender {
@Autowired
private MovieCatalog movieCatalog;
// ...
}
MovieRecommender
클래스에서MovieCatalog
타입의 빈이 주입됩니다.- 이때,
MovieCatalog
빈 중@Primary
로 지정된firstMovieCatalog
가 주입됩니다.
2.3. XML 설정(XML Configuration) 예제
Spring에서 XML을 사용하여 빈을 정의하는 경우에도 @Primary
와 같은 기능을 사용할 수 있습니다. 다음은 XML 설정 예제입니다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean class="example.SimpleMovieCatalog" primary="true">
<!-- 해당 빈이 주입될 때 우선적으로 사용됨 -->
</bean>
<bean class="example.SimpleMovieCatalog">
<!-- 이 빈은 기본적으로 주입되지 않음 -->
</bean>
<bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>
- 첫 번째
SimpleMovieCatalog
빈이primary="true"
로 설정되어 있어, 주입 시 이 빈이 우선 선택됩니다. - 두 번째
SimpleMovieCatalog
빈은 주입 시 선택되지 않습니다. movieRecommender
빈은@Autowired
된MovieCatalog
빈을 주입받을 때 첫 번째SimpleMovieCatalog
를 주입받게 됩니다.
@Qualifier
어노테이션을 사용한 Spring의 자동 주입 세밀 조정
1. @Qualifier
어노테이션의 필요성
@Primary
어노테이션은 여러 빈 중 하나를 우선적으로 주입할 때 유용하지만, 특정 상황에서는 더 세밀한 제어가 필요할 수 있습니다. 이때 사용하는 것이 바로 @Qualifier
어노테이션입니다. @Qualifier
는 특정 빈을 선택하는 데 필요한 추가적인 정보를 제공하여, 동일한 타입의 여러 빈 중에서 정확히 어떤 빈을 주입할지 명확하게 지정할 수 있게 합니다.
2. @Qualifier
어노테이션의 사용 예시
2.1. 필드에 @Qualifier
사용
가장 기본적인 예로, @Qualifier
를 필드에 직접 적용하여 특정 빈을 주입할 수 있습니다.
@Component
public class MovieRecommender {
@Autowired
@Qualifier("main")
private MovieCatalog movieCatalog;
// ...
}
- 이 예제에서
MovieCatalog
타입의 빈 중에서main
이라는 이름의 빈이 주입됩니다. @Qualifier("main")
을 사용하여 주입할 빈을 명확히 지정할 수 있습니다.
2.2. 메서드 인자에 @Qualifier
사용
@Qualifier
는 생성자나 메서드의 인자에도 적용할 수 있습니다.
@Component
public class MovieRecommender {
private final MovieCatalog movieCatalog;
private final CustomerPreferenceDao customerPreferenceDao;
@Autowired
public void prepare(@Qualifier("main") MovieCatalog movieCatalog,
CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
prepare
메서드에서MovieCatalog
타입의 빈 중에서main
이라는 이름의 빈이 주입되도록 지정합니다.- 다른 인자
CustomerPreferenceDao
는 타입에 따라 자동으로 주입됩니다.
2.3. XML 설정에서의 @Qualifier
사용
Spring XML 설정에서도 @Qualifier
와 같은 효과를 낼 수 있습니다. 다음은 XML 설정 예제입니다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
<bean class="example.SimpleMovieCatalog">
<qualifier value="main"/>
<!-- 필요한 의존성 주입 -->
</bean>
<bean class="example.SimpleMovieCatalog">
<qualifier value="action"/>
<!-- 필요한 의존성 주입 -->
</bean>
<bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>
main
과action
이라는qualifier
값을 가진 두 개의SimpleMovieCatalog
빈이 정의되어 있습니다.movieRecommender
빈에서main
또는action
이라는qualifier
값을 통해 특정 빈을 주입받을 수 있습니다.
2.4. 컬렉션과 @Qualifier
사용
@Qualifier
를 사용하여 여러 빈을 컬렉션으로 주입받을 수도 있습니다.
@Component
public class MovieRecommender {
private Set<MovieCatalog> actionCatalogs;
@Autowired
public void setActionCatalogs(@Qualifier("action") Set<MovieCatalog> actionCatalogs) {
this.actionCatalogs = actionCatalogs;
}
// ...
}
- 여러
MovieCatalog
빈이action
이라는qualifier
값을 가지고 있다면, 이 빈들이 모두Set<MovieCatalog>
에 주입됩니다.
2.5. 커스텀 @Qualifier
어노테이션 사용
자신만의 커스텀 @Qualifier
어노테이션을 정의하여 사용할 수도 있습니다.
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Genre {
String value();
}
@Component
public class MovieRecommender {
@Autowired
@Genre("Action")
private MovieCatalog actionCatalog;
@Autowired
@Genre("Comedy")
private MovieCatalog comedyCatalog;
// ...
}
@Genre
라는 커스텀 어노테이션을 정의하여, 특정 장르의MovieCatalog
빈을 주입받도록 설정할 수 있습니다.- XML 설정에서 이 커스텀 어노테이션을 사용하여 빈을 정의할 수도 있습니다.
<bean class="example.SimpleMovieCatalog"> <qualifier type="Genre" value="Action"/> <!-- 필요한 의존성 주입 --> </bean>
```
Spring Framework에서 제네릭(Generic) 타입을 사용하여 자동 주입 시 빈을 구분하는 방법에 대해 설명드리겠습니다. 제네릭을 사용하면 @Qualifier
어노테이션 없이도 특정 타입의 빈을 선택할 수 있습니다.
1. 제네릭을 사용한 자동 주입의 개요
Spring에서는 제네릭 타입을 사용하여 자동 주입 시 특정 빈을 구분할 수 있습니다. 이는 @Qualifier
를 사용하는 대신, 제네릭 타입 자체가 빈을 구분하는 역할을 합니다. 이 방법을 사용하면 코드를 더 간결하게 작성할 수 있으며, 제네릭 타입 정보를 활용하여 더욱 세밀하게 빈을 관리할 수 있습니다.
2. 제네릭을 사용한 자동 주입의 예시
다음은 제네릭 타입을 사용하여 빈을 구분하고 주입하는 예제입니다.
2.1. 빈 설정
먼저, 제네릭 인터페이스를 구현하는 두 개의 빈을 설정해 보겠습니다.
@Configuration
public class MyConfiguration {
@Bean
public StringStore stringStore() {
return new StringStore();
}
@Bean
public IntegerStore integerStore() {
return new IntegerStore();
}
}
StringStore
는Store<String>
을 구현하고,IntegerStore
는Store<Integer>
를 구현합니다.- 이 두 빈은 각각 제네릭 타입에 따라 구분됩니다.
2.2. 제네릭을 사용한 빈 주입
이제, Store<String>
과 Store<Integer>
타입의 빈을 주입하는 코드를 살펴보겠습니다.
@Component
public class MyService {
@Autowired
private Store<String> s1; // <String> 타입의 Store 빈 주입 (stringStore 빈)
@Autowired
private Store<Integer> s2; // <Integer> 타입의 Store 빈 주입 (integerStore 빈)
}
s1
필드는Store<String>
타입의 빈을 주입받으며, 이는stringStore
빈입니다.s2
필드는Store<Integer>
타입의 빈을 주입받으며, 이는integerStore
빈입니다.- 제네릭 타입이 자동으로
@Qualifier
와 같은 역할을 하여 적절한 빈을 선택합니다.
2.3. 제네릭을 사용한 컬렉션 주입
Spring은 제네릭 타입을 사용하여 컬렉션도 주입할 수 있습니다. 예를 들어, 특정 제네릭 타입을 가진 모든 빈을 리스트(List)로 주입할 수 있습니다.
@Component
public class MyService {
@Autowired
private List<Store<Integer>> s; // <Integer> 타입의 Store 빈들만 주입
}
List<Store<Integer>>
타입의 필드s
에는Store<Integer>
타입의 모든 빈이 주입됩니다.Store<String>
타입의 빈은 이 리스트에 포함되지 않습니다.- 이렇게 제네릭을 사용하면 여러 빈을 쉽게 그룹화하여 관리할 수 있습니다.
CustomAutowireConfigurer
를 사용한 커스텀 자동 주입 구성
Spring Framework에서 CustomAutowireConfigurer
를 사용하여 커스텀 자동 주입(Autowiring)을 설정하는 방법에 대해 살펴보겠습니다. CustomAutowireConfigurer
는 Spring의 @Qualifier
어노테이션을 사용하지 않고도 커스텀 어노테이션을 활용해 자동 주입을 설정할 수 있는 유용한 도구입니다.
1. CustomAutowireConfigurer
개요
CustomAutowireConfigurer
는 Spring의 BeanFactoryPostProcessor
중 하나로, 커스텀 어노테이션을 사용해 의존성 주입 시 후보 빈을 결정할 수 있게 해줍니다. 이 기능은 Spring의 @Qualifier
어노테이션을 확장하여, 커스텀 어노테이션을 사용해 보다 유연한 의존성 주입을 가능하게 합니다.
2. CustomAutowireConfigurer
설정 예시
먼저, CustomAutowireConfigurer
를 사용하여 커스텀 어노테이션을 등록하는 방법을 살펴보겠습니다.
2.1. XML 설정에서 CustomAutowireConfigurer
사용
다음은 XML 설정에서 CustomAutowireConfigurer
를 사용하여 커스텀 어노테이션을 등록하는 방법을 보여줍니다.
<bean id="customAutowireConfigurer"
class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
<property name="customQualifierTypes">
<set>
<value>example.CustomQualifier</value>
</set>
</property>
</bean>
customAutowireConfigurer
빈은CustomAutowireConfigurer
클래스를 사용하여 정의됩니다.customQualifierTypes
속성에CustomQualifier
라는 커스텀 어노테이션을 등록하여, 이 어노테이션을 사용해 자동 주입을 설정할 수 있도록 합니다.
2.2. 커스텀 어노테이션 정의
이제, XML 설정에서 사용된 CustomQualifier
라는 커스텀 어노테이션을 정의해보겠습니다.
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface CustomQualifier {
String value();
}
CustomQualifier
는 필드나 메서드 파라미터에 적용될 수 있는 커스텀 어노테이션입니다.- 이 어노테이션은
value
속성을 가지고 있으며, 이를 통해 특정 빈을 지정할 수 있습니다.
2.3. CustomQualifier
를 사용한 자동 주입
커스텀 어노테이션을 사용하여 특정 빈을 주입하는 방법을 살펴보겠습니다.
@Component
public class MyService {
@Autowired
@CustomQualifier("special")
private MyRepository myRepository;
// ...
}
MyService
클래스에서MyRepository
타입의 빈을 주입받을 때,@CustomQualifier("special")
어노테이션을 사용하여 특정한MyRepository
빈을 주입받습니다.
3. 자동 주입 후보 결정
Spring의 AutowireCandidateResolver
는 자동 주입 후보를 결정할 때 다음과 같은 요소를 고려합니다:
autowire-candidate
속성: 각 빈 정의에서 이 값이 true로 설정된 빈만 주입 후보가 됩니다.default-autowire-candidates
패턴:<beans/>
요소에 설정된 기본 패턴에 따라 후보가 결정됩니다.@Qualifier
어노테이션과 커스텀 어노테이션:@Qualifier
또는CustomAutowireConfigurer
에 등록된 커스텀 어노테이션이 적용된 빈이 주입 후보가 됩니다.
만약 여러 빈이 주입 후보로 선택되면, primary
속성이 true로 설정된 빈이 우선적으로 선택됩니다.
@Resource
어노테이션을 사용한 의존성 주입
Spring Framework에서 @Resource
어노테이션을 사용하여 의존성을 주입하는 방법에 대해 살펴보겠습니다. @Resource
는 JSR-250 표준 어노테이션으로, 주로 Jakarta EE 환경에서 사용되지만, Spring에서도 지원됩니다.
1. @Resource
어노테이션 개요
@Resource
어노테이션은 필드나 세터 메서드에 적용되어 의존성을 주입하는 데 사용됩니다. 이 어노테이션은 주입할 빈을 이름으로 찾는 방식(즉, by-name)을 기본으로 합니다. 하지만 이름이 지정되지 않으면, 필드명이나 세터 메서드의 프로퍼티명을 기반으로 빈을 주입합니다.
2. @Resource
어노테이션 사용 예시
2.1. 이름을 지정한 @Resource
사용
다음은 @Resource
어노테이션을 사용하여 특정 이름의 빈을 주입하는 예제입니다.
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Resource(name="myMovieFinder")
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}
@Resource(name="myMovieFinder")
어노테이션을 사용하여, 이름이myMovieFinder
인 빈을setMovieFinder
메서드에 주입합니다.- 이 방식은 빈의 이름을 명확히 지정하여 주입할 때 유용합니다.
2.2. 이름을 지정하지 않은 @Resource
사용
그럼 이제, 이름을 지정하지 않고 @Resource
를 사용하는 방법을 살펴보겠습니다.
public class SimpleMovieLister {
private MovieFinder movieFinder;
@Resource
public void setMovieFinder(MovieFinder movieFinder) {
this.movieFinder = movieFinder;
}
}
- 이름을 지정하지 않으면,
@Resource
는 기본적으로 필드명(movieFinder
)을 빈 이름으로 사용하여 주입합니다. - 즉,
movieFinder
라는 이름의 빈이 자동으로 주입됩니다.
3. @Resource
를 사용한 필드 주입
@Resource
어노테이션은 필드에도 직접 사용할 수 있습니다. 다음은 필드에 @Resource
를 사용하여 빈을 주입하는 예제입니다.
public class MovieRecommender {
@Resource
private CustomerPreferenceDao customerPreferenceDao;
@Resource
private ApplicationContext context;
public MovieRecommender() {
}
}
customerPreferenceDao
필드는customerPreferenceDao
라는 이름의 빈을 찾거나, 타입이CustomerPreferenceDao
인 빈을 주입받습니다.context
필드는ApplicationContext
타입의 빈을 주입받으며, 이는 Spring에서 자동으로 해결 가능한 의존성 중 하나입니다.
4. @Resource
어노테이션의 동작 방식
@Resource
어노테이션은 다음과 같은 순서로 주입할 빈을 찾습니다:
- 이름 매칭:
@Resource
에 지정된 이름으로 빈을 찾습니다. 이름이 지정되지 않았다면 필드명이나 메서드명에서 이름을 추출하여 사용합니다. - 타입 매칭: 이름으로 찾지 못하면, 해당 필드나 메서드의 타입과 일치하는 빈을 주입합니다. 예를 들어,
ApplicationContext
와 같은 Spring에서 자동으로 해결 가능한 타입은 특별한 설정 없이도 주입됩니다.
5. 최근 @Resource
어노테이션 사용 감소와 그 이유
최근에는 @Resource
어노테이션이 점점 덜 사용되고 있습니다. 그 이유는 다음과 같습니다:
- 타입 기반 주입의 선호: Spring에서는 이름 기반 주입보다는 타입 기반 주입이 더 선호됩니다.
@Autowired
어노테이션은 타입에 따라 빈을 자동으로 주입하므로, 코드를 더 간결하게 유지할 수 있습니다. 또한,@Qualifier
를 함께 사용하면 다중 빈 상황에서도 정확한 빈을 선택할 수 있어 더 유연한 구성이 가능합니다.
- Spring Boot의 사용 증가: Spring Boot 프로젝트에서는
@Resource
보다@Autowired
와@Qualifier
, 그리고 프로퍼티 주입을 위한@Value
어노테이션이 더 일반적으로 사용됩니다. 이는 코드의 일관성을 유지하고, Spring Boot의 자동 설정 기능과 더 잘 맞기 때문입니다.
- 표준 자바 어노테이션의 축소:
@Resource
는 JDK 11 이후로 더 이상 기본 자바 라이브러리의 일부가 아니며, Jakarta EE로 이전되었습니다. 이는 표준 자바 어노테이션에 의존하는 대신 Spring 고유의 어노테이션을 사용하는 트렌드를 가속화했습니다.
@Value
어노테이션을 사용한 프로퍼티 주입
Spring Framework에서 @Value
어노테이션을 사용하여 외부화된 프로퍼티를 주입하는 방법에 대해 설명드리겠습니다. @Value
어노테이션은 주로 환경 설정 파일이나 시스템 속성 등에서 값을 가져와 주입할 때 사용됩니다.
1. @Value
어노테이션 개요
@Value
어노테이션은 Spring에서 외부화된 프로퍼티를 주입하는 데 사용됩니다. 이 어노테이션은 문자열, 숫자, 배열 등 다양한 타입으로 변환하여 값을 주입할 수 있으며, Spring Expression Language (SpEL)을 사용하여 동적으로 값을 계산할 수도 있습니다.
2. @Value
어노테이션 사용 예시
2.1. 기본 사용 예
가장 기본적인 사용 예로, application.properties
파일에서 값을 가져와 주입하는 방법을 살펴보겠습니다.
@Component
public class MovieRecommender {
private final String catalog;
public MovieRecommender(@Value("${catalog.name}") String catalog) {
this.catalog = catalog;
}
}
@Value("${catalog.name}")
어노테이션을 사용하여application.properties
파일에서catalog.name
프로퍼티의 값을 가져와catalog
필드에 주입합니다.- 예를 들어,
application.properties
파일에catalog.name=MovieCatalog
가 설정되어 있다면,catalog
필드에는"MovieCatalog"
가 주입됩니다.
2.2. @PropertySource
와 함께 사용
프로퍼티 파일을 명시적으로 지정하여 사용하는 경우, @PropertySource
어노테이션을 사용하여 파일을 지정할 수 있습니다.
@Configuration
@PropertySource("classpath:application.properties")
public class AppConfig { }
@PropertySource("classpath:application.properties")
는application.properties
파일을 로드하여 해당 파일의 프로퍼티를 사용하도록 설정합니다.- 이를 통해
@Value
어노테이션이 해당 파일에서 값을 읽어올 수 있게 됩니다.
2.3. 기본값 설정
만약 지정된 프로퍼티가 존재하지 않을 경우 기본값을 설정할 수도 있습니다.
@Component
public class MovieRecommender {
private final String catalog;
public MovieRecommender(@Value("${catalog.name:defaultCatalog}") String catalog) {
this.catalog = catalog;
}
}
@Value("${catalog.name:defaultCatalog}")
는catalog.name
프로퍼티가 존재하지 않을 경우"defaultCatalog"
를 기본값으로 주입합니다.
3. 커스텀 타입 변환기 사용
Spring의 @Value
어노테이션은 기본적으로 문자열 값을 다른 타입으로 변환할 수 있지만, 커스텀 타입 변환기를 정의하여 사용할 수도 있습니다.
@Configuration
public class AppConfig {
@Bean
public ConversionService conversionService() {
DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService();
conversionService.addConverter(new MyCustomConverter());
return conversionService;
}
}
conversionService
빈을 정의하여, 커스텀 타입 변환기를 추가할 수 있습니다.- 이를 통해
@Value
어노테이션이 지정된 문자열 값을 원하는 커스텀 타입으로 변환할 수 있습니다.
4. SpEL을 사용한 동적 값 계산
@Value
어노테이션은 Spring Expression Language(SpEL)를 사용하여 동적으로 값을 계산할 수 있습니다.
@Component
public class MovieRecommender {
private final String catalog;
public MovieRecommender(@Value("#{systemProperties['user.catalog'] + 'Catalog'}") String catalog) {
this.catalog = catalog;
}
}
@Value("#{systemProperties['user.catalog'] + 'Catalog'}")
는 시스템 속성user.catalog
에"Catalog"
를 추가한 값을 주입합니다.- SpEL을 사용하면 이처럼 복잡한 계산이나 조건에 따라 주입할 값을 동적으로 결정할 수 있습니다.
4.1. 복잡한 데이터 구조 주입
SpEL을 사용하여 복잡한 데이터 구조를 주입할 수도 있습니다.
@Component
public class MovieRecommender {
private final Map<String, Integer> countOfMoviesPerCatalog;
public MovieRecommender(@Value("#{{'Thriller': 100, 'Comedy': 300}}") Map<String, Integer> countOfMoviesPerCatalog) {
this.countOfMoviesPerCatalog = countOfMoviesPerCatalog;
}
}
@Value
어노테이션을 사용하여 Map<String, Integer> 타입의 데이터를 주입할 수 있습니다.- SpEL을 사용하여 복잡한 데이터 구조를 정의하고 이를 주입할 수 있습니다.
@PostConstruct
와 @PreDestroy
을 사용한 빈의 라이프사이클 관리
Spring Framework에서 빈의 초기화와 소멸 시점을 관리하는 데 사용되는 @PostConstruct
와 @PreDestroy
어노테이션에 대해 설명드리겠습니다. 이 어노테이션들은 JSR-250 표준에 속하며, Spring 2.5부터 지원됩니다.
1. @PostConstruct
와 @PreDestroy
어노테이션 개요
@PostConstruct
와 @PreDestroy
어노테이션은 각각 빈의 초기화 시점과 소멸 시점에 호출되는 메서드를 지정하는 데 사용됩니다. 이 어노테이션들은 CommonAnnotationBeanPostProcessor에 의해 인식되며, Spring의 ApplicationContext에 등록된 빈이 특정 라이프사이클 이벤트에서 호출되도록 합니다.
@PostConstruct
: 빈이 초기화된 후(즉, 의존성 주입이 완료된 후) 호출됩니다.@PreDestroy
: 빈이 소멸되기 전에 호출됩니다.
2. @PostConstruct
와 @PreDestroy
어노테이션 사용 예시
2.1. @PostConstruct
사용 예
다음은 @PostConstruct
어노테이션을 사용하여 빈의 초기화 시점에 캐시를 미리 채우는 예제입니다.
@Component
public class CachingMovieLister {
@PostConstruct
public void populateMovieCache() {
// 초기화 시점에 영화 캐시를 채웁니다...
}
}
@PostConstruct
어노테이션이 붙은populateMovieCache
메서드는 빈이 생성되고 의존성 주입이 완료된 후 자동으로 호출됩니다.- 이 메서드에서 필요한 초기화 작업을 수행할 수 있습니다.
2.2. @PreDestroy
사용 예
다음은 @PreDestroy
어노테이션을 사용하여 빈이 소멸되기 전에 캐시를 비우는 예제입니다.
@Component
public class CachingMovieLister {
@PreDestroy
public void clearMovieCache() {
// 소멸되기 전에 영화 캐시를 비웁니다...
}
}
@PreDestroy
어노테이션이 붙은clearMovieCache
메서드는 빈이 소멸되기 전에 호출됩니다.- 이 메서드에서 리소스를 정리하거나 필요한 종료 작업을 수행할 수 있습니다.
3. Spring에서의 라이프사이클 관리
이 어노테이션들을 사용하기 위해서는 CommonAnnotationBeanPostProcessor
가 Spring의 ApplicationContext에 등록되어 있어야 합니다. 일반적으로 Spring Boot 애플리케이션에서는 자동으로 이 설정이 활성화되므로 별도의 설정이 필요하지 않습니다.
3.1. JDK 9 이후의 변화
@PostConstruct
와 @PreDestroy
어노테이션은 원래 JDK 6에서 JDK 8까지 표준 Java 라이브러리의 일부였습니다. 그러나 JDK 9 이후 javax.annotation
패키지가 Java의 기본 모듈에서 제거되었고, JDK 11부터는 완전히 삭제되었습니다. 따라서 이제는 jakarta.annotation-api
아티팩트를 Maven Central에서 다운로드하여 클래스패스에 추가해야 합니다.
1. 어노테이션 기반 설정 개요
Spring Framework에서는 XML 파일을 사용하지 않고도 어노테이션을 사용하여 설정을 정의할 수 있습니다. 이때, 자바 클래스를 이용하여 Spring 컨테이너를 설정하게 되며, 주로 @Configuration
과 @Bean
어노테이션을 사용하여 빈을 정의하고 관리합니다.
1.1. @Configuration
어노테이션
@Configuration
어노테이션은 하나 이상의 @Bean
어노테이션이 선언된 메서드를 포함하는 클래스를 나타냅니다. 이 클래스는 애플리케이션 컨텍스트에서 빈 팩토리로 작동합니다.
@Configuration
public class AppConfig {
@Bean
public MovieCatalog movieCatalog() {
return new MovieCatalog();
}
@Bean
public MovieRecommender movieRecommender() {
return new MovieRecommender(movieCatalog());
}
}
AppConfig
클래스는@Configuration
어노테이션을 사용하여 Spring 설정 클래스로 선언되었습니다.movieCatalog()
와movieRecommender()
메서드는 각각@Bean
어노테이션으로 빈을 정의합니다.- Spring 컨테이너는 이 메서드를 호출하여 빈을 생성하고 관리합니다.
1.2. @Bean
어노테이션
@Bean
어노테이션은 메서드 레벨에서 선언되며, 해당 메서드가 반환하는 객체를 Spring 컨테이너에서 관리하는 빈으로 등록합니다. 이를 통해 의존성 주입이 필요한 객체를 직접 구성할 수 있습니다.
@Bean
public MovieCatalog movieCatalog() {
return new MovieCatalog();
}
movieCatalog()
메서드는MovieCatalog
타입의 빈을 생성하며, Spring 컨테이너는 이 빈을 관리하고 다른 빈에서 필요할 때 주입합니다.
2. 컴포넌트 스캔과 @ComponentScan
Spring에서는 수동으로 모든 빈을 정의하지 않고도 자동으로 빈을 스캔하여 등록할 수 있습니다. @ComponentScan
어노테이션을 사용하면 특정 패키지를 스캔하여, 그 안에 정의된 @Component
, @Service
, @Repository
, @Controller
등의 어노테이션이 붙은 클래스를 자동으로 빈으로 등록할 수 있습니다.
2.1. @ComponentScan
사용 예시
@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
}
AppConfig
클래스는@ComponentScan
어노테이션을 사용하여com.example
패키지를 스캔합니다.- 이 패키지 안에서
@Component
등의 어노테이션이 붙은 모든 클래스가 자동으로 Spring 빈으로 등록됩니다.
2.2. @Component
어노테이션
@Component
는 빈으로 등록될 수 있는 클래스를 나타내는 일반적인 어노테이션입니다. 이 외에도 특별한 용도의 어노테이션(@Service
, @Repository
, @Controller
)이 있으며, Spring에서는 각각의 역할에 맞게 빈을 생성하고 관리합니다.
@Component
public class MovieCatalog {
// ...
}
MovieCatalog
클래스에@Component
어노테이션을 추가하면,@ComponentScan
을 통해 자동으로 빈으로 등록됩니다.
3. 프로파일 관리와 @Profile
어노테이션
Spring에서는 환경별로 다른 설정을 적용할 수 있도록 @Profile
어노테이션을 제공합니다. 이 어노테이션을 사용하면 특정 프로파일에서만 활성화되는 빈을 정의할 수 있습니다.
@Configuration
public class DataSourceConfig {
@Bean
@Profile("development")
public DataSource devDataSource() {
// 개발용 데이터 소스 설정
return new DataSource("devDB");
}
@Bean
@Profile("production")
public DataSource prodDataSource() {
// 운영용 데이터 소스 설정
return new DataSource("prodDB");
}
}
@Profile("development")
어노테이션을 사용하여 개발 환경에서만 활성화되는devDataSource
빈을 정의할 수 있습니다.- 마찬가지로
@Profile("production")
을 통해 운영 환경에서 사용할prodDataSource
빈을 정의합니다.
4. @Import
를 사용한 설정 클래스 분리
설정 클래스가 많아지면 코드가 복잡해질 수 있습니다. 이때 @Import
어노테이션을 사용하여 설정 클래스를 분리하고, 하나의 설정 클래스에서 다른 설정 클래스를 불러올 수 있습니다.
@Configuration
@Import({DataSourceConfig.class, AnotherConfig.class})
public class AppConfig {
}
AppConfig
클래스에서@Import
어노테이션을 사용하여DataSourceConfig
와AnotherConfig
클래스를 불러옵니다.- 이를 통해 설정 클래스를 모듈화하여 관리할 수 있습니다.
참고자료 : Spring 공식 문서의 Annotation-based Container Configuration
'Spring Study' 카테고리의 다른 글
핸들러 메서드(Handler Method) - 컨트롤러 (0) | 2024.10.10 |
---|---|
리플렉션 (1) | 2024.10.08 |
Java Instrument API vs ASM(Abstract Syntax Manipulation) (0) | 2024.09.03 |
Mixin Pattern (자바에선 다중상속 허용X -> 믹스인디자인패턴으로 흉내) (0) | 2024.08.28 |
Proxy Pattern ( Delegate Pattern 에서의 '위임' 과의 차이 ) (0) | 2024.08.28 |