2022. 10. 26. 13:12ㆍJAVA
최근 @Profile 이 어떻게 작동하는지에 대한 설명을 요청받았다.
무지성 구글링으로 갖다 쓴 것이라 당연히 대답하지 못했다.
'이 어노테이션을 쓰면 알아서 빈 등록을 해주는구나' 정도로만 이해하고 사용했다.
사용하는 모든 기술의 코어를 파악하는 것은 현실적으로 어렵겠지만... 대략적인 그림은 그릴 수 있어야하지 않겠는가....!
질문받은 김에 @SpringBootApplication 에 대해서 조금 공부해보기로 했다.
허를 찌르는 질문 덕분에 또 관련 정보를 찾아보며 성장하는 계기가 되었다. 시작!
우선 SpringBoot 어플리케이션의 메인함수에 붙어있는 어노테이션을 살펴봅시다
@SpringBootApplication
public class TempApplication {
public static void main(String[] args) {
SpringApplication.run(TempApplication.class, args);
}
}
@SpringBootApplication 이라는 어노테이션이 달려있습니다.
들어가보면,
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
...
...
}
또 여러 어노테이션이 달려있습니다.
여기서 가장 핵심이라고 생각되는 것들은
@EnableAutoConfiguration 과 @ComponentScan 입니다.
@ComponentScan
컴포넌트스캔은 많이 아실 것이라고 생각합니다.
해당 어노테이션이 붙은 클래스의 하위 모든 패키지를 스캔하며 사용자가 정의한 컴포넌트 빈들을 컨테이너에 등록합니다.
@EnableAutoConfiguration
해당 어노테이션은 말 그대로 Auto Configuration을 활성화하겠다는 설정입니다.
SpringBoot는 spring.factories 정보를 가지고 자동설정을 진행한다고 합니다.
여기 적혀있는 클래스들은 @Configuration 어노테이션 없이도 자동으로 빈으로 등록됩니다.
그 말인즉슨, spring.factories 파일을 수정해서 본인의 설정 클래스를 적어두면 @Configuration 어노테이션을 적지 않아도 된다는 사실!!!!!!!!!!!!!!!! 예,, 사실 쓸 일은 없겠습니다..
요약하면, 스프링 팩토리에 나열된 configuration 클래스들이 자동으로 빈 등록됩니다!
물론 항상 모든 빈을 다 등록하는 것은 아닙니다.
AutoConfigurationImportSelector 라는 친구가 조건에 분기해서 빈을 등록할지 말지 판단한다고 합니다.
잘 모르겠습니다만, 핵심은 @Condition 류의 어노테이션입니다.
(OnBeanCondition, OnClassCondition, OnWebApplicationCondition, @ConditionalOnBean, @ConditionalOnMissingBean 등등)
이 친구들 덕분에 우리가 만든 빈들이 스프링 auto configuration 빈들과 충돌하지 않습니다. 미리 스프링개발자 형님들이 다 계획적으로 구현해놓으셨습니다....
팩토리의 각 AutoConfigruation들은 필요한 상황에만 자신이 실행될 수 있도록 @Conditional, @Condition과 같은 annotation들로 설정이 되어있습니다. 그 annotation 을 기반으로 필터링이 먼저 이뤄지고 필터링되지 않은 AutoConfigruation을 가지고 작업이 진행됩니다.
이 때, @Profile 과 @Lazy 같은 spring 기술 어노테이션도 auto configuration에서 활용된다고 합니다!
우리가 .properties에 적어놓은 설정정보들도 이 때 활용됩니다.
많이 돌아오긴 했지만, @Profile을 살펴봅시다
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(ProfileCondition.class)
public @interface Profile {
/**
* The set of profiles for which the annotated component should be registered.
*/
String[] value();
}
아니나 다를까!!!!!!!!
이 친구도 @Conditional 이라는 어노테이션을 갖고 있습니다.
특정 조건이 만족되면 빈으로 등록된다는 약속입니다.
그리고, String[] value()라는 메서드를 갖고있습니다. 선언하는 곳에서 매개변수로 넘겨준 프로필 목록들이
스프링 컨테이너를 통해 빈 등록여부를 판가름합니다.
그리고, ProfileCondition.class 라는 클래스 내부에는 matches 라는 메서드가 있습니다.
class ProfileCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
if (attrs != null) {
for (Object value : attrs.get("value")) {
if (context.getEnvironment().acceptsProfiles(Profiles.of((String[]) value))) {
return true;
}
}
return false;
}
return true;
}
}
이 matches 메서드에서 메타데이터와 여러가지를 짬뽕해서 @Conditional의 조건을 판단하는 것 같습니다.
아직은 배움이 미천하여,,,, 솔직히 잘은 모르겠습니다.
여튼,,, 이정도 까지만 알아도 감 잡는데는 충분했습니다!
두고보자 오토컨피규레이션 이놈자식!!!!!!!!!! 용두사미의 왕 감자 이창민!!!!!!!!!
https://velog.io/@jwkim/spring-boot-springapplication-annotation
http://dveamer.github.io/backend/SpringBootAutoConfiguration.html#@SpringBootApplication
'JAVA' 카테고리의 다른 글
[Spring] LocalDateTime response가 array 형식으로 반환될 때 (4) | 2022.08.22 |
---|---|
[Spring] 싱글톤 빈이 동시 요청을 처리하는 방법 (0) | 2022.08.11 |
[Spring + Redis] 오류 org.springframework.data.redis.serializer.SerializationException: Cannot deserialize; (0) | 2022.07.29 |
[Spring + Redis] 레디스로 게시글 조회수 중복 카운팅 검증하기 (1) | 2022.07.27 |
ifPresent() 메서드로 Optional 처리하기 (7) | 2022.07.22 |