스프링 컨테이너 : Bean이라고 불리우는, 객체의 생성주기를 관리하고, DI 를 관리함.
그 중 스프링 컨테이너가 갖고 있는 설정 중 application context 가 담당하게 된다. 이 application context 는 가장 주요한 작업은 bean을 생성하고, bean 간의 관계를 설정하는 것이다.
따라서 application context를, 다른 말로 bean factory 라고도 부른다.
spring container
의 동작 방식은 IoC 의 개념이 가미된 방식이기 때문에, 다른 말로 spring IoC container
라고도 부른다.
하나의 객체를 다른 객체에 주입하는 것, 즉 객체의 동적 연결
을 담당하는 것이 스프링 컨테이너
이다. 즉 DI 작업도 스프링 컨테이너가 담당한다. 그런데 이 작업이 가장 중요한 작업이기 때문에 스프링 컨테이너를 다른 말로 스프링 DI container
라고 부른다, 근데 말이 길기 때문에 DI container
라고 부른다.
application context가 제어권을 가지고 직접 만들고, 관계를 부여하는 객체를 Bean
이라고 부른다.
POJO(plain Old Java Object) : 가장 기본적인, 근본에 가까운 객체.
bean 은 추상 클래스나 인터페이스의 상속이라 구현 등을 거쳐 만들어지는 가공된 특수한 객체가 아닌, 가장 기본적인 자바의 방식으로 생성된 객체이다.
스프링 Ioc/DI container 에 의해 관리가 된다.
bean 이 가진 주요한 속성
application context가 bean을 사용하기 위해서는 설정 정보(configuration, metadata..)가 있어야 한다.
설정을 입력하는 방식에는 2가지 방법이 존재한다.
첫 번째는 xml, 두 번째는 annotation 방식이다.
만들 때에 편리한 방식은 annotation 이지만, 향후에 유지 보수 시, 전체적인 bean 들을 일괄적으로 확인하기는 어렵다는 단점이 있다.
bean을 등록한다는 의미는, 설정 정보를 읽어와서 bean 객체를 만들 준비를 한다는 의미이다.
bean 등록 방법에는 두 가지 방법이 있다.
1. 수동 방법 : 외부 라이브러리를 가지고 와서 bean 으로 등록할 때에는 수동으로 등록해주어야만 한다.
class MyResource {
// 내가 등록하려는 객체
}
@Configuration
class MyResourceConfig {
// MyResource 라는 객체를 등록하기 위한 설정 정보를 담는 객체
@Bean
public MyResource getResource() {
return new MyResource();
}
}
@Bean 어노테이션이 붙은 메소드의 메소드명 ex) getResource
가 Bean 의 Id 값이 된다.
@Configuration :
@Components 라는 어노테이션이 붙은 클래스
는 자동으로 bean 으로 등록된다. 그런데 @Component 라는 어노테이션을 상속받아 오버라이딩한 하위 어노테이션이 있다. 그것이 @Controller
, @Service
, @Repository
, @Configuration
이다.
@Configuraion 과 같이 자동으로 등록되는 Bean 의 id 는 해당 클래스의 생성자 이름을 따라간다. 다만 주의해야 할 점은 카멜 케이스에 의해 첫글자는 소문자로 인식된다.
ex) MyResourceConfig 라는 @Configuraion 은 자동으로 Bean 으로 등록되는데, 이 때의 id 는 myResourceCongig
가 된다.
spring context : ..
예제
ApplicationContext 를 통해 전달받은 객체 dao와 dao1 은 싱글톤 패턴에 의해 동일한 객체이다.
ApplicationContext 의 기능 중 하나는 계속해서 언급되다싶이 객체를 singleton 으로 관리한다는 점.
왜 bean 객체를 singleton으로 bean 을 관리할까?
=> spring은 server을 application을 구현하기 위해서 사용했는데 여러 클라이언트에 의해 공유되는 객체가 필요하다.
이 때, 공유되는 객체
를 유지하기 위해서는 singleton으로 유지해야 효율이 좋다.
주의해야 할 점은, 객체 자체는 공유될 수 있다. 다만 싱글톤의 객체를 사용할 때에는 Stateless
를 유지해야 한다. 하지만 VO 객체들의 경우, 상태정보를(각각의 VO 마다의 고유한 정보들) 가지고 있기 때문에 Bean 으로 사용하지 않는다.
두 개의 class 를 대상으로 한다.
A가 B를 의존한다, 라는 것은 B의 내용이 바뀔 경우 A의 내용이 바뀌거가 심하면 아예 사용이 불가능할 수도 있음을 의미한다.
DI의 Injection 방법에는 2가지가 존재한다.
생성자 주입
Setter 주입
xml 파일에는 문서의 구조가 미리 정해진 형태로 만들어졌는지 검증하는 기능이 있다. 즉 어떤 xml 이냐에 따라서 사용가능한 태그와 태그의 구조가 이미 결정되어있다.
이러한 검증 작업을 하는 방식에도 2가지가 존재한다.
Beans라는 파일 이름과 applicationContext 라는 두 가지 파일 이름으로 작성한다.
파일 생성 방법
이클립스와는 달리 인텔리제이에서의 applicationContext.xml 의 생성은 다음과 같다.
그러면 다음과 같은 schema 가 기본구조로 생성된다.
참고로 이클립스의 경우에는 namespace 를 추가적으로 구성하는 설정이 있었는데, 인텔리제이의 경우에는
<beans
// 이 태그 안에 사용하려는 값을 입력하면 자동완성이 되기 때문에 참고해서 추가적 사항을 입력할 수 있다.
>
Bean으로 객체를 생성할 때, 인자를 주입하여 생성하고자 한다면 두 가지 방법이 존재한다.
첫 번째 방식이 생성자에 인자를 주입하는 방식인 constructor-arg
이고,
두 번째 방식이 setter 메소드를 통해 인자를 주입하는 빙삭인
property
이다.
생성자를 통한 주입의 Bean 태그의 예시
Setter 를 통한 주입의 Bean 태그의 예시
또한 생성자 혹은 Setter 를 통한 주입의 과정에서 원시데이터가 아닌 참조(String을 제외한) 타입의 데이터를 주입한다면,
주입하고자 하는 데이터를 bean 으로 등록한 뒤 constructor-arg 혹은 property 에 value
가 아닌 ref
속성의 값으로 해당 bean 의 id 값을 넣는다.
추상 클래스 혹은 싱글톤 패턴의 경우, 객체를 생성하지 않는 것이 기본적인 특징이다. 그런데 해당 케이스에서도 예제의 getInstance()
와 같은 추상 클래스 내부에서 해당 추상 클래스나 싱글톤을 구현한 객체를 반환할 경우가 있다.
Constructor-arg
, property
들은 각각의 schema 를 통해 축약형을 기입을 할 수 있다.
우선 축약형을 사용하기 위해서는 uri 링크를 통해 schema/c 와 schema/p 를 가지고 오되, 각각의 uri 에 대한 namespace 를 명시해준다. 대체로 c, p로 명시한다.
그 후, c => Constructor-arg 를 사용할 때에는
c:"인자명"="value"
혹은
c:_"index 번호"="value"
의 형태로 bean 태그 안에 입력해준다.
마찬가지로 p => property 를 사용할 때에는
p:"인자명"="value"
혹은
p:_"index 번호"="value"
의 형태로 bean 태그 안에 입력해준다.