참고
목차
- 의존성 관리
- 자동 설정
- 내장 서블릿 컨테이너
<!-- Inherit defaults from Spring Boot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
</parent>
<!-- Add typical dependencies for a web application -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
pom.xml에서 의존성을 정의할 때 버전을 명시하지 않았음에도 불구하고 Spring Boot는 알아서 적절한 버전을 가져와준다. 어떻게 가능한 걸까?
Spring Boot의 의존성 관리 기능 때문이다.
Spring Boot 이전에는 버전이 달라서 에러가 생기는 문제가 빈번히 일어났다.
자동 환경 설정은 스프링부트의 큰 장점이다. 스프링부트는 jdbc, h2 등 약 100여가지의 자동 설정(starter)를 제공한다.
요즘엔 쉽게 Starter 위주로 의존성을 추가하면 부모(spring-boot-starter-parent)로부터 의존성을 상속받기 때문에 UTF-8 인코딩, 자바 버전, 플러그인 등 뿐만 아니라 버전도 자동으로 버전이 매핑된다. 따라서 Spring Boot Dependency에서 관리하는 의존성들은 굳이 버전을 명시하지 않아도 된다.
Spring Data JPA라는 의존성을 추가
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
Maven dependency 검색 사이트
<dependency>
<groupId>org.modelmapper</groupId>
<artifactId>modelmapper</artifactId>
<version>2.1.0</version>
</dependency>
spring-boot-dependencies-2.0.3.RELEASE.pom
에 버전들이 정리되어있다
...
<snakeyaml.version>1.19</snakeyaml.version>
<solr.version>6.6.4</solr.version>
<spring.version>5.0.7.RELEASE</spring.version>
<spring-amqp.version>2.0.4.RELEASE</spring-amqp.version>
<spring-batch.version>4.0.1.RELEASE</spring-batch.version>
<spring-cloud-connectors.version>2.0.2.RELEASE</spring-cloud-connectors.version>
<spring-data-releasetrain.version>Kay-SR8</spring-data-releasetrain.version>
<spring-hateoas.version>0.24.0.RELEASE</spring-hateoas.version>
...
Spring Boot에서 관리해주는 의존성 버전을 변경하고 싶을 때는 properties
에 버전을 추가해 Overriding 해주면 된다.
<properties>
<spring.version>5.0.6.RELEASE</spring.version>
</properties>
Configuration이란?
Spring의 Bean을 등록하는 JAVA 설정 파일
여러 설정을 일으키며 내장된 톰캣 서버에서 Web Application이 실행될 수 있는 이유 중에 하나는 Auto Configuration 때문이다.
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
excludeFilters = {@Filter(
type = FilterType.CUSTOM,
classes = {TypeExcludeFilter.class}
), @Filter(
type = FilterType.CUSTOM,
classes = {AutoConfigurationExcludeFilter.class}
@SpringBootApplication
어노테이션 안에 위와 같이 설정되어 있기 때문이다.
// @SpringBootApplication
@SpringBootConfiguration
@ComponentScan
@EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
스프링부트에서는 @EnableAutoConfiguration
또는 @SpringBootApplication
중 하나만 사용하면 자동 환경설정이 가능하다.
@SpringBootApplication 어노테이션을 사용하는 것은 다음의 세 어노테이션을 사용하는 것과 같다.
@SpringBootConfiguration
: 스프링부트 설정을 나타내는 어노테이션이다. 스프링의 @Configuration을 대체한다.@ComponentScan
: basePackages 프로퍼티 값에 별도의 경로를 설정하지 않으면 해당 어노테이션이 위치한 패키지가 루트 경로가 된다. 하위 루트까지 쭉 가면서 Bean을 등록한다.@Component
가 붙어있는 클래스를 찾아가서 모든 인스턴스를 생성해 빈으로 등록한다.@EnableAutoConfiguration
: 미리 정의된 Bean을 가져와서 등록해준다.ComponentScan
수행하면서 Bean 등록EnableAutoConfiguration
으로 추가적으로 읽어온 Bean들을 등록# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
등..
org.springframework.boot.autoconfigure.EnableAutoConfiguration
키 값 밑에 설정되어 있는 클래스들은 전부 auto configuration 적용 대상이 된다ConditionlOn
으로 시작메인 애플리케이션 클래스부터 하위의 Component라는 애노테이션을 가진 클래스들을 스캔해서 Bean으로 등록한다.
@Component
@Configuration
@Repository
@Service
@Controller
@RestController
- xxx-spring-boot-autoconfigure 모듈 : 자동설정
- xxx-spring-boot-starter 모듈 : 필요 의존성 정의
- xxx-spring-boot-starter : 하나로 만들기
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.0.3.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
package me.dsunni;
public class Holoman {
String name;
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;
}
@Override
public String toString() {
return "Holoman{" +
"name='" + name + '\'' +
", howLong=" + howLong +
'}';
}
}
package me.dsunni;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HolomanConfiguration {
@Bean
public Holoman holoman() {
Holoman holoman = new Holoman();
holoman.setHowLong(5);
holoman.setName("dsunni");
return holoman;
}
}
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
me.dsunni.HolomanConfiguration
Maven
- Lifecycle
- install
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>me.dsunni</groupId>
<artifactId>dsunni-spring-boot-starter</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
위와 같이 정상적으로 들어와 있는 것을 확인할 수 있다.
@SpringBootApplication
public class Application {
public static void main(String[] args) {
// SpringApplication.run(Application.class, args);
SpringApplication application = new SpringApplication(Application.class);
application.setWebApplicationType(WebApplicationType.NONE);
application.run(args);
}
}
메인 애플리케이션 수정 후 추가한 Holoman
Bean이 있는지 확인해보자
package me.dsunni;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
@Component
public class HolomanRunner implements ApplicationRunner {
@Autowired
Holoman holoman;
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println(holoman);
}
}
ApplicationRunner
인터페이스@Component
추가application.properties 파일을 통해 Bean을 정의해서 동적으로 생성하도록 해보자
application.properties
스프링부트는 application.properties 파일을 통해 설정을제공한다. 이 파일에는 부트가 제공하는 프로퍼티 뿐 아니라 커스텀 프로퍼티를 추가할 수 있다.
그 중 설정 프로퍼티 클래스를 사용하면 관련 설정을 한 클래스에서 관리할 수 있다.
동일한 key 값인 holoman들을 묶어서 Bean으로 등록할 수 있다
HolomanRunner는 application.properties에서 설정한 값을 읽어와 Holoman 빈을 재정의하게 된다.
package me.dsunni;
import org.springframework.boot.context.properties.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;
}
}
위 HolomanProperties 클래스는 property 파일을 통해 값을 가져오는 역할을 수행한다.
자동 설정 클래스 내의 스프링 빈을 property 파일을 통해 재정의 하고자 할 때는 이 어노테이션을 사용한다.
이 어노테이션을 사용하기 위해서는 먼저 다음과 같은 dependency를 추가해야한다.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
위 application.properties
파일에서 등록했던 Bean의 이름(holoman)을 괄호 안에 넣어준다.
그 후 properties 파일에 있던 name, how-long을 받을 수 있는 변수를 정의하고, getter와 setter를 만들어준다. 이렇게 하면 변수에 값을 받을 수 있게된다.
package me.dsunni;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableConfigurationProperties(HolomanProperties.class)
public class HolomanConfiguration {
@Bean
@ConditionalOnMissingBean
public Holoman holoman(HolomanProperties properties) {
Holoman holoman = new Holoman();
holoman.setHowLong(properties.getHowLong());
holoman.setName(properties.getName());
return holoman;
}
}
이 어노테이션을 통해 HolomanConfiguration 클래스를 프로퍼티 파일(HolomanProperties) 정보를 담고 있는 클래스로 자동 등록하게 해준다.
이 어노테이션은 스프링 부트 프로젝트 상에서 같은 이름의 스프링 빈이 있을 때에는 그 스프링 빈을 상요하고, 만약 없다면 자동 등록한 빈을 쓰게끔 유도해준다.