이번 WIL의 키워드
1.DI
2.IoC
3.Bean
기본개념
스프링에 대한 얘기를 하면서 빠지지 않는 개념이
'의존성 주입'
이라는 개념이다.
의존성(Dependency)
이라는 것은 하나의 객체가 다른 객체 없이 제대로 된 역할을 할 수 없다는 것을 의미한다.의존성
은 하나의 객체가 다른 객체의 상태에 따라 영향을 받는 것을 의미한다. 흔히 A 객체가 B 객체 없이 동작이 불가능한 상황을 'A가 B에 의존적이다'라고 표현한다.주입(Injection)
은 말 그대로 외부에서 '밀어 넣는 것'을 의미한다.'의존성 주입'
방식을 사용하려면 두번째 그림의 오른쪽 도형처럼 추가적인 하나의 존재가 필요하게 된다. 이 존재는 의존성이 필요한 객체에 필요한 객체를 찾아서 '주입'
하는 역할을 하게 된다.'ApplicationContext'
라는 존재가 필요한 객체들을 생성하고, 필요한 객체들을 주입하는 역할을 해 주는 구조이다.ApplicationContext
가 관리하는 객체들을 '빈(Bean)'
이라는 용어로 부르고, 빈과 빈 사이의 의존관계를 처리하는 방식으로 XML 설정, 어노테이션 설정, Java 설정 방식을 이용할 수 있다.기본개념
스프링 컨테이너가 필요에 따라 개발자 대신 Bean들을 관리(제어)해주는 행위
일반적인 상황에서는 개발자가 직접 객체를 제어해야 했다. new
연산자를 통해 객체를 생성하고, 객체의 의존성을 맺어주고, 초기화를 해주고 등등...
하지만 Spring 에서는 xml 파일 또는 어노테이션 방식으로 스프링 컨테이너에 Bean(객체)
를 등록하기만 하면, 스프링 컨테이너에서 Bean
의 생명주기(생성 → 의존성 설정 → 초기화 → 소멸)를 전부 관리해준다.
즉, 객체에 대한 제어권이 컨테이너로 역전되기 때문에 제어의 역전이라고 하는 것이다.
- Spring에서는 제어의 역전을 지원하여, 필요에 따라 개발자대신 스프링 컨테이너가 객체(Bean)들을 제어해준다.
- 스프링 컨테이너는 Bean들의 생명주기(생성 -> 의존성 설정 -> 초기화 -> 소멸)을 관리하며, 필요에 따라 객체 간 의존성 주입을 해준다.
- 제어의 역전은 의존성 주입의 상위 개념이다.
- 제어의 역전은 코드의 재사용성과 유지보수성을 높인다.
기본 개념
Bean
은Spring IoC Container
가 관리하는 자바 객체,Spring Bean Container
에 존재하는 객체를 말한다.
Spring
에서는 Spring Container
, IoC Container
라는 개념을 사용한다.Container
는 인스턴스의 생명주기를 관리하며, 생성된 인스턴스들에게 추가적인 기능을 제공하도록 하는 것이다.Container
는 개발자가 작성한 코드의 처리과정을 위임받는 독립적인 존재라고 생각하면 된다.Container
는 적절한 설정만 되어있다면 누구의 도움 없이도 작성한 코드를 스스로 참조한 뒤 알아서 객체의 생성과 소멸을 컨트롤해준다.Spring Container
는 Spring framework
의 핵심부에 위치하며, 종속 객체 주입을 이용하여 Application을 구성하는 Component
들을 관리한다.Spring Container
에서 생성되는 객체를 Bean
이라고 한다.Spring IoC(Inversion of Control) Container
에 의해 인스턴스화, 관리, 생성된다.Bean Container
는 의존성 주입을 통해 Bean 객체를 사용할 수 있도록 해준다.Bean
은 보통 Singleton
으로 존재한다.Singleton
: 어떤 Class가 최초 한번만 메모리를 할당하고(Static) 그 메모리에 객체를 만들어 사용하는 디자인 패턴POJO(Plain Old Java Object)
를 Beans
라고 부른다.POJO
: 본래 자바의 장점을 살리는 특정 '기술'에 종속되어 동작하는 것이 아닌 '오래된' 방식의 '순수한' 자바객체Beans
는 Application의 핵심을 이루는 객체이며, 대부분 Container
에 공급하는 설정 메타 데이터(XML 파일)에 의해 생성된다.Container
는 이 메타 데이터를 통해 Bean
의 생성, Bean Life Cycle
, Bean Dependency(종속성)
등을 알 수 있다.Bean
이 아니고, ApplicationContext.getBean()
으로 얻어질 수 있는 객체는 Bean
이다.Bean
은 ApplicationContext
가 알고있는 객체, 즉 ApplicationContext
가 만들어서 그 안에 담고있는 객체를 의미한다.Spring IoC Container
가 IoC Container
를 만들고 그 안에 Bean
을 등록할때 사용하는 Interface
들을 Life Cycle Callback
이라고 부른다.Life Cycle Callback
중에는 @Conponent
가 붙어있는 모든 Class의 Instance를 생성해 Bean
으로 등록하는 작업을 수행하는 Anotation Process가 등록되어있다.@ComponentScan
, @Component
Anotation이 붙어있는 Class가 이에 해당한다.@ComponentScan
, @Component
Anotation을 사용해서 Bean
을 등록하는 방법이다.@ComponentScan
은 어느 지점부터 Component
를 찾으라고 알려주는 역할을 하고, @Component
는 실제로 찾아서 Bean
으로 등록할 Class를 의미한다.@ComponentScan
이 붙어있는 Class가 있는 package에서부터 모든 하위 package의 모든 Class를 찾아 다니며, @Component
나 @Component
를 사용하는 다른 Annotation
을 사용하는 Class를 찾는다.Bean
등록 방법은, XML에 설정하는 방법과 Java Class에 설정하는 방법이 있다.Bean
설정파일은 XML과 자바 설정파일로 작성할 수 있는데 일반적으로는 XML에 설정하지만, 최근 추세는 자바 설정파일을 좀 더 많이 사용한다.@Configuration
Annotation을 사용해서 직접 @Bean
을 등록해주는 방법이다.@Bean
Annotation을 사용해 직접 Bean
을 정의하면 자동으로 Bean
으로 등록된다.Bean
을 직접 정의해서 등록하면 @Component
Annotation을 붙이지 않아도 된다.@Configuration
public class ExampleConfiguration {
@Bean
public ExampleController exampleController() {
return new ExampleController;
}
}
exampleController()
에서 리턴되는 객체(ExampleController)
가 IoC Container
안에 Bean
으로 등록된다.
@Configuration
Annotation을 보면 이 Annotation도 내부적으로 @Component
를 사용하기 때문에 @ComponentScan
의 검색 대상이 되고,
그에 따라 Bean
을 정의한 @Configuration
이 읽힐때 그 안에 정의한 Bean
들이 IoC Container
에 등록되는 것이다.
XML 파일에 직접 Bean
을 등록하여 Application의 Bean
을 설정하는 방법이다.
XML 방식으로 Bean
을 정의하는데 필요한 속성들은 아래와 같다.
기본적인 양식은 아래와 같다.
<!-- A simple bean definition -->
<bean id="..." class="..."></bean>
<!-- A bean definition with scope-->
<bean id="..." class="..." scope="singleton"></bean>
<!-- A bean definition with property -->
<bean id="..." class="...">
<property name="message" value="Hello World!"/>
</bean>
<!-- A bean definition with initialization method -->
<bean id="..." class="..." init-method="..."></bean>
-실제 사용되는 예시는 아래와 같다.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">
<bean id="dog" class="com.spring.Dog">
<property name="myName" value="poodle"></property>
</bean>
<bean id="cat" class="com.spring.Cat">
<property name="myName" value="bella"></property>
</bean>
<bean id="petOwner" class="com.spring.PetOwner" scope="singleton">
<constructor-arg name="animal" ref="dog"></constructor-arg>
</bean>
</beans>
Bean
을 Singleton
으로 생성하여 관리한다.Singleton
Bean
은 Spring Container에서 한 번 생성 후, Container가 사라질 때 Bean
도 제거.Instance
는 Single Beans Cache
에 저장되고, 해당 Bean
에 대한 요청과 참조가 있으면 캐시된 객체를 반환.Bean
은 Scope
가 명시적으로 지정되지 않으면 Singleton
.Bean
마다 하나의 객체를 생성하는 것을 의미한다.Bean
을 주입 받으면 언제나 주입받은 Bean
은 동일한 객체라는 가정하에서 개발 한다.request
, session
, global session
의 Scope는 일반 Spring Application이 아닌, Spring MVC Web Application에서만 사용