@Import, @ImportAutoConfiguration 애너테이션
0. 들어가면서
Spring 프레임워크에서 특정 애너테이션만으로 많은 기능들이 빈(bean)을 통해 주입됩니다.
무엇을 기준으로 필요한 빈들이 주입되는지 궁금했는데, 최근 @DataJpaTest
애너테이션과 관련된 포스트를 작성하면서 스프링 애너테이션에 대해 조금 더 알게 되었습니다.
이번 포스트에선 제가 알게된 내용들을 정리하였습니다.
1. @Import 애너테이션
Indicates one or more component classes to import
@Import
애너테이션은 임포트(import)하기 위한 클래스들을 명시적으로 표시합니다.
임포트 된 클래스들은 빈 객체로 추가됩니다.
공식 문서를 보면 다음과 같은 조건을 가진 대상을 @Import
애너테이션에 추가하여 사용하라고 되어 있습니다.
@Configuration
애너테이션이 추가된 클래스- 해당 클래스에서
@Bean
애너테이션으로 정의된 빈들도 모두 사용 가능합니다.
- 해당 클래스에서
@Component
,@Service
애너테이션이 붙은 클래스
1.1. @Import 활용 예제
간단한 테스트 코드를 통해 빈들이 정상적으로 주입되는지 확인해보겠습니다.
1.1.1. CustomConfiguration 클래스
@Configuration
애너테이션을 붙혀서 빈(bean) 객체들을 정의한 설정 클래스입니다.FirstBean
,SecondBean
클래스를 빈으로 정의합니다.
package blog.in.action.config;
import blog.in.action.beans.FirstBean;
import blog.in.action.beans.SecondBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CustomConfiguration {
@Bean
public FirstBean firstBean() {
return new FirstBean();
}
@Bean
public SecondBean secondBean() {
return new SecondBean();
}
}
1.1.2. POJO 클래스
- 순수한 자바 클래스이며 별도로 기능은 없습니다.
package blog.in.action.beans;
public class FirstBean {
}
package blog.in.action.beans;
public class SecondBean {
}
1.1.3. ThirdBean 클래스
@Component
애너테이션이 붙은 클래스이며 빈 역할을 수행합니다.
package blog.in.action.beans;
import org.springframework.stereotype.Component;
@Component
public class ThirdBean {
}
1.1.4. ImportTests 클래스
@Import
애너테이션에 빈으로써 필요한 클래스들을 명시적으로 추가합니다.@Autowired
애너테이션에 의해 빈 객체들이 주입 받는지 테스트를 통해 확인합니다.
package action.in.blog;
import blog.in.action.beans.FirstBean;
import blog.in.action.beans.SecondBean;
import blog.in.action.beans.ThirdBean;
import blog.in.action.config.CustomConfiguration;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.notNullValue;
@Import(value = {
CustomConfiguration.class,
ThirdBean.class
})
@ExtendWith({SpringExtension.class})
public class ImportTests {
@Autowired
FirstBean firstBean;
@Autowired
SecondBean secondBean;
@Autowired
ThirdBean thirdBean;
@Test
public void whenRunTestWithSpringExtension_thenAllBeansNotNull() {
assertThat(firstBean, notNullValue());
assertThat(secondBean, notNullValue());
assertThat(thirdBean, notNullValue());
}
}
테스트 결과
2. @ImportAutoConfiguration 애너테이션
Import and apply the specified auto-configuration classes. Applies the same ordering rules as @EnableAutoConfiguration but restricts the auto-configuration classes to the specified set, rather than consulting ImportCandidates.
지정된 auto-configuration
클래스들을 가져와서 적용합니다.
@Import
애너테이션과 유사하지만, @ImportAutoConfiguration
애너테이션은 별도로 대상 클래스들을 지정하지 않으면 META-INF
폴더의 spring.factories
파일에서 대상 클래스들을 가져옵니다.
2.1. @ImportAutoConfiguration 애너테이션 사용 예시
간단하게 이전에 살펴봤던 @AutoConfigureDataJpa
애너테이션을 기준으로 사용 예시를 살펴보겠습니다.
2.1.1. @AutoConfigureDataJpa 애너테이션
@AutoConfigureDataJpa
애너테이션 위에@ImportAutoConfiguration
애너테이션이 추가되어 있습니다.
package org.springframework.boot.test.autoconfigure.orm.jpa;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@ImportAutoConfiguration
public @interface AutoConfigureDataJpa {
}
2.1.2. spring.factories 파일 살펴보기
@AutoConfigureDataJpa
애너테이션이 포함된spring-boot-test-autoconfigure.jar
파일을 확인해보았습니다./META-INF/spring.factories
파일에는AutoConfigureDataJpa
애너테이션에 의해 임포트 되는 클래스들이 정의되어 있습니다.
...
# AutoConfigureDataJpa auto-configuration imports
org.springframework.boot.test.autoconfigure.orm.jpa.AutoConfigureDataJpa=\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration
2.2. @ImportAutoConfiguration 애너테이션 활용 예제
간단하게 커스텀 애너테이션을 만들어 테스트해보겠습니다.
2.2.1. 패키지 구조
/resources/META-INF
폴더에spring.factories
파일을 생성합니다.
./
├── mvnw
├── mvnw.cmd
├── pom.xml
└── src
├── main
│ ├── java
│ │ └── blog
│ │ └── in
│ │ └── action
│ │ ├── ActionInBlogApplication.java
│ │ ├── annotation
│ │ │ └── CustomAutoConfiguration.java
│ │ ├── beans
│ │ │ ├── FirstBean.java
│ │ │ ├── SecondBean.java
│ │ │ └── ThirdBean.java
│ │ └── config
│ │ └── CustomConfiguration.java
│ └── resources
│ ├── META-INF
│ │ └── spring.factories
│ ├── application.yml
│ └── static
└── test
└── java
└── action
└── in
└── blog
├── ImportAutoConfigurationTests.java
└── ImportTests.java
2.2.2. @CustomAutoConfiguration 애너테이션
@ImportAutoConfiguration
애너테이션을 위에 추가합니다.
package blog.in.action.annotation;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@ImportAutoConfiguration
public @interface CustomAutoConfiguration {
}
2.2.3. spring.factories 파일
@CustomAutoConfiguration
애너테이션을 통해 임포트 되는 클래스들을 정의합니다.- 상위에서 테스트에서 사용한
CustomConfiguration
,ThirdBean
클래스를 명시하였습니다.
- 상위에서 테스트에서 사용한
blog.in.action.annotation.CustomAutoConfiguration=\
blog.in.action.config.CustomConfiguration,\
blog.in.action.beans.ThirdBean
2.2.4. ImportAutoConfigurationTests 클래스
- 이번 포스트에서 만든
@CustomAutoConfiguration
애너테이션을 클래스 상단에 추가합니다. @Autowired
애너테이션에 의해 빈 객체들이 주입 받는지 테스트를 통해 확인합니다.
package action.in.blog;
import blog.in.action.annotation.CustomAutoConfiguration;
import blog.in.action.beans.FirstBean;
import blog.in.action.beans.SecondBean;
import blog.in.action.beans.ThirdBean;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.notNullValue;
@CustomAutoConfiguration
@ExtendWith({SpringExtension.class})
public class ImportAutoConfigurationTests {
@Autowired
FirstBean firstBean;
@Autowired
SecondBean secondBean;
@Autowired
ThirdBean thirdBean;
@Test
public void whenRunTestWithSpringExtension_thenAllBeansNotNull() {
assertThat(firstBean, notNullValue());
assertThat(secondBean, notNullValue());
assertThat(thirdBean, notNullValue());
}
}
테스트 결과
TEST CODE REPOSITORY
REFERENCE
- https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Import.html
- https://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/autoconfigure/ImportAutoConfiguration.html
- https://stackoverflow.com/questions/59444679/when-to-use-importautoconfiguration-vs-import
댓글남기기