Spring Auto Configuration
스프링 부트 자동 구성은 프로젝트에 추가한 jar 종속성[dependency]을 기반으로 스프링 애플리케이션을 자동으로 구성하려고 시도합니다. 예를 들어, HSQLDB가 클래스패스에 있고 데이터베이스 연결 빈을 수동으로 구성하지 않은 경우, 스프링 부트는 인메모리 데이터베이스를 자동 구성합니다.
@Configuration 클래스 중 하나에 @EnableAutoConfiguration 또는 @SpringBootApplication 어노테이션을 추가함으로써 자동 구성을 선택해야 합니다.
@SpringBootApplication 또는 @EnableAutoConfiguration 어노테이션은 하나만 추가해야 합니다. 일반적으로 주요 @Configuration 클래스에 이 중 하나를 추가하는 것이 좋습니다.
Spring Boot 프로젝트의 classpath를 확인하기 위해 아래 그림처럼 STS IDE에서 Maven Build를 선택한다.
그리고 Goals 입력창에 dependency:tree를 입력하고 Run 버튼을 선택한다.
콘솔창에서 현재 프로젝트의 classpath를 확인할 수 있다.
mvn dependency:tree 명령문 실행 결과입니다.
[INFO] Scanning for projects...
[INFO]
[INFO] [1m---------------------------< [0;36msia:taco-cloud[0;1m >---------------------------[m
[INFO] [1mBuilding taco-cloud 0.0.1-SNAPSHOT[m
[INFO] from pom.xml
[INFO] [1m--------------------------------[ jar ]---------------------------------[m
[INFO]
[INFO] [1m--- [0;32mdependency:3.5.0:tree[m [1m(default-cli)[m @ [36mtaco-cloud[0;1m ---[m
[INFO] sia:taco-cloud:jar:0.0.1-SNAPSHOT
[INFO] +- org.springframework.boot:spring-boot-starter-thymeleaf:jar:3.1.2:compile
[INFO] | +- org.springframework.boot:spring-boot-starter:jar:3.1.2:compile
[INFO] | | +- org.springframework.boot:spring-boot-starter-logging:jar:3.1.2:compile
[INFO] | | | +- ch.qos.logback:logback-classic:jar:1.4.8:compile
[INFO] | | | | \- ch.qos.logback:logback-core:jar:1.4.8:compile
[INFO] | | | +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.20.0:compile
[INFO] | | | | \- org.apache.logging.log4j:log4j-api:jar:2.20.0:compile
[INFO] | | | \- org.slf4j:jul-to-slf4j:jar:2.0.7:compile
[INFO] | | +- jakarta.annotation:jakarta.annotation-api:jar:2.1.1:compile
[INFO] | | \- org.yaml:snakeyaml:jar:1.33:compile
[INFO] | \- org.thymeleaf:thymeleaf-spring6:jar:3.1.1.RELEASE:compile
[INFO] | +- org.thymeleaf:thymeleaf:jar:3.1.1.RELEASE:compile
[INFO] | | +- org.attoparser:attoparser:jar:2.0.6.RELEASE:compile
[INFO] | | \- org.unbescape:unbescape:jar:1.1.6.RELEASE:compile
[INFO] | \- org.slf4j:slf4j-api:jar:2.0.7:compile
[INFO] +- org.springframework.boot:spring-boot-starter-web:jar:3.1.2:compile
[INFO] | +- org.springframework.boot:spring-boot-starter-json:jar:3.1.2:compile
[INFO] | | +- com.fasterxml.jackson.core:jackson-databind:jar:2.15.2:compile
[INFO] | | | +- com.fasterxml.jackson.core:jackson-annotations:jar:2.15.2:compile
[INFO] | | | \- com.fasterxml.jackson.core:jackson-core:jar:2.15.2:compile
[INFO] | | +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.15.2:compile
[INFO] | | +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.15.2:compile
[INFO] | | \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.15.2:compile
[INFO] | +- org.springframework.boot:spring-boot-starter-tomcat:jar:3.1.2:compile
[INFO] | | +- org.apache.tomcat.embed:tomcat-embed-core:jar:10.1.11:compile
[INFO] | | \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:10.1.11:compile
[INFO] | +- org.springframework:spring-web:jar:6.0.11:compile
[INFO] | | +- org.springframework:spring-beans:jar:6.0.11:compile
[INFO] | | \- io.micrometer:micrometer-observation:jar:1.11.2:compile
[INFO] | | \- io.micrometer:micrometer-commons:jar:1.11.2:compile
[INFO] | \- org.springframework:spring-webmvc:jar:6.0.11:compile
[INFO] | +- org.springframework:spring-aop:jar:6.0.11:compile
[INFO] | +- org.springframework:spring-context:jar:6.0.11:compile
[INFO] | \- org.springframework:spring-expression:jar:6.0.11:compile
[INFO] +- org.springframework.boot:spring-boot-devtools:jar:3.1.2:runtime
[INFO] | +- org.springframework.boot:spring-boot:jar:3.1.2:compile
[INFO] | \- org.springframework.boot:spring-boot-autoconfigure:jar:3.1.2:compile
[INFO] +- org.springframework.boot:spring-boot-starter-validation:jar:3.1.2:compile
[INFO] | +- org.apache.tomcat.embed:tomcat-embed-el:jar:10.1.11:compile
[INFO] | \- org.hibernate.validator:hibernate-validator:jar:8.0.1.Final:compile
[INFO] | +- jakarta.validation:jakarta.validation-api:jar:3.0.2:compile
[INFO] | +- org.jboss.logging:jboss-logging:jar:3.5.3.Final:compile
[INFO] | \- com.fasterxml:classmate:jar:1.5.1:compile
[INFO] +- org.projectlombok:lombok:jar:1.18.28:compile
[INFO] +- org.springframework.boot:spring-boot-starter-test:jar:3.1.2:test
[INFO] | +- org.springframework.boot:spring-boot-test:jar:3.1.2:test
[INFO] | +- org.springframework.boot:spring-boot-test-autoconfigure:jar:3.1.2:test
[INFO] | +- com.jayway.jsonpath:json-path:jar:2.8.0:test
[INFO] | +- jakarta.xml.bind:jakarta.xml.bind-api:jar:4.0.0:test
[INFO] | | \- jakarta.activation:jakarta.activation-api:jar:2.1.2:test
[INFO] | +- net.minidev:json-smart:jar:2.4.11:test
[INFO] | | \- net.minidev:accessors-smart:jar:2.4.11:test
[INFO] | | \- org.ow2.asm:asm:jar:9.3:test
[INFO] | +- org.assertj:assertj-core:jar:3.24.2:test
[INFO] | | \- net.bytebuddy:byte-buddy:jar:1.14.5:test
[INFO] | +- org.hamcrest:hamcrest:jar:2.2:test
[INFO] | +- org.junit.jupiter:junit-jupiter:jar:5.9.3:test
[INFO] | | +- org.junit.jupiter:junit-jupiter-api:jar:5.9.3:test
[INFO] | | | +- org.opentest4j:opentest4j:jar:1.2.0:test
[INFO] | | | +- org.junit.platform:junit-platform-commons:jar:1.9.3:test
[INFO] | | | \- org.apiguardian:apiguardian-api:jar:1.1.2:test
[INFO] | | +- org.junit.jupiter:junit-jupiter-params:jar:5.9.3:test
[INFO] | | \- org.junit.jupiter:junit-jupiter-engine:jar:5.9.3:test
[INFO] | | \- org.junit.platform:junit-platform-engine:jar:1.9.3:test
[INFO] | +- org.mockito:mockito-core:jar:5.3.1:test
[INFO] | | +- net.bytebuddy:byte-buddy-agent:jar:1.14.5:test
[INFO] | | \- org.objenesis:objenesis:jar:3.3:test
[INFO] | +- org.mockito:mockito-junit-jupiter:jar:5.3.1:test
[INFO] | +- org.skyscreamer:jsonassert:jar:1.5.1:test
[INFO] | | \- com.vaadin.external.google:android-json:jar:0.0.20131108.vaadin1:test
[INFO] | +- org.springframework:spring-core:jar:6.0.11:compile
[INFO] | | \- org.springframework:spring-jcl:jar:6.0.11:compile
[INFO] | +- org.springframework:spring-test:jar:6.0.11:test
[INFO] | \- org.xmlunit:xmlunit-core:jar:2.9.1:test
[INFO] +- org.springframework.boot:spring-boot-starter-jdbc:jar:3.1.2:compile
[INFO] | +- com.zaxxer:HikariCP:jar:5.0.1:compile
[INFO] | \- org.springframework:spring-jdbc:jar:6.0.11:compile
[INFO] | \- org.springframework:spring-tx:jar:6.0.11:compile
[INFO] \- com.h2database:h2:jar:1.4.196:runtime
[INFO] [1m------------------------------------------------------------------------[m
[INFO] [1;32mBUILD SUCCESS[m
[INFO] [1m------------------------------------------------------------------------[m
[INFO] Total time: 2.424 s
[INFO] Finished at: 2024-01-31T13:50:06+09:00
[INFO] [1m------------------------------------------------------------------------[m
spring-boot-autoconfigure
spring-boot-autoconfigure 모듈은 스프링 부트 애플리케이션의 자동 구성(auto-configuration) 기능을 제공합니다. 이 모듈은 스프링 부트 애플리케이션 실행 시 다양한 시점에서 활용되며, 애플리케이션의 구성과 초기화 과정을 단순화하고 자동화합니다. spring-boot-autoconfigure가 사용되는 주요 시점은 다음과 같습니다:
1. 애플리케이션 시작 시
- 초기 구성 로딩: 애플리케이션 시작 시, spring-boot-autoconfigure는 .m2/repository/org/springframework/boot/spring-boot-autoconfigure/3.1.2/spring-boot-autoconfigure-3.1.2.jar//META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 파일 내에 등록된 자동 구성 클래스들을 로드합니다. 이 과정에서 스프링 부트는 애플리케이션의 클래스패스를 검사하여 사용 가능한 기술과 라이브러리를 식별하고, 관련된 자동 구성을 적용합니다.
2. 의존성 및 클래스패스 검사
- 조건부 구성: spring-boot-autoconfigure 모듈 내에 포함된 자동 구성 클래스들은 다양한 @Conditional 어노테이션을 사용하여 특정 조건이 충족될 때만 활성화됩니다. 예를 들어, @ConditionalOnClass 어노테이션은 클래스패스에 특정 클래스가 존재할 때 해당 자동 구성을 활성화하는 데 사용됩니다. 이러한 조건부 로직을 통해 spring-boot-autoconfigure는 필요한 구성만을 적용합니다.
3. 자동 구성의 적용
- 빈 생성 및 구성: 조건에 따라 활성화된 자동 구성 클래스들은 필요한 스프링 빈을 생성하고 구성합니다. 이는 데이터베이스 연결, 웹 MVC 설정, 보안 구성, 메시징 시스템 등 애플리케이션의 다양한 부분에 걸쳐 이루어질 수 있습니다.
- 환경 및 프로퍼티 구성: spring-boot-autoconfigure는 애플리케이션의 환경 및 프로퍼티 설정에 따라 구성을 조정합니다. 예를 들어, application.properties 또는 application.yml 파일에서 설정한 프로퍼티 값에 기반하여 데이터 소스나 JPA 설정 등이 자동으로 구성됩니다.
4. 애플리케이션 실행 후
- 런타임 시 구성 변경: 일부 자동 구성은 애플리케이션 실행 중에도 변경될 수 있습니다. 예를 들어, 개발 중에는 임베디드 서버가 자동으로 구성되지만, 배포 환경에서는 외부 서버 설정에 맞게 자동 구성이 조정될 수 있습니다.
spring-boot-autoconfigure는 스프링 부트 애플리케이션의 시작부터 실행 후까지 다양한 시점에 걸쳐 중요한 역할을 수행합니다. 이 모듈은 애플리케이션의 클래스패스와 설정을 기반으로 적절한 자동 구성을 적용하며, 개발자가 복잡한 구성 작업 없이도 다양한 기능과 서비스를 손쉽게 사용할 수 있도록 돕습니다.
@EnableAutoConfiguration
spring-boot-autoconfigure 모듈에 포함된 자동 구성 클래스들은 스프링 부트가 지원하는 다양한 기술 스택과 통합 포인트에 대한 구성을 담당합니다. 예를 들어, 데이터베이스 연결, JPA 설정, 웹 MVC 구성, 보안 설정, 메시징 서비스 통합 등과 관련된 자동 구성 클래스들이 이 모듈 내에 존재합니다
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
/**
* Environment property that can be used to override when auto-configuration is
* enabled.
*/
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
/**
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude
*/
Class<?>[] exclude() default {};
/**
* Exclude specific auto-configuration class names such that they will never be
* applied.
* @return the class names to exclude
* @since 1.3.0
*/
String[] excludeName() default {};
}
spring-boot-autoconfigrue 패키지들의 클래스들을 BeanDefinition 형태로 DefaultListableBeanFactory에 등록하는 과정은 주로 ConfigurationClassPostProcessor와 @EnableAutoConfiguration 어노테이션에 의해 수행됩니다. 이 과정은 크게 다음과 같은 단계를 포함합니다:
1. @SpringBootApplication 및 @EnableAutoConfiguration
- 스프링 부트 애플리케이션은 일반적으로 @SpringBootApplication 어노테이션을 사용하여 구성됩니다. 이 어노테이션은 @EnableAutoConfiguration을 포함하고 있으며, @EnableAutoConfiguration은 스프링 부트의 자동 구성 기능을 활성화합니다.
- @EnableAutoConfiguration 어노테이션은 내부적으로 AutoConfigurationImportSelector를 사용하여 자동 구성 후보 클래스들을 선택합니다. 이 선택 과정은 spring.factories 파일 내에 정의된 EnableAutoConfiguration 키 아래 나열된 자동 구성 클래스들을 기반으로 합니다.
2. AutoConfigurationImportSelector
- AutoConfigurationImportSelector는 스프링 부트의 자동 구성 메커니즘의 핵심입니다. 이 클래스는 spring.factories 파일에서 org.springframework.boot.autoconfigure.EnableAutoConfiguration 키에 매핑된 자동 구성 클래스들의 목록을 로드합니다.
- 로드된 자동 구성 클래스들은 다양한 @Conditional 어노테이션을 통해 조건부로 적용됩니다. 이는 애플리케이션의 클래스패스, 환경 변수, 구성 속성 등에 따라 달라집니다.
3. ConfigurationClassPostProcessor
- ConfigurationClassPostProcessor는 스프링의 BeanFactoryPostProcessor 인터페이스를 구현하는 중요한 클래스로, 애플리케이션 컨텍스트 로딩 과정에서 @Configuration 어노테이션이 붙은 클래스들을 처리합니다.
- 이 클래스는 @Configuration 클래스들 내에서 정의된 빈 메소드들을 스캔하고, 이를 BeanDefinition 객체로 변환하여 DefaultListableBeanFactory에 등록합니다. 자동 구성 클래스들 역시 @Configuration 어노테이션을 사용하므로, ConfigurationClassPostProcessor에 의해 처리됩니다.
4. 빈 정의 등록
- ConfigurationClassPostProcessor에 의해 처리된 빈 정의들은 DefaultListableBeanFactory에 등록되며, 이후 빈 생명주기 관리(인스턴스화, 의존성 주입, 초기화 등) 과정에 따라 관리됩니다.
이러한 과정을 통해 spring-boot-autoconfigure에 의해 로드된 자동 구성 클래스들은 DefaultListableBeanFactory에 BeanDefinition 형태로 등록되며, 스프링 부트 애플리케이션의 자동 구성이 이루어집니다.
@AutoConfigurationPackage
@AutoConfigurationPackage는 Spring Boot의 자동 구성 시스템의 일부로, 주로 내부적으로 사용되는 주석(annotation)입니다. 이 주석은 애플리케이션의 메인 설정 클래스가 있는 패키지를 자동 구성의 기준점으로 사용하도록 지시합니다. 즉, Spring Boot는 이 패키지와 그 하위 패키지들을 기준으로 하여 컴포넌트 스캔(Component Scanning), 자동 구성(Auto-Configuration) 등을 수행합니다.
작동 방식
- 컴포넌트 스캔: Spring Boot는 @AutoConfigurationPackage에 의해 지정된 패키지를 시작점으로 사용하여 @Component, @Service, @Repository, @Controller 등의 주석이 붙은 클래스들을 자동으로 찾아 스프링 애플리케이션 컨텍스트에 빈(bean)으로 등록합니다.
- 기준점 설정: 이 주석은 애플리케이션의 구조와 구성 요소를 기준으로 삼을 주요 패키지를 식별하는 데 도움이 됩니다. 이를 통해 Spring Boot는 애플리케이션의 특정 부분에 대한 자동 구성을 더 효율적으로 수행할 수 있습니다.
사용 예
@SpringBootApplication 주석 안에 @AutoConfigurationPackage가 함께 포함되어 있습니다.
이는 @AutoConfigurationPackage를 통해 해당 애플리케이션의 메인 클래스가 위치한 패키지가 자동 구성의 기준점으로 설정됩니다. 이는 Spring Boot가 애플리케이션을 구성할 때 참조하는 기본 패키지 경로를 설정하는 데 도움이 됩니다.
AutoConfigurationImportSelector
AutoConfigurationImportSelector는 Spring Boot의 자동 구성(Auto-Configuration) 기능의 핵심 요소 중 하나입니다. 이 클래스는 @EnableAutoConfiguration 주석의 일부로 동작하며, Spring Boot 애플리케이션의 시작 시점에 클래스패스를 스캔하여 조건에 따라 적절한 자동 구성 클래스들을 선택하고 가져오는 역할을 합니다.
작동 방식
1. 클래스패스 스캔: AutoConfigurationImportSelector는 애플리케이션의 클래스패스를 스캔하여 사용 가능한 모든 자동 구성 후보(getCandidateConfigurations 메서드)를 찾습니다. 이 후보들은 일반적으로
.m2/repository/org/springframework/boot/spring-boot-autoconfigure/3.1.2/spring-boot-autoconfigure-3.1.2.jar//META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 파일 내에 위치해 있으며, Spring Boot 라이브러리에 포함된 자동 구성 클래스들의 목록을 제공합니다.
2. 조건부 처리: 각 자동 구성 클래스는 조건부 주석(@ConditionalOnClass, @ConditionalOnBean, @ConditionalOnProperty 등)을 사용하여 특정 조건을 충족할 때만 활성화되도록 설계되어 있습니다. AutoConfigurationImportSelector는 이러한 조건들을 평가하여 현재 애플리케이션 컨텍스트와 클래스패스에 맞는 자동 구성 클래스들을 선택합니다.(getAutoConfigurationEntry 메서드, getAtrributes 메서드, getExclusion 메서드, checkExcludedClasses 메서드, removeAll 메서드 그리고 spring.factories에서는 자동 구성에 사용될 필터 정보를 얻음)
※ spring.factories에서 읽어온 3개의 필터(OnBeanCondition, OnClassCondition, OnWebApplicationCondition)를 통해 AutoConfiguration.imports 파일에 등록된 AutoConfiguration 클래스를 필터링합니다.
3. 구성 클래스 가져오기: 조건에 맞는 자동 구성 클래스들이 결정되면, AutoConfigurationImportSelector는 이들을 애플리케이션 컨텍스트에 가져오고 등록합니다. 이 과정을 통해 애플리케이션에 필요한 빈, 구성 및 기능이 자동으로 설정됩니다.
중요성
AutoConfigurationImportSelector는 Spring Boot의 마법처럼 느껴지는 부분, 즉 개발자가 복잡한 구성 작업 없이도 빠르게 시작할 수 있도록 하는 부분의 핵심입니다. 이를 통해 개발자는 애플리케이션의 비즈니스 로직에 더 집중할 수 있으며, Spring Boot는 내부적으로 필요한 구성과 빈을 자동으로 처리합니다.
이 메커니즘 덕분에, 예를 들어, Spring MVC 웹 애플리케이션을 개발할 때 개발자는 웹 관련 구성(디스패처 서블릿, 뷰 리졸버 등)을 직접 설정하지 않아도 되며, Spring Boot가 이를 자동으로 처리합니다. 비슷한 방식으로 데이터베이스, 보안, 메시징 등 다양한 영역에서도 자동 구성이 적용됩니다.
DefaultListableBeanFactory
DefaultListableBeanFactory는 스프링 프레임워크의 핵심 부분 중 하나로, 빈(Bean)의 생성, 구성, 관리, 그리고 의존성 주입(Dependency Injection)을 담당하는 IoC(Inversion of Control) 컨테이너의 구현체입니다. 이 과정은 매우 세밀하며, 여러 단계와 구성 요소를 포함하고 있습니다. 다음은 이 과정을 더 상세하게 설명한 것입니다:
1. 리소스 위치 지정 및 로딩
- 리소스 위치 지정: 스프링 부트 애플리케이션 시작 시, DefaultListableBeanFactory는 애플리케이션의 configuration metadata(예: 자바, XML, 어노테이션 기반)를 식별합니다. 스프링 부트는 자동 구성을 통해 대부분의 경우 개발자가 명시적으로 구성 소스를 지정할 필요가 없도록 해줍니다.
- 리소스 로딩: 구성 소스가 식별되면, 해당 리소스(클래스, XML 파일 등)에서 빈 정의를 로드합니다. 이 과정은 BeanDefinitionReader 인터페이스의 구현체(예: AnnotatedBeanDefinitionReader, XmlBeanDefinitionReader)를 통해 이루어집니다.
2. 빈 정의의 등록
- 로드된 BeanDefinition는 BeanDefinitionRegistry 인터페이스를 통해 DefaultListableBeanFactory에 등록됩니다. 각 빈 정의는 빈의 이름, 클래스, 생명주기 콜백, 의존성 등에 대한 정보를 포함합니다.
3. 의존성 해석 및 주입
- 의존성 해석: DefaultListableBeanFactory는 빈의 의존성을 해석하기 위해 빈 정의에 명시된 정보(예: @Autowired, @Qualifier, @Resource 등의 어노테이션을 통해)를 사용합니다. 이 과정에서 의존성 그래프가 생성되며, 순환 의존성이 있는지 검사합니다.
- 의존성 주입: 의존성이 해석되면, DefaultListableBeanFactory는 빈 인스턴스를 생성하고, 의존성 주입을 수행합니다. 이는 생성자 주입, 세터 주입, 필드 주입 등 다양한 방식을 통해 이루어질 수 있습니다.
4. 빈의 인스턴스화 및 초기화
- 빈 인스턴스화: 의존성이 해석되고 주입될 준비가 되면, DefaultListableBeanFactory는 빈의 인스턴스를 생성합니다. 이는 빈 정의에 명시된 클래스의 생성자를 호출함으로써 이루어집니다.
- 초기화 콜백: 인스턴스화된 빈은 필요한 초기화 작업을 수행할 수 있습니다. 이는 @PostConstruct 어노테이션, InitializingBean 인터페이스의 afterPropertiesSet 메소드, XML 구성의 init-method 지정 등 다양한 방법을 통해 수행할 수 있습니다.
5. 빈 포스트 프로세싱
- 빈이 완전히 생성되고 초기화되면, BeanPostProcessor 구현체를 통해 후처리가 이루어집니다. 이는 AOP 프록시 생성, @Required 어노테이션 처리, @Autowired 어노테이션 처리 등을 포함할 수 있습니다. BeanPostProcessor는 빈의 초기화 단계 전후에 커스텀 로직을 실행할 수 있게 해줍니다.
6. 싱글톤 빈의 등록 및 사용
- DefaultListableBeanFactory는 생성된 빈을 싱글톤 캐시에 저장합니다. 이후 애플리케이션에서 해당 빈을 요청하면, DefaultListableBeanFactory는 캐시된 인스턴스를 반환하여 빈을 재사용합니다. 이는 메모리 사용량을 최소화하고, 애플리케이션의 성능을 향상시킵니다.
7. 빈의 사용 및 소멸
- 애플리케이션이 실행되는 동안, 스프링 IoC 컨테이너는 필요에 따라 빈을 애플리케이션에 제공합니다. 애플리케이션이 종료될 때, DefaultListableBeanFactory는 DisposableBean 인터페이스의 destroy 메소드, @PreDestroy 어노테이션, XML 구성의 destroy-method 지정 등을 통해 빈의 소멸 과정을 관리합니다.
- DefaultListableBeanFactory를 통한 이러한 과정은 스프링 애플리케이션의 빈 생명주기를 관리하며, 의존성 주입을 통해 느슨한 결합과 유연한 애플리케이션 구조를 가능하게 합니다.
@Conditional 어노테이션
Condition Evaluation Report 활성화
application.properties 또는 yml 파일에서 다음과 같이 debug 속성을 true로 설정한다.
Spring Boot Starters and Auto-configuration
임베디드 톰캣의 경우, 모든 것은 스타터로 시작됩니다. 우리는 애플리케이션에 Web 종속성을 추가했으므로 Spring Boot Web 스타터가 pom.xml 파일에 Maven 종속성으로 포함되었습니다.
spring-boot-starter-web in pom.xml file:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--...-->
</dependencies>
Spring Boot는 사전 정의된 스타터 패키지를 제공합니다. 이는 Spring 모듈과 일부 타사 라이브러리 및 도구를 함께 모아 둔 것입니다. spring-boot-starter-web은 독립 실행형[standalone] 웹 애플리케이션을 구축하는 데 도움이 됩니다. 이것은 Spring Core Web 라이브러리를 Jackson(JSON 처리), 검증, 로깅 및 내장 Tomcat 서버 등 다른 도구들과 함께 그룹화합니다.
자동 구성이 어떻게 작동하는지 설명하기 위해, 우리는 Spring Boot 라이브러리와 스타터 정의에 있는 코드를 통해 탐색할 것입니다.
Finding Tomcat
먼저, 우리의 pom.xml 파일에서 스타터 spring-boot-starter-web의 구현으로 이동해 봅시다. IDE에서 일반적으로 artifactId 이름을 통해 이 작업을 수행할 수 있습니다. 우리는 아티팩트 정의에 도달할 것이며, 이는 자체 종속성도 포함합니다. 만약 여러분이 2.3 버전 이전의 Spring Boot를 사용하고 있다면, Maven을 사용했기 때문에 pom.xml 파일이 될 것입니다. 2.3 버전 이후부터는 Gradle 파일을 찾을 수 있을 것입니다. 여기 소스 코드를 확인하세요.
Spring Boot Starter Web’s build configuration (build.gradle):
dependencies {
api(platform(project(":spring-boot-project:spring-boot-dependencies")))
api(project(":spring-boot-project:spring-boot-starters:spring-boot-starter"))
api(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-json"))
////////////////////////////////////////////////////////////////////////////////////
api(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-tomcat"))
////////////////////////////////////////////////////////////////////////////////////
api("org.springframework:spring-web")
api("org.springframework:spring-webmvc")
}
파일은 자체적으로 spring-boot-starter-tomcat과의 종속성을 가지고 있습니다. 이제 그 아티팩트 내부로 탐색해 보겠습니다. 이 링크를 따라서 해당 build.gradle 파일의 소스 코드를 확인하세요.
Spring Boot Starter Tomcat’s build configuration (build.gradle):
dependencies {
api(platform(project(":spring-boot-project:spring-boot-dependencies")))
api("jakarta.annotation:jakarta.annotation-api")
////////////////////////////////////////////////
api("org.apache.tomcat.embed:tomcat-embed-core") {
exclude group: "org.apache.tomcat", module: "tomcat-annotations-api"
}
api("org.glassfish:jakarta.el")
api("org.apache.tomcat.embed:tomcat-embed-websocket") {
exclude group: "org.apache.tomcat", module: "tomcat-annotations-api"
}
}
해당 파일을 확인해 보면, Spring이 아닌 종속성인 tomcat-embed-core를 포함하고 있는 것을 볼 수 있습니다. 이것은 내장 서버를 시작하는 데 사용되는 Tomcat 클래스를 포함하고 있는 Apache 라이브러리입니다. 이것은 최신 소스 파일로의 링크입니다.
The Spring Boot Autoconfigure module
spring-boot-starter-web은 또한 spring-boot-starter에 의존하는데, 이는 다음과 같은 종속성을 정의합니다(소스 코드 참조):
Spring Boot Starter’s build configuration (build.gradle):
dependencies {
api(platform(project(":spring-boot-project:spring-boot-dependencies")))
api(project(":spring-boot-project:spring-boot"))
/////////////////////////////////////////////////////////////
api(project(":spring-boot-project:spring-boot-autoconfigure"))
api(project(":spring-boot-project:spring-boot-starters:spring-boot-starter-logging"))
api("jakarta.annotation:jakarta.annotation-api")
api("org.springframework:spring-core")
api("org.yaml:snakeyaml")
}
핵심 Spring Boot 스타터이며, 아티팩트 spring-boot-autoconfigure를 가져옵니다. 이 패키지에는 @Configuration 어노테이션이 달린 많은 클래스들이 있는데, 이것들이 Spring Boot "마법"의 큰 부분을 이루는 이유입니다.
Web server factory configuration
autoconfigure 모듈에 포함된 자동 구성 클래스 중 하나는 ServletWebServerFactoryConfiguration입니다. 궁금하다면 전체 소스 파일을 확인하세요. 다음은 가장 관련성이 높은 코드 블록입니다:
ServletWebServerFactoryConfiguration.java inside spring-boot-autoconfigure:
@Configuration(proxyBeanMethods = false)
class ServletWebServerFactoryConfiguration {
@Configuration(proxyBeanMethods = false)
//////////////////////////////////////////////////////////////////////////
@ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class })
@ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
static class EmbeddedTomcat {
@Bean
TomcatServletWebServerFactory tomcatServletWebServerFactory(
ObjectProvider<TomcatConnectorCustomizer> connectorCustomizers,
ObjectProvider<TomcatContextCustomizer> contextCustomizers,
ObjectProvider<TomcatProtocolHandlerCustomizer<?>> protocolHandlerCustomizers) {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
factory.getTomcatConnectorCustomizers()
.addAll(connectorCustomizers.orderedStream().collect(Collectors.toList()));
factory.getTomcatContextCustomizers()
.addAll(contextCustomizers.orderedStream().collect(Collectors.toList()));
factory.getTomcatProtocolHandlerCustomizers()
.addAll(protocolHandlerCustomizers.orderedStream().collect(Collectors.toList()));
return factory;
}
}
// ...
}
@ConditionalOnClass 어노테이션이 있는 라인이 이 내용의 핵심 개념입니다. 해당 어노테이션은 Tomcat 클래스가 클래스 경로에 있는 경우(tomcat-embed-core 아티팩트에도 포함된 다른 클래스 중에서) EmbeddedTomcat configuration을 처리해야 한다고 Spring에 지시합니다. 해당 클래스는 이전에 전이적 종속성을 검색하는 동안 이미 찾았으므로 실제로 클래스 경로에 포함됩니다.
따라서, 정의된 빈은 클래스패스에 로드될 것이며, 이 빈은 TomcatServletWebServerFactory 객체입니다. 이 팩토리는 Spring Boot의 핵심 아티팩트(spring-boot, 또한 spring-boot-starter에 포함된 종속성) 내에 포함되어 있습니다. 이 클래스는 Tomcat 내장 서버를 설정하므로 여기가 주요 로직이 실제로 존재하는 곳입니다.
'Spring Boot' 카테고리의 다른 글
Apache kafka (0) | 2024.04.10 |
---|---|
@SessionAttributes / @ModelAttribute (0) | 2024.04.10 |
Lombok (0) | 2024.04.10 |
SLF4J (0) | 2024.04.10 |
@Autowired (0) | 2024.04.10 |