목표 : Spring의 Anntation 설정을 할 수 있다.
이번엔 계속 XML에서 설정해온 Configuration 정보들을 Annotation으로 어떻게 할 수 있을지 알아볼 예정이다.
해당 링크를 중심으로 하나씩 알아가 보도록 하자.
Annotation-based Container Configuration
먼저 Annotation이 XML보다 Spring configuration하는 것에 있어서 더 좋은가? 에 대한 질문으로 시작한다.
답은 역시나 "상황에 따라 다르다" 이다.
XML 방식은 소스 코드 외, XML만 보고도 설정을 알 수 있다. 즉, 설정과 소스 코드의 분리가 가능하다.
그러나, 프로젝트가 커질수록 XML 관리가 복잡해지기 시작한다.
Annotation은 더 짧고 간결한 구성이 가능하지만 소스 코드와 설정의 분리가 애매해진다.
context namespace
<?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/>
</beans>
context라는 namespace를 넣어준 것에 집중하자.
그리고, <context:annotation-config/> 를 적용하며, 이제 Annotation을 통해 설정할 수 있도록 변경되었다.
@Autowired
Autowired는 Bean과 Bean간의 관계에 대해, Spring Container가 자동으로 연결해주는 것이다.
그 때, Bean의 이름, Bean의 Type등으로 관계를 설정할 수 있다.
public class MovieRecommender {
private final CustomerPreferenceDao customerPreferenceDao;
@Autowired
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
그 예시를 보자.
MovieRecommender의 생성자에 Autowired Annotation을 사용하였다.
CustomerPreferenceDao와 관계를 설정해준 것이다.
이는 이전 XML 문법의 다음과 같다.
<bean id="customerPreferenceDao" class="kr.co.test.CustomerPreferenceDao"/>
<bean id="movieRecommender" class="kr.co.test.MovieRecommender">
<constructor-arg ref="customerPreferenceDao" />
</bean>
다만, Spring 버전이 올라가면서, 생성자 주입 시, 자동 Autowired 가 될 수 있고, 필드에 쓰는 경우도 많다.
public class MovieRecommender {
private final CustomerPreferenceDao customerPreferenceDao;
// Autowired 생략 가능
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao) {
this.customerPreferenceDao = customerPreferenceDao;
}
}
@RequiredArgsConstructor // Lombok 활용
public class MovieRecommender {
private final CustomerPreferenceDao customerPreferenceDao;
}
public class MovieRecommender {
@Autowired // 필드에 설정 가능
private final CustomerPreferenceDao customerPreferenceDao;
}
@Primary
Autowired를 할 때, 이름 혹은 타입 등으로 설정할 수 있는데, 그 중, 타입으로 연결했더니 중복인 경우, 어떤 것을 Autowired를 할지 모를 경우가 있다. 그 때 활용할 수 있는 Annotation이다.
@Configuration
public class MovieConfiguration {
@Bean
@Primary
public MovieCatalog firstMovieCatalog() { ... }
@Bean
public MovieCatalog secondMovieCatalog() { ... }
// ...
}
@Configuration : Bean 설정으로 등록되면서, Spring 설정과 관련있는 Bean이라는 것을 알려주는 Annotation
@Bean : XML에서 Bean 설정하는 것 대신, Java Annotation을 통해 Bean 설정할 수 있게 도와주는 Annotation
위 예시를 보았을 때, @Primary가 없다고 가정하면 에러가 나오게 된다. (No Unique Bean)
@Qualifiers
public class MovieRecommender {
private MovieCatalog movieCatalog;
private CustomerPreferenceDao customerPreferenceDao;
@Autowired
public void prepare(@Qualifier("main") MovieCatalog movieCatalog,
CustomerPreferenceDao customerPreferenceDao) {
this.movieCatalog = movieCatalog;
this.customerPreferenceDao = customerPreferenceDao;
}
// ...
}
<?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"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean class="example.SimpleMovieCatalog">
<qualifier value="action"/>
<!-- inject any dependencies required by this bean -->
</bean>
<bean id="movieRecommender" class="example.MovieRecommender"/>
</beans>
같은 타입의 Bean을 만들 때, Quialifier는 Autowired 시, Qualifier 라는 Annotation과 Value를 넣으면, 선택하여 실행시킬 수 있다.
@Resource
@Autowired와 같은 역할을 한다고 보면된다.
약간의 차이는 Bean의 이름을 통해 주입하며, 생성자에 적용할 수 없다.
@Value
보통 Application에서 XML 외에 application.properties 라는 파일을 만들어, property를 읽어들인다.
@Configuration
@PropertySource("classpath:application.properties")
public class AppConfig { }
위와 같이, Property를 연결하는 구문을 만들고, application.properties를 만들어준다.
그리고, Key=Value 형태로 값을 저장하면, 해당 값을 가져와 쓸 수 있다.
@PostConstruct, @PreDestroy
LifeCycle과 관련된 Annotation이다.
@PostConstruct 는 Bean이 생성되기 전에 실행되는 함수이다.
@PreDestroy는 Bean의 소멸을 앞두고 실행되는 함수이다. 단, context.close()가 필요하다.
WrapUp
Annotation이라는 것이 사용자의 편의를 생각해, 만들어지다보니 암기해야할 것처럼 느껴질 수 있다.
다만, 사용을 하다보면 자연스럽게 알게되고, 자주 쓰다보면 당연스레 써지게 되기도 한다.
다만, 이 Annotation의 역할과 상황을 잘 기억하여 쓸 수 있도록 하자.
'Framework > Spring' 카테고리의 다른 글
[Spring] 환경설정은 어떻게 할 수 있을까? (0) | 2022.08.10 |
---|---|
[Spring] Classpath와 Component가 뭘까? (0) | 2022.08.02 |
[Spring] Bean의 LifeCycle는 어떻게 될까? (0) | 2022.07.31 |
[Spring] Bean Scope 가 뭘까? (0) | 2022.07.29 |
[Spring] 스프링의 DI가 뭘까? (0) | 2022.07.26 |