자동 구성
예제 만들기
- JdbcTemplate을 사용한 회원 데이터를 DB에 보관하고 관리하는 기능 개발
@Data
public class Member {
private String memberId;
private String name;
public Member() {
}
public Member(String memberId, String name) {
this.memberId = memberId;
this.name = name;
}
}
- 회원 예제
@Configuration
@Slf4j
public class DbConfig {
@Bean
public DataSource dataSource() {
log.info("dataSource 빈 등록");
HikariDataSource dataSource = new HikariDataSource();
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setJdbcUrl("jdbc:h2:mem:test"); //메모리 DB 사용
dataSource.setUsername("sa");
dataSource.setPassword("");
return dataSource;
}
@Bean
public TransactionManager transactionManager() {
log.info("transactionManager 빈 등록");
return new JdbcTransactionManager(dataSource());
}
@Bean
public JdbcTemplate jdbcTemplate() {
log.info("jdbcTemplate 빈 등록");
return new JdbcTemplate(dataSource());
}
}
- 설정 예제
- H2 데이터베이스를 메모리 DB로 사용하기 위해 DataSource로 등록
- DB 메모리 모드로 동작 옵션 => jdbc:h2:mem:test
- JDBC를 사용하기 위해 Jdbc 트랜잭션 매니저와 JdbcTemplate을 빈으로 등록
- 트랜잭션 매니저와 JdbcTemplate 모두 datasource를 필요로 한다.
- JdbcTransactionManager와 DataSourceTransactionManager보다 예외처리 기능 측면만 좋아졌을 뿐 서로 같다고 생각하면 된다.
- H2 데이터베이스를 메모리 DB로 사용하기 위해 DataSource로 등록
@Repository
public class MemberRepository {
public final JdbcTemplate template;
public MemberRepository(JdbcTemplate template) {
this.template = template;
}
public void initTable() {
template.execute("create table member(member_id varchar primary key, name varchar)");
}
public void save(Member member) {
template.update("insert into member(member_id,name) values(?,?)",
member.getMemberId(),
member.getName());
}
public Member find(String memberId) {
return template.queryForObject("select member_id, name from member where member_id=?",
BeanPropertyRowMapper.newInstance(Member.class),
memberId);
}
public List<Member> findAll() {
return template.query("select member_id, name from member",
BeanPropertyRowMapper.newInstance(Member.class));
}
}
- JdbcTemplate을 사용한 회원 관리 레포지토리 예제
- initTable() : 테이블 생성 SQL로 보통 레포지토리에서는 테이블 생성 스크립트를 두지 않지만 예제를 위해서 사용
@SpringBootTest
class MemberRepositoryTest {
@Autowired
MemberRepository memberRepository;
@Transactional
@Test
public void memberTest() {
Member member = new Member("idA", "memberA");
memberRepository.initTable();
memberRepository.save(member);
Member findMember = memberRepository.find(member.getMemberId());
assertThat(findMember.getMemberId()).isEqualTo(member.getMemberId());
assertThat(findMember.getName()).isEqualTo(member.getName());
}
}
- 회원 레포지토리 테스트 예제
- @Transactional을 사용해서 트랜잭션 기능 적용
- @Transactional을 사용하기 위해 TransactionManager가 스프링 빈으로 필요
- @Transactional을 사용해서 트랜잭션 기능 적용
스프링 부트의 자동 구성
- 스프링 부트는 자동 구성(Auto Configuration) 기능을 제공한다.
- 일반적으로 자주 사용하는 많은 빈들을 자동으로 등록해주는 기능이다.
- ex) JdbcTemplate, DataSource, TransactionManager 등 ...
- 수 많은 자동 구성 클래스 중 JdbcTemplate을 위한 클래스 코드를 확인해보자.
@AutoConfiguration(after = DataSourceAutoConfiguration.class)
@ConditionalOnClass({ DataSource.class, JdbcTemplate.class })
@ConditionalOnSingleCandidate(DataSource.class)@EnableConfigurationProperties(JdbcProperties.class)
@Import({ DatabaseInitializationDependencyConfigurer.class, JdbcTemplateConfiguration.class,
NamedParameterJdbcTemplateConfiguration.class })
public class JdbcTemplateAutoConfiguration {
}
- JdbcTemplateAutoConfiguration - 자동 구성 클래스
- @AutoConfiguration : 자동 구성을 사용하기 위한 어노테이션
- 자동 구성 내부에 @Configuration이 있기에 빈을 등록하는 자바 설정 파일로 사용할 수 있다.
- after 속성을 통해 자동 구성이 실행되는 순서를 지정할 수 있다.
- @ConditionalOnClass : IF문과 유사한 기능을 제공하는 어노테이션
- 어노테이션에 지정된 클래스들이 있는 경우에만 설정이 동작한다.
없는 경우 설정들이 모두 무효화되고 빈도 등록되지 않는다. - @ConditionalXxx 시리즈가 있다. (@ConditionalOnBean 등..)
=> 자동 구성의 핵심
- 어노테이션에 지정된 클래스들이 있는 경우에만 설정이 동작한다.
- @Import : 스프링에서 자바 설정을 추가할 때 사용한다.
- @AutoConfiguration : 자동 구성을 사용하기 위한 어노테이션
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(JdbcOperations.class)
class JdbcTemplateConfiguration {
@Bean
@Primary
JdbcTemplate jdbcTemplate(DataSource dataSource, JdbcProperties properties) {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
JdbcProperties.Template template = properties.getTemplate();
jdbcTemplate.setFetchSize(template.getFetchSize());
jdbcTemplate.setMaxRows(template.getMaxRows());
if (template.getQueryTimeout() != null) {
jdbcTemplate.setQueryTimeout((int)template.getQueryTimeout().getSeconds());
}
return jdbcTemplate;
}
}
- JdbcTemplateConfiguration 클래스
- JdbcTemplateAutoConfiguration에서 @Import하고 있는 설정 중 하나이다.
- @Configuration : 자바 설정 파일로 사용된다.
- @ConditionalOnMissingBean : 어노테이션의 값으로 지정된 빈이 없을 때 해당 설정 파일이 동작한다.
- 여기서 JdbcOperations는 JdbcTemplate의 부모 인터페이스로 개발자에 의해 직접 JdbcTemplate이 빈으로 등록되어 있지 않으면 자동 구성을 사용하기 위함이다.
- 스프링 부트에서 제공하는 수 많은 자동 구성들은 spring-boot-autoconfigure 라이브러리에 모여있다.
- spring-boot-autoconfigure 라이브러리는 스프링 부트를 사용하면 기본적으로 사용된다.
- Auto Configuration 용어
- 자동 설정 - Configuration은 컴퓨터 용어에서 환경 설정, 설정으로 사용된다.
- 빈들을 자동으로 등록해서 스프링이 동작하는 환결을 자동으로 설정해주기 때문에 자동 설정이라는 용어도 맞다.
- 자동 구성 - Configuration은 구성(=배치)라는 뜻으로도 사용된다.
- 스프링에 필요한 빈들을 자동으로 배치해주는 것이기에 자동 구성이라는 용어도 맞다.
- 자동 설정이 넓게 사용되는 의미, 자동 구성이 실행에 필요한 컴포넌트 조각을 자동으로 배치하는 좁은 의미에 가깝다.
- 자동 설정 - Configuration은 컴퓨터 용어에서 환경 설정, 설정으로 사용된다.
자동 구성 직접 만들기 - 기반 예제
public class Memory {
private long used;
private long max;
public Memory(long used, long max) {
this.used = used;
this.max = max;
}
public long getUsed() {
return used;
}
public long getMax() {
return max;
}
@Override
public String toString() {
return "Memory{" +
"used=" + used +
", max=" + max +
'}';
}
}
- 자바 메모리 사용량 예제
- used : 사용중인 메모리
- max : 최대 메모리
@Slf4j
public class MemoryFinder {
public Memory get() {
long max = Runtime.getRuntime().maxMemory();
long total = Runtime.getRuntime().totalMemory();
long free = Runtime.getRuntime().freeMemory();
long used = total - free;
return new Memory(used, max);
}
@PostConstruct
public void init() {
log.info("init memoryFinder");
}
}
- JVM에서 메모리 정보를 실시간으로 조회하는 기능 예제
- max : JVM이 사용할 수 있는 최대 메모리로 이 수치가 넘어가면 OOM이 발생
- total : JVM이 확보한 전체 메모리 (JVM은 처음부터 max까지 다 확보하지 않고 필요할 때 조금씩 확보한다)
- free : total 중 사용하지 않는 메모리(JVM이 확보한 전체 메모리 중 사용하지 않은 것)
- used : JVM이 사용중인 메모리 (used = total - free)
@Slf4j
@RestController
@RequiredArgsConstructor
public class MemoryController {
private final MemoryFinder memoryFinder;
@GetMapping("/memory")
public Memory system() {
Memory memory = memoryFinder.get();
log.info("memory={}", memory);
return memory;
}
}
- 메모리 정보를 조회하는 컨트롤러 예제
@Configuration
public class MemoryConfig {
@Bean
public MemoryController memoryController() {
return new MemoryController(memoryFinder());
}
@Bean
public MemoryFinder memoryFinder() {
return new MemoryFinder();
}
}
- Memory 관련 설정 파일
- 예제에서 memory, member 패키지를 별도로 나눈 것은 별도의 모듈, 라이브러리처럼 사용한다고 생각하면 된다.
@Conditional
- 메모리 조회 기능을 특정 조건일 때만 기능이 활성화 되도록 하려면?
- ex) 개발 서버에서만 사용하고 운영 서버에서는 사용하지 않게하려면?
- 소스 코드를 고치지 않고, 같은 소스 코드로 특정 상황(조건)일 때 각각 적용하기 위해서 사용하는 기능이 @Conditional 어노테이션이다.
- @Conditional : 특정 조건에 맞을 때 설정이 동작하도록 하는 어노테이션이다.
public interface Condition {
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
- Condition 인터페이스
- matches() 메소드가 true를 반환하면 조건에 만족해서 동작하고 false를 반환하면 동작하지 않는다.
- ConditionContext : 스프링 컨테이너, 환경 정보등을 담고 있다.
- AnnotatedTypeMetadata : 어노테이션 메타 정보를 담고 있다.
- 자바 시스템 속성이 memory=on 이라고 되어있을 때만 메모리 기능이 동작하도록 해보자.
@Slf4j
public class MemoryCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
//-Dmemory=on
String memory = context.getEnvironment().getProperty("memory");
log.info("memory={}", memory);
return "on".equals(memory);
}
}
- Condition 구현 클래스
- 자바 환경 정보에 memory=on이라고 되어있는 경우에만 true를 반환하도록 했다.
@Configuration
@Conditional(MemoryCondition.class)
public class MemoryConfig {
@Bean
public MemoryController memoryController() {
return new MemoryController(memoryFinder());
}
@Bean
public MemoryFinder memoryFinder() {
return new MemoryFinder();
}
}
- Memory 관련 설정 파일
- @Conditional을 통해 이전에 Condition을 구현해 만든 클래스를 조건으로 넣어준다.
- 자바 환경 정보에 memory=on이 아니면 false를 반환하게되고 @Conditional이 false이면 Memory 설정 파일은 무효화가 되고 빈들도 등록되지 않기 때문에 Memory 관련 기능을 사용할 수 없게 된다.
- @Conditional을 통해 이전에 Condition을 구현해 만든 클래스를 조건으로 넣어준다.
- 자바 환경 정보 설정
- 상단바 Run -> Edit Configurations
- Modify options -> Add VM options
- 값 입력
- 값 입력 시 -D를 맨 앞에 꼭 붙여줘야 한다.
- 스프링은 외부 설정을 추상화해서 Environment로 통합
- 다양한 외부 환경 설정을 Environment 하나로 읽을 수 있다.
- ex) VM options, Program arguments, application.properties ...
#VM Options
#java -Dmemory=on -jar project.jar
-Dmemory=on
#Program arguments
# -- 가 있으면 스프링이 환경 정보로 사용
#java -jar project.jar --memory=on
--memory=on#application.properties
#application.properties에 있으면 환경 정보로 사용
memory=on
@Conditional - 다양한 기능
@Configuration
//@Conditional(MemoryCondition.class)
@ConditionalOnProperty(name = "memory", havingValue = "on") //추가
public class MemoryConfig {...}
- Memory 관련 설정 파일
- @ConditionalOnProperties(name = "memory", havingValue = "on")
- 환경 정보가 memory=on이라는 조건에 만족하면 동작하고 아니면 동작하지 않는다.
- 이전에 Condition을 구현하고 구현체를 @Conditional에 넘겨준 코드와 일치한다.
- 내부에서는 @Conditional을 사용하며 그 내부에는 Conditon을 구현한 OnPropertyCondtion을 가지고 있다.
- @ConditionalOnProperties(name = "memory", havingValue = "on")
- @ConditionalOnXxx : @Conditional과 관련해서 편리하게 사용할 수 있도록 스프링에서 제공하는 어노테이션들이다.
- @ConditionalOnClass , @ConditionalOnMissingClass
- OnClass는 클래스가 있는 경우 동작, OnMissing~ 클래스가 없는 경우 동작.
- @ConditionalOnBean , @ConditionalOnMissingBean
- OnBean은 빈이 있는 경우 동작, OnMissing~ 빈이 없는 경우 동작.
- @ConditionalOnProperty : 환경 정보가 있는 경우 동작한다.
- @ConditionalOnResource : 리소스가 있는 경우 동작한다.
- @ConditionalOnWebApplication , @ConditionalOnNotWebApplication
- OnWeb~은 웹 애플리케이션인 경우 동작, OnNot~은 웹 애플리케이션이 아닌 경우 동작한다.
- @ConditionalOnExpression : SpEL 표현식에 만족하는 경우 동작한다.
- @ConditionalOnClass , @ConditionalOnMissingClass
- @ConditionalOnXxx는 주로 스프링 부트 자동 구성에 사용된다.
순수 라이브러리 만들기 memory-v1
plugins {
id 'java'
}
group = 'memory'
sourceCompatibility = '17'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web:3.0.2'
compileOnly 'org.projectlombok:lombok:1.18.24'
annotationProcessor 'org.projectlombok:lombok:1.18.24'
testImplementation 'org.springframework.boot:spring-boot-starter-test:3.0.2'
}
...
- build.gradle
- 스프링 부트 플러그인을 사용하지 않았기에 라이브러리 버전을 직접 명시해줘야 한다.
- 스프링 부트 플러그인 사용 시 실행 가능한 Jar 구조를 기본으로 만든다.
- 스프링 부트 플러그인을 사용하지 않았기에 라이브러리 버전을 직접 명시해줘야 한다.
- 이전에 만든 memory 패키지의 Memory, MemoryController, MemoryFinder를 복사해서 붙여넣고 빌드
- 빌드한 결과물로 생성된 Jar 파일은 실행 가능한 Jar가 아니기에 스스로 동작하지 못하고 다른 곳에 포함되어서 동작하는 라이브러리로 사용할 것
순수 라이브러리 사용 project-v1
- memory-v1 라이브러리를 적용할 새로운 프로젝트 project-v1 생성
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "hello";
}
}
- Controller 예제
- 새로 만든 프로젝트에서 memory-v1.jar (라이브러리)를 추가
- 새로운 프로젝트에서 libs 폴더 생성 후 memory-v1.jar 파일을 복사한 것을 넣어준다.
- 라이브러리를 사용하기 위해서는 build.gradle의 dependencies에 의존성을 추가해줘야 한다.
...
dependencies {
implementation files('libs/memory-v1.jar') //추가
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
...
- build.gradle
- implementation files('libs/memory-v1.jar') : 라이브러리를 jar 파일로 직접 가지고 있는 경우 files로 지정하면 된다.
- 정상적으로 jar 파일이 인식되면 아래 그림과 같이 내부 구조가 표시된다.
@Configuration
public class MemoryConfig {
@Bean
public MemoryFinder memoryFinder() {
return new MemoryFinder();
}
@Bean
public MemoryController memoryController() {
return new MemoryController(memoryFinder());
}
}
- 라이브러리 사용을 위한 설정 파일
- 새로운 프로젝트 project-v1에서 memory-v1 라이브러리를 적용하려면 빈으로 등록해서 사용해야 한다.
- 외부 라이브러리를 사용하려면 라이브러리 내부에 있는 어떤 빈을 등록해야하는지 알아야하고 등록해야 한다.
- 이런 부분을 스프링 부트 자동 구성이 자동으로 처리해준다.
자동 구성 라이브러리 만들기 memory-v2
- 목표 - 프로젝트에 라이브러리만 추가하면 모든 구성이 자동으로 처리되도록 해보자.
- 라이브러리만 추가하면 스프링 빈들이 자동으로 등록되도록 하는 것이 목표
@AutoConfiguration
@ConditionalOnProperty(name = "memory", havingValue = "on")
public class MemoryAutoConfig {
@Bean
public MemoryController memoryController() {
return new MemoryController(memoryFinder());
}
@Bean
public MemoryFinder memoryFinder() {
return new MemoryFinder();
}
}
- 자동 구성을 위한 설정 파일
- 이전에 직접 만들었던 메모리 관련 기능 라이브러리 memory-v1 패키지에 자동 구성 설정 파일 추가
- @AutoConfiguration : 스프링 부트가 제공하는 자동 구성 기능을 적용할 때 사용하는 어노테이션이다.
- @ConditionalOnProperty : 특정 환경 정보가 있을 때 라이브러리를 적용하도록 설정할 수 있는 어노테이션이다. (IF문과 유사한 기능)
- 라이브러리가 있더라도 상황에 다라 기능을 켜고 끌 수 있도록 유연한 기능을 제공한다.
- 스프링 부트 자동 구성을 적용하기 위해서 자동 구성 대상을 다음 파일에 지정해줘야 한다.
- src/main/resources/METAINF/spring 패키지의
org.springframework.boot.autoconfigure.AutoConfiguration.imports 파일에 지정 - 파일에 자동 구성 대상을 패키지를 포함해서 명시해줘야 한다.
- 스프링 부트는 시작 시점에 해당 파일의 정보를 읽어서 자동 구성으로 사용한다.
- src/main/resources/METAINF/spring 패키지의
자동 구성 라이브러리 사용 project-v2
- 이전 예제 project-v1에서는 memory-v1 라이브러리를 사용하기 위해 스프링 빈을 직접 등록
- project-v2에서는 memory-v2 라이브러리를 사용하기 위해서 스프링 자동 구성이 적용되었기에 빈을 별도로 설정하지 않아도 된다.
- @ConditionalOnProperty에 부합하도록 자바 환경 정보에 -Dmemory=on 만 적어주면 된다.
자동 구성 이해 - 스프링 부트의 동작
src/main/resources/METAINF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
- 스프링 부트는 다음 경로에 있는 파일을 읽어서 스프링 부트 자동 구성으로 사용한다.
- 스프링 부트 자동 구성이 동작하는 원리
- main() 메소드 실행 -> @SpringBootApplication
- @SpringBootApplication 내부의 @EnableAutoConfiguration 동작
- 자동 구성을 활성화 하는 기능을 제공
- @EnableAutoConfiguration 내부의 @Import(AutoConfigurationImportSelector.class)
- @Import는 주로 스프링 설정 정보(@Configuration)를 포함할 때 사용한다.
- AutoConfigurationImportSelector는 ImportSelector를 구현한 클래스로 @Configuration이 아니다.
자동 구성 이해 - ImportSelector
- @Import에 설정 정보를 추가하는 2가지 방법
- 정적인 방법 : @Import(클래스)
- 정적인 방법으로 코드에 대상이 정확히 지정되어 있기에 설정으로 사용할 대상을 동적으로 변경할 수 없다.
- 동적인 방법 : @Import(ImportSelector)
- 코드로 프로그래밍해서 설정으로 사용할 대상을 동적으로 선택할 수 있다.
- 정적인 방법 : @Import(클래스)
@Configuration
@Import({AConfig.class, BConfig.class})
public class AppConfig {...}
- @Import 정적인 방법 예제
- 이 경우 AConfig, BConfig를 모두 사용하며 정적으로 대상을 변경할 수 없다.
public interface ImportSelector {
String[] selectImports(AnnotationMetadata importingClassMetadata);
...
}
- ImportSelector 인터페이스
- 설정 정보 대상을 동적으로 선택할 수 있는 인터페이스이다.
- ImportSelector 예제
public class HelloBean {...}
@Configuration
public class HelloConfig {
@Bean {
return new HelloBean();
}
}
- ImportSelector 사용하기 위한 기반 예제
- 스프링 설정 파일 HelloConfig에 HelloBean을 스프링 빈으로 등록
public class HelloImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{"hello.selector.HelloConfig"};
}
}
- ImportSelector 구현 클래스
- 설정 정보를 동적으로 선택할 수 있게 해주는 ImportSelector 인터페이스 구현
- 예제에서는 단순히 hello.selector.HelloConfig 설정 정보를 반환했다.
- 이렇게 반환된 설정 정보는 선택되서 사용된다.
- 설정 정보로 사용할 클래스를 동적으로 프로그래밍하면 된다.
public class ImportSelectorTest {
@Test
public void staticConfig() {
AnnotationConfigApplicationContext appContext =
new AnnotationConfigApplicationContext(StaticConfig.class);
HelloBean bean = appContext.getBean(HelloBean.class);
Assertions.assertThat(bean).isNotNull();
}
@Test
public void selectorConfig() {
AnnotationConfigApplicationContext appContext =
new AnnotationConfigApplicationContext(SelectorConfig.class);
HelloBean bean = appContext.getBean(HelloBean.class);
Assertions.assertThat(bean).isNotNull();
}
@Configuration
@Import(HelloConfig.class)
public static class StaticConfig {
}
@Configuration
@Import(HelloImportSelector.class)
public static class SelectorConfig {
}
}
- ImportSelector 사용 예제
- staticConfig()
- 스프링 컨테이너를 만들고 StaticConfig.class를 초기 설정 정보로 사용함으로 HelloBean이 스프링 컨테이너에 잘 등록된 것을 확인할 수 있다.
- selectorConfig() 동작 원리
- selectorConfig() 는 SelectorConfig.class를 초기 설정 정보로 사용
- SelectorConfig.class는 @Import로 ImportSelector의 구현체인 HelloImportSelector를 사용
- 스프링은 HelloImportSelector를 실행하고 selectImports() 메소드를 통해 "hello.selector.HelloConfig"라는 문자를 반환 받는다.
- "hello.selector.HelloConfig" 문자에 맞는 대상을 설정 정보로 사용하기에 hello.selector.HelloConfig가 설정 정보로 사용된다.
- staticConfig()
//@EnableAutoConfiguration 내부
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {…}
- @EnableAutoConfiguration 동작 방식
- AutoConfigurationImportSelector는 ImportSelector의 구현체로 설정 정보를 동적으로 선택할 수 있다.
- 동적으로 다음 파일들의 정보를 읽어서 설정 정보로 선택한다.
- META-INF/spring/
org.springframework.boot.autoconfigure.AutoConfiguration.imports - org.springframework.boot.autoconfigure.AutoConfiguration.imports
- META-INF/spring/
- 동적으로 다음 파일들의 정보를 읽어서 설정 정보로 선택한다.
- AutoConfigurationImportSelector는 ImportSelector의 구현체로 설정 정보를 동적으로 선택할 수 있다.
- 스프링 자동 구성이 동작하는 방식
- main() 메소드 실행 -> @SpringBootApplication
- @SpringBootApplication 내부의 @EnableAutoConfiguration 동작
- 자동 구성을 활성화 하는 기능을 제공
- @EnableAutoConfiguration 내부의 @Import(AutoConfigurationImportSelector.class)
- resources/META-INF/spring/
org.springframework.boot.autoconfigure.AutoConfiguration.imports 파일을 열어서 설정
정보 선택- 해당 파일의 설정 정보가 스프링 컨테이너에 등록되고 사용된다.
- @AutoConfiguration 특징
- 자동 구성의 순서를 지정할 수 있다.
- 내부에 @Configuration을 포함하고 있는 스프링 설정 파일이지만 일반 스프링 설정과 라이프 사이클이 다르기 때문에 컴포넌트 스캔의 대상이 되면 안되고 파일에 지정해서 사용해야 한다.
- 스프링 부트가 제공하는 컴포넌트 스캔에는 @AutoConfiguration을 제외하는 AutoConfigurationExcludeFilter가 포함되어 있다.
- 파일 : resources/META-INF/
spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
- 자동 구성 내부에서 컴포넌트 스캔을 사용하면 안되고 @Import는 사용할 수 있다.
- 대부분 AutoConfiguration은 라이브러리를 만들어서 제공할 때 사용한다.
라이브러리 제공 외에는 사용하는 특정 빈들이 어떻게 등록됐는지 확인할 때 필요한 경우가 있다.
정리
- 스프링 부트는 자동 구성(Auto Configuration) 기능을 제공한다.
- 일반적으로 자주 사용하는 많은 빈들을 자동으로 등록해주는 기능이다.
- 자동 구성 관련 어노테이션
- @AutoConfiguration : 자동 구성을 사용하기 위한 어노테이션
- 자동 구성 내부에 @Configuration이 있기에 빈을 등록하는 자바 설정 파일로 사용할 수 있다.
- @ConditionalXxx : 자동 구성의 핵심으로 속성, 클래스, 메소드 등 조건에 따라 IF문과 같이 특정 조건에 맞을 때 설정이 동작하도록 하는 어노테이션이다.
- @AutoConfiguration : 자동 구성을 사용하기 위한 어노테이션
- @AutoConfiguration
- 내부에 @Configuration을 포함하고 있는 스프링 설정 파일이지만 일반 스프링 설정과 라이프 사이클이 다르기 때문에 컴포넌트 스캔의 대상이 되면 안되고 파일에 지정해서 사용해야 한다.
- 스프링 부트가 제공하는 컴포넌트 스캔에는 @AutoConfiguration을 제외하는 AutoConfigurationExcludeFilter가 포함되어 있다.
- src/main/resources/METAINF/spring 패키지의
org.springframework.boot.autoconfigure.AutoConfiguration.imports 파일에 지정 - 스프링 부트는 시작 시점에 해당 파일의 정보를 읽어서 자동 구성으로 사용한다.
- 내부에 @Configuration을 포함하고 있는 스프링 설정 파일이지만 일반 스프링 설정과 라이프 사이클이 다르기 때문에 컴포넌트 스캔의 대상이 되면 안되고 파일에 지정해서 사용해야 한다.
- @Import에 설정 정보를 추가하는 2가지 방법
- 정적인 방법 : @Import(클래스)
- 정적인 방법으로 코드에 대상이 정확히 지정되어 있기에 설정으로 사용할 대상을 동적으로 변경할 수 없다.
- 동적인 방법 : @Import(ImportSelector)
- ImportSelector 인터페이스를 통해 설정 정보 대상을 동적으로 선택할 수 있다.
- 정적인 방법 : @Import(클래스)
출처 : [인프런 김영한 스프링 부트 - 핵심 원리와 활용]
스프링 부트 - 핵심 원리와 활용 강의 | 김영한 - 인프런
김영한 | 실무에 필요한 스프링 부트는 이 강의 하나로 모두 정리해드립니다., 백엔드 개발자를 위한 스프링 부트 끝판왕! 실무에 필요한 내용을 모두 담았습니다. [임베딩 영상] 김영한의 스
www.inflearn.com
'Spring > [인프런 김영한 스프링 부트 - 핵심 원리와 활용]' 카테고리의 다른 글
[인프런 김영한 스프링 부트 - 핵심 원리와 활용] 외부설정과 프로필2 (2) | 2025.01.23 |
---|---|
[인프런 김영한 스프링 부트 - 핵심 원리와 활용] 외부설정과 프로필1 (2) | 2025.01.22 |
[인프런 김영한 스프링 부트 - 핵심 원리와 활용] 스프링 부트 스타터와 라이브러리 관리 (0) | 2024.12.30 |
[인프런 김영한 스프링 부트 - 핵심 원리와 활용] 스프링 부트와 내장 톰캣 (1) | 2024.12.30 |
[인프런 김영한 스프링 부트 - 핵심 원리와 활용] 웹 서버와 서블릿 컨테이너 (0) | 2024.12.29 |