😀 Spring 자동 설정의 이해
본 포스팅은 백기선님의 inflearn 강의인 "스프링 부트 개념과 활용" 을 정리한 내용입니다.
@SpringBootApplication
@SpringBootConfiguration
@ComponentScan
@EnableAutoConfiguration
을 내포하고 있다.
🥕@SpringBootConfiguration
@SpringBootConfiguration Document
@SpringBootConfiguration is a class-level annotation that is part of the Spring Boot framework. It indicates that a class provides application configuration.
Document에서 보면@SpringBootConfiguration
은 Application Class에 사용되고 , 클래스에@Bean
이 선언되어 있는 Spring Container 인 것을 나타낸다. 라고 나와있다.
🤔Bean
은 두 단계로 나눠서 읽힌다
🥕@ComponentScan
Bean을 Scan 하는 Annotation.
@Component
,@Configuration
@Repository
@Service
@Controller
@RestController
라는 Annotation을 가진Class
들을 스캔해서 Bean에 등록.@Filter
를 추가해서@ComponentScan
에 의해서 Bean에 등록되는 일을 막을 수 있음.😬 주의 !
@ComponentScan
이 정의된 Class와 같은 혹은 하위 패키지에 있는 것들만Bean
에 등록한다.Example
- com.example.ddingg 안에
Application.java
가 있다. 이 클래스에는@ComponentScan
이 선언되어 있다.- com.example.choi 안에는
@Component
가 정의된Category.java
파일이 있다.@ComponentScan
이 선언된Application.java
부터 Bean을 읽기 시작하기 때문에Category.java
는Bean
에 등록 될 수 없다.
🥕@EnableAutoConfiguration
여러가지 설정이 읽히면서 Application이 동작하는데 그렇게 할 수 있는 이유가
@EnableAutoConfiguration
때문이다.Bean을 Scan하는 Annotation.
@ComponentScan
이Bean
을 읽어드린 다음에 추가적으로Bean
들을 등록한다.
META-INF
내부의spring-factories
라는 파일이 있다. 파일 안의 Key 값들 중에org.springframework.boot.autoconfigure.EnableAutoConfiguration
라는 Key가 있는데 여기안에 정의된 모든Class
(뜯어보면 모든 클래스에@Configuration
이 선언되어 있다.)들이 AutoConfiguration된다.
😀 자동 설정 구현
xxx-Spring-Boot-Autoconfigure 모듈 : 자동설정
xxx-Spring-Boot-Starter 모듈 : 필요한 의존성 정의
build.gradle 추가
org.springframework.boot:spring-boot-autoconfigure:2.2.6.RELEASE
org.springframework.boot:spring-boot-autoconfigure-processor:2.2.6.RELEASE
🤔Bean이 중복되서 정의되면?
Bean
을 생성할때 위에서는 @ComponentScan
이후에 @EnableAutoConfituration
가 실행되어 거기에 정의된 @Configuration
파일들을 읽어서 Bean
에 등록한다고 했다. 실제로는 어떻게 적용이 될까?
예를들어 보자. A project
에서 Holoman
이라는 클래스에 @Configuration
을 설정하고 Bean
을 등록해 Local 저장소에 배포했다. (maven은 LifeCyclep에서 install 하면 되던데 gradle은 어떻게 하는걸까..)
그리고 B project
에서 Dependency를 추가해 방금 배포한 jar 파일의 의존성을 추가한다. 그리고 B project
내부에서 똑같이 Holoman
이라는 타입을 가지는 Bean
을 생성한다.
🤔🤔🤔
이때 B project
를 실행시키면 어떤 Bean
이 추가되어 있을까?
🥕🥕🥕
답은 A project
의 Bean
이다. @ComponentScan
이후에 @EnableAutoConfituration
가 실행되기 때문에 Bean
이 덮어쓰기 되는 것이다.
그렇다면 B project
의 Bean
을 쓰기위해서는 어떻게 해야할까?
A project
에서 Bean
으로 만들기 위한 객체 위에 @ConditionalOnMissingBean
을 적어 줌으로써 해결 할 수 있다. 이 말은, 이 타입의 Bean이 없을때만 이 Bean을 쓰도록 해! 라는 말이다. 즉, LifeCycle에 의해 덮어쓰기 당하는 일을 없에는 것이다.
@Configuration
public class HolomanConfiguration {
@Bean // Holoman 클래스에 데이터 저장 후 Bean에 등록하겠다고 표시
@ConditionalOnMissingBean // 이 Bean을 추가할때 똑같은 타입의 다른 Bean이 있으면 그거 써!
public Holoman holoman(){
Holoman holoman = new Holoman();
holoman.setHowLong(5);
holoman.setName("ddingg");
return holoman;
}
}
🙄🙄 어.. 나는 Bean 재정의 안하고 그냥 Bean 안에 값을 수정하고 싶은데?
방법이 있습니다. 아까 위에서 B project
에서 Bean
을 재정의 해서 덮어 씌우는 걸 봤는데, 이렇게 Bean
을 재정의 하려면 장황하게 뭘 또 써야한다. 이때 우리는 @ConfigurationProperties
와 application.properties
파일을 통해 얼마든지 Bean
안의 값을 다시 수정할 수 있다.
먼저 Getter/Setter Class를 만들어 @ConfigurationProperties
를 적용시켜준다.
@ConfigurationProperties("holoman")
public class HolomanProperties {
private String name;
private int howLong;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getHowLong() {
return howLong;
}
public void setHowLong(int howLong) {
this.howLong = howLong;
}
}
@ConfigurationProperties
를 등록하려고 하면 Spring Boot Configuration Annotation Processor not found in classpath
와 같은 에러가 나올 텐데, Open Document
로 가서 보려했는데 안열리더라. 수동으로 찾아찾아가서 문서를 열어 확인했다. 여기 로 가서 Maven 혹은 Gradle에 맞는 의존성을 추가해주자. 나는
dependencies {
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
}
Gradle 4.6이후면 위와 같은 의존성을 사용하면 된다.
그리고 B project
로 가서 /src/main/resource
안에 application.properties
파일을 만들어 준다. (Spring initailizer를 사용했다면 이미 파일이 있을것이다. 그냥 Gradle이나 Maven 프로젝트로 Spring Project를 시작했다면 따로 만들어 주어야 한다.)
//application.properties
holoman.name = 바꾼이름
holoman.how-long = 100 // 변수명을 camelCase로 썻다면 하이픈으로 바꾸어 준다.(kebab-case 라고한다)
이런식으로 접근 할 수 있다.
'개발공부 > Spring' 카테고리의 다른 글
[SpringBoot] Spring 에서 내장 웹 서버의 이해와 Servelt / ssl 인증 (0) | 2020.05.03 |
---|---|
[SpringBoot] Spring Boot 소개 (0) | 2020.05.03 |
[SpringBoot]Spring AOP와 프록시 패턴 (0) | 2020.05.01 |
[SpringBoot]Spring 의존성 주입 DI(Dependency Injection) 와 순환 참조 (0) | 2020.05.01 |
[SpringBoot] IoC 컨테이너와 Bean (0) | 2020.05.01 |