1. XML: <bean> 태그
- <bean>태그를 사용하는 건 가장 단순하면서 강력한 설정 방법.
- 기본적으로 id와 class라는 두개의 어트리뷰트가 필요 (id 생략 가능)
<bean id="hello" class="springbook.leaningtest.spring.ioc.bean.Hello">
...
</bean>
- <bean>은 다른 빈의 <property> 태그 안에 정의가 가능 (이때는 id, 이름을 지정하지 않음)
이러한 빈을 내부 빈(inner bean)이라 하며, 다른 빈에서는 참조할 수 없음. 강한 결합이 필요한 경우에 사용
<bean id="hello" class="springbook.leaningtest.spring.ioc.bean.Hello">
<property name="printer">
<bean class="springbook.leaningtest.spring.ioc.bean.StringPrinter"/>
</property>
</bean>
2. XML: 네임스페이스와 전용 태그
- <bean> 태그 외에 전용 태그를 사용해 빈을 등록하는 방법
- 스프링의 빈의 두가지 분류
1. 애플리케이션의 핵심 코드를 담은 컴포넌트
2. 서비스 또는 컨테이너 설정을 위한 빈
- 스프링은 DI의 원리로 애플리케이션 컨텍스트 자신에게 필요한 정보도 오브젝트 형태로 DI해서 사용
- 이를 통해 컨테이너의 유연한 확장이 가능
- 애플리케이션 로직을 담은 빈이 동일하게 <bean>이라는 태그를 사용해서 만들면 구분이 안됨
-> 의미가 잘 드러나는 네임스페이스와 태그를 가진 설정 방법을 제공
- 전용 태그 하나로 동시에 여러개의 빈을 만들수 있다는 장점
-> ex) <context:annotaion-config> 이 태그 하나로 보통 5개의 빈이 선언
* 스프링이 제공해주는 것 외에도 개발자가 스스로 커스텀 태그를 만들어서 적용할 수도 있음.
장점
1. 내용이 매우 분명하게 드러나고 선언 자체도 깔끔
2. 다른 빈 설정과 혼동 되지도 않는다.
<bean> 태그를 이용한 AOP 설정
<bean id="mypoint" class="org.springframework.aop.aspectj.AspectJExpressionPoinrCut">
<property name="expression" value="execution(* *.. *ServiceImp.upgrade*(..)")
</bean>
<aop> 전용 태그를 이용한 AOP 설정
<aop:pointcut id="mypointcut" expression="execution(* *..*ServiceImpl.upgrade*(..))" />
3. 자동인식을 이용한 빈 등록: 스트레오타입 애노테이션과 빈 스캐너
XML을 통한 빈 관리의 단점
1. 애플리케이션의 규모가 커지고 빈의 개수가 많아지면 XML 파일을 관리하기가 번거로움
2. 여러 개발자가 설정파일을 공유해서 개발하다 동시에 수정을하면 충돌이 일어나는 경우가 발생
- 빈 스캐닝을 통한 자동인식 빈 등록: 애노테이션이 붙은 클래스를 자동으로 찾아서 빈으로 등록하는 방식
- 빈 스캐너: 스캐닝 작업을 담당하는 오브젝트
- 빈 스캐너는 지정된 클래스패스 아래에 있는 모든 패키지의 클래스를 대상으로 함
- 스테레오타입 애노테이션: @Component를 포함해 디폴트 필터에 적용되어 있는 애노테이션
- 빈 스캐너는 기본적으로 클래스 이름을 빈의 아이디로 사용 (첫 글자만 소문자로 바꿈)
- 모든 클래스를 다 검색하는 것은 비효율적이며, 패키지를 지정하는 것이 바람직.
지정된 패키지와 그 서브패키지의 클래스들이 자동 검색 대상
@Component("myAnnotatedHello")
public class AnnotatedHello{
...
}
빈의 이름을 클래스 이름과 다르게 지정해야 하는 경우
1. 같은 빈이 이미 존재하여 충돌을 피해야 하는 경우
2. 좀 더 의미있는 이름을 사용하고 싶은 경우
자동 스캔으로 빈을 등록할 때의 장/단점
<장점>
1. 복잡한 XML문서 생성과 관리에 수고를 덜어주어 개발속도 향상
<단점>
1. 애플리케이션에 등록될 빈의 유무와 정의를 파악하기 힘듬
2. XML처럼 상세한 메타정보 항목을 지정할 수 없음
3. 클래스당 1개 이상의 빈을 등록할 수 없다는 제한
<단점의 해결방안>
1. 생산성을 위해 빈 스캐닝을 사용하여 빈 등록
2. 어느 정도 마무리가 되면, 세밀한 관리와 제어가 필요한 운영 시점에 XML형태의 빈 선언을 적용
자동인식을 통한 빈 등록을 사용하기 위한 2가지 방법
1. XML을 이용한 빈 스캐너 등록
- 모든 빈을 스캔하고 싶다면 XML 설정 파일에 <context:component-scan> 태그를 이용
<context:component-scan base-package="springbook.learningtest.spring.ioc.bean" />
2. 빈 스캐너를 내장한 애플리케이션 컨텍스트 사용
- AnnotationConfigApplicationContext, 등을 이용
- web.xml안에 컨텍스트 파라미터 설정 변경 필요
@Component 외에 스테레오타입 애노테이션
1. @Repository : 데이터 엑세스 계층의 DAO또는 리포지토리 클래스에 사용
2. @Service: 서비스 계층의 클래스에 사용
3. @Controller: 프레젠테이션 계층읠 MVC컨트롤러에 사용
* 특정 계층으로 분류하기 힘든 경우 @Component를 사용하는 것이 바람직
4. 자바 코드에 의한 빈 등록: @Configuration 클래스의 @Bean 매소드
- 오브젝트 팩토리: 오브젝트 생성과 의존관계를 주입을 담당하는 오브젝트
- 팩토리 빈은 <bean> 태그를 이용해 빈으로 등록 또 팩토리 빈당 하나의 빈만 정의 가능
- 그에 반해 자바코드에 의한 빈 등록 기능은 하나의 클래스 안에 여러 개의 빈을 정의
- 빈 설정 메타정보를 담고 있는 자바 코드는 @Configuration 애노테이션
- @Bean 메소드를 통해 빈을 정의
XML 문서와 대칭 구조
<beans> - @Configuration
<bean> - @Bean
@Configuration
public class AnnotatedHelloConfig{
@Bean
public AnnotatedHello annotatedHello(){
return new AnnotatedHello();
}
}
* 설정을 담은 자바 코드에 해당하는 AnnotatedHelloConfig 클래스 자체도 하나의 빈으로 등록 됨
- new AnnotatedHello() 코드가 존재해도 싱글톤이므로 단 한 번만 만들어짐
- 스프링은 @Bean이 붙은 메소드를 이용해 빈을 만들면 새로운 오브젝트가 만들어지지 않도록 @Bean 메소드를 조작
@Configuration
public class HelloConfig{
@Bean
public Hello hello(){
Hello hello = new Hello();
hello.setPrinter(printer());
return hello;
}
@Bean
public Hello hello2(){
Hello hello = new Hello();
hello.setPrinter(printer());
return hello;
}
@Bean
public Printer printer(){
return new StringPrinter();
}
}
-> hello(), hello2()에서 사용된 printer()는 모두 동일한 객체(1번만 만들어짐)
- 등록하기 힘든 기술 서비스 빈의 등록이나 컨테이너 설정용 빈을 XML 없이 등록할때 유용
- 프로퍼티 값을 지정하는 것을 비롯해 어떤 종류의 빈 설정이라도 손쉽게 만듬
- 동시의 빈 스캐너의 자동인식 대상
자바 코드 설정이 XML같은 외부 설정보다 유용한 점
1. 컴파일러나 IDE를 통한 타입 검증이 가능하다.
- XML은 텍스트 문서다. 이름, 프로퍼티, 등에 오류를 검증할 수 없음
-> 자바 코드는 클래스나 프로퍼티 이름이 정확하지 않으면 컴파일 에러가 발생
2. 자동완성과 같은 IDE 지원 기능을 최대한 이용할 수 있다.
- 자바 에디터의 자동완성을 통해 작성 속도가 향상된다.
3. 이해하기 쉽다.
4. 복잡한 빈 설정이나 초기화 작업을 손쉽게 적용할 수 있다.
- @Bean 메소드를 이용해 빈을 저의하는 경우 여러개 빈을 만들기 쉽다.
- 자바코드를 통한 초기화 작업이 가능하며, new 키워드 대신 스태틱 팩토리 메소드 등을 이용해 빈 오브젝트 생성이 가능
5. 자바 코드에 의한 빈 등록: 일반 빈 클래스의 @Bean 메소드
- @Configuration이 붙은 클래스가 아닌 일반 POJO 클래스에도 @Bean을 사용할 수 있음
- @Bean 메소드를 가진 클래스는 어떤 방법으로든지 빈으로 등록 필요
- @Configuration이 붙은 @Bean과 아닌 @Bean의 미묘한 차이점이 존재
public class HelloConfig{
@Bean
public Hello hello(){
Hello hello = new Hello();
hello.setPrinter(printer());
return hello;
}
@Bean
public Hello hello2(){
Hello hello = new Hello();
hello.setPrinter(printer());
return hello;
}
@Bean
public Printer printer(){
return new StringPrinter();
}
}
*printer()가 싱글톤이 아닌 새로운 객체로 생성, @Configuration 클래스 안에서만 싱글톤
- 싱글톤으로 사용하기 위한 방법은 클래스에서 직접 DI를 받은 뒤 사용
public class HelloConfig{
//---- 변경한 영역----
private Printer printer;
public void setPrinter(Printer printer){
this.printer = printer;
}
//---- 변경한 영역----
@Bean
public Hello hello(){
Hello hello = new Hello();
hello.setPrinter(this.printer); //DI 받음
return hello;
}
@Bean
public Hello hello2(){
Hello hello = new Hello();
hello.setPrinter(this.printer); //DI 받음
return hello;
}
@Bean
public Printer printer(){
return new StringPrinter();
}
}
- 일반 빈 클래스에 @Bean 메소드 사용하는 경우
-> 빈과 매우 밀접한 관계를 가진 경우
- 일반 빈 클래스에 @Bean 메소드 사용에 단점
-> 설정정보가 일반 애플리케이션 코드와 함께 존재하기 때문에 유연성이 떨어짐
빈 등록 메타정보 구성 전략
1. XML 단독 사용
- 모든 빈을 명시적으로 XML 등록하는 방법
- <bean>과 스키자에 정의된 전용태그를 이용하는 방식
- 모든 설정정보를 자바 코드에 분리, 순수한 POJO코드를 유지하고 싶을때 좋은 선택
- 기존에 개발된 애플리케이션에서 코드에 손대지 않고 재사용하고 싶을 경우에 유용
- 특화된 커스텀 스키마와 전용 태그를 만들어서 사용하는 경우 좋은 이점을 가짐
2. XML과 빈 스캐닝의 혼용
- 기술 서비스, 컨테이너 설정은 XML + 개발이 진행되면서 만들어지는 애플리케이션 빈들은 애노테이션을 부여해 자동스캔
- 단 스캔 대상이 되는 클래스를 위치시킬 패키지를 미리 결정해둬야 함
-> 최상위 패키지를 지정하므로 클래스를 중복해서 빈으로 등록할 수 있음
-> 잘못된 패키지 스캐닝 + 트랜잭션 AOP 설정이 겹치면 AOP적용이 되지 않는 현상이 발생
-> 컨텍스트 계층구조 내에서 같은 클래스의 빈이 중복 등록되는 것을 스프링이 문제삼지 않음
3. XML 없이 빈 스캐닝 단독 사용
- 애플리케이션 컴포넌트(Java) + 각종 기술 서비스와 컨테이너 설정용 빈(Java) 스캔으로 자동 등록
- 애노테이션을 부여할 수 있는 컴포넌트 클래스는 빈 스캔 대상
- 성격이 다른 @Configuration 자바 코드는 적절히 패키지를 구분해 주는 것이 좋음
<장점>
1. 모든 빈의 정보가 자바코드로 담겨있으므로 타입에 안전한 방식으로 작성
<단점>
1. 정의된 전용 태그를 사용할 수 없음
'개발서적 > 토비 스프링 3.1-Vol.2' 카테고리의 다른 글
[토비의 스프링 - Vol.2] 1장 - 1.4 기타 빈 설정 메타정보 (0) | 2022.01.17 |
---|---|
[토비의 스프링 - Vol.2] 1장 - 1.3 프로토타입과 스코프 (0) | 2022.01.17 |
[토비의 스프링 - Vol.2] 1장 - 1.2.5 컨테이너가 자동등록하는 빈 (0) | 2022.01.17 |
[토비의 스프링 - Vol.2] 1장 - 1.2.4 프로퍼티 값 설정 방법 (0) | 2022.01.17 |
[토비의 스프링 - Vol.2] 1장 - 1.2.3 빈 의존관계 설정 방법 (0) | 2022.01.17 |