이 레포 를 기반으로 학습합니다.
1. Petclinic 프로젝트 실행
- 해당 레포를 클론 한 후 Intellij를 해당 폴더를 basedir 로 엽니다.
- Intellij가 자동적으로 dependency와 plugin들을 설치해줍니다.
- Cli에 ./mvnw package를 통해 패키지를 빌드해 줍니다
- maven에 packaging 옵션이 없어서 기본적으로 jar 패키지가 되므로, 빌드하여 생성된 jar 파일을 java로 실행하면 동작합니다.
2. Properties 변경을 통한 환경 설정
src > main > resource 의 application.properties 에서 spring 관련 옵션을 지정해줍니다.
# database init, supports mysql too
database=h2
spring.datasource.schema=classpath*:db/${database}/schema.sql
spring.datasource.data=classpath*:db/${database}/data.sql
# Web
spring.thymeleaf.mode=HTML
# JPA
spring.jpa.hibernate.ddl-auto=none
spring.jpa.open-in-view=false
# Internationalization
spring.messages.basename=messages/messages
# Actuator
management.endpoints.web.exposure.include=*
# Logging
logging.level.org.springframework=INFO
logging.level.org.springframework.web=DEBUG
logging.level.org.springframework.context.annotation=TRACE
logging.level.org.springframework.context.anno
# Maximum time static resources should be cached
spring.resources.cache.cachecontrol.max-age=12h
3. 서버 요청
DispatcherServlet -> Controller의 메소드 호출 -> Owner 객체 생성 후 모델에 등록 -> 리턴할 view의 경로를 반환
-> templates 에 있는 html을 반환
4. IoC
의존성을 주입해주는 걸 Dependency Injection 이라고 하는데
그 제어권을 다른 대상에게 넘겨주는 것이 Inversion of Control 입니다.
스프링이 관리하는 객체인 Bean 을 등록하면
해당 객체에 대해 의존성 주입을 대신 수행해줍니다
Bean은 Annotation을 통해 등록해줍니다.
5. IoC Container
- ApplicationContext (BeanFactory)
bean을 만들고 의존성을 엮어주며(의존성 주입) 제공해줍니다.
그치만 실제로 소스코드에서 직접 참고해서 쓸 일은 많이 없습니다.
Controller, Repository 들은 이 Ioc Container (ApplicationContext) 에 들어있습니다.
물론 모든 객체로 등록되어 있는 것은 아닙니다.
Entity, Dto 이런 것들은 그렇지 않습니다.
생성자에 명시된 인자와 동일한 타입의 Bean을 찾아서 주입해줍니다.
의존성 주입은 Spring IoC Container 에 있는 Bean 들끼리만 가능합니다.
ApplicationContext를 Bean에 주입해서 가져다 쓸 수도 있지만, 거의 그럴 일은 없다고 보면 됩니다.
어떤 인스턴스 하나를 어플리케이션 전반에서 재사용함으로써
멀티쓰레드 상황에서 Singleton 을 매우 손쉽게 적용할 수 있습니다.
6. Bean
스프링에서 Bean은 ApplicationContext가 알고 관리하는 객체들입니다.
오로지 이런 Bean들만 서로 의존성 주입이 가능합니다.
Bean을 등록하는 방법은 2가지가 있는데요,
하나는 Component Scanning이고 (일반적인 방식)
다른 하나는 XML 및 자바 설정 파일에 등록하는 것입니다. (구닥다리 방식)
Component Scanning은 Component라는 Annotation이 되어있는 객체를 찾는 것인데요
Annotation Processor 중에 Spring IoC Container가 빈을 등록할 때 사용하는 여러 인터페이스가 있는데
그런 인터페이스들을 Lifecycle Callback 이라고 합니다.
여러 Lifecycle Callback 중에는 이런 Component 라는 Annotation 이 붙어있는 모든 클래스를 찾아서
그 클래스의 인스턴스를 만들어 Bean으로 등록해주는 것이 있습니다.
위와 같이 @Component 어노테이션이 적용된 어노테이션들은 다양합니다
@Controller @Repository @Service @Configuration ..etc
Spring Boot 의 경우엔 @SpringBootApplication Annotation 엔
내부적으로 @ComponentScan Annotation이 그 역할(Bean을 등록)을 하는 라이프사이클을 제공합니다.
덕분에 @SpringBootApplication 이라는 어노테이션이 붙은 빈이
위치한 폴더의 하위 폴더에 있는 모든 컴포넌트를 스캔합니다.
ComponentScan은 어느 지점부터 찾을지를 알려주고
Component는관리할 대상을 알려줍니다.
어노테이션이 아니라 Configuration을 이용해도 되는데 요즘에 xml로 작성하는 일은 거의 없고
다음과 같이 직접 메소드 단에서 Bean을 만들어 줄 수 있습니다.
@Configuration
public class SampleConfig {
@Bean
public SampleController sampleController(){
return new SampleController();
}
}
@Configuration 이 Bean이여서 먼저 Context에서 관리되고
그 후에 다음 메소드들이 호출되어 생성된 객체가 Bean으로 등록되게 됩니다.
7. 의존성 주입
의존성 주입을 명시하는 방법은 여러가지가 있습니다.
- 생성자에 @Autowired 어노테이션을 붙여줍니다.
- 멤버변수(field)에 @Autowired 어노테이션을 붙여줍니다. (그냥 해줍니다)
- 스프링 4.3부터는 그냥 생성자만 선언해도, 인자가 Bean으로 등록되어 있으면 자동으로 Bean으로 관리해줍니다.
- Setter를 지정하여 그 Setter에 @Autowired를 붙여주는 방법도 있습니다.
물론 @Autowired를 붙였다는건 그 대상이 Bean임을 전제하는 거라, Bean이 아니면 주입이 안됩니다.
여러 방법 중에서 생성자를 사용하는 방법을 권장합니다.
필수적으로 사용해야 하는 레퍼런스 없이 객체를 만들지 못하도록 강제할 수 있기 때문입니다.
특정 의존성이 없을 때 해당 객체가 정상적으로 동작하지 않는다면
생성자를 선언함으로써 주입을 보장할 수 있습니다.
Field Injection 이나 Setter Injection 은 의존성이 없이도 강제로 만들 수 있습니다.
물론 그게 장점이 되는 경우도 있습니다. (순환 참조의 경우)
만약 상호 의존적인 객체가 둘다 생성자를 사용하면.. 노답입니다. 가급적으로 의존성 조율을..
조율이 안되면 reflection 으로 해결..
'Java > Spring' 카테고리의 다른 글
[6] 스프링 프레임워크 핵심 - Component Scan, Bean Scope (0) | 2020.12.05 |
---|---|
[5] 스프링 프레임워크 핵심 - Autowired (0) | 2020.12.04 |
[4] 스프링 프레임워크 핵심 - IOC 컨테이너와 Bean (0) | 2020.11.30 |
[3] 간략한 스프링 개요 - PSA (0) | 2020.11.30 |
[2] 간략한 스프링 개요 - AOP (0) | 2020.11.28 |
댓글