티스토리 뷰
DI : 종속객체 주입 DI를 다른말로 와이어링 이라고 한다
빈 설정 방식
1. XML을 이용한 명시적 설정
2. JAVA을 이용한 명시적 설정
3. 내장되어있는 빈을 알아서 찾아서 하는 자동설정
다양한 방법이있지만 무엇을 쓰든 개인취향
하지만 추천하자면 자동설정 > JAVA config > XML config
스프링의 자동설정
1. 컴포넌트 스캐닝 - Application Context에 생성되는 빈을 자동으로 발견
2. 오토와이어링 - 자동으로 빈 의존성을 충족
@ComponentScan, @Configuration 이게 붙어있으면 스프링이 빈으로 생성한다
Configuration : 스프링이 빈을 생성하기 위해 표시하는 어노테이션이며 빈을 1개만 생성하게해준다 @Bean은 여러개 생길수도있다.
코드 2.3 컴포넌트 스캐닝을 가능케 하는 @ComponentScan
package soundsystem;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class CDPlayerConfig {
}
xml을 이용한 컴포넌트 스캐닝은 <context:componenet-scan> 요소를 사용
xml로 컴포넌트 스캐닝 활성화하기
<?xml version="1.0M encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context=Mhttp://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.spri ngframework.org/schema/context/spring-context.xsdM>
〈context:component-scan base-package="soundsystem" />
</beans>
빈에 id값을 주고싶다면 @Named 사용 아니면 @Component
ComponentScan에 basepackage를 바꾸고 싶다면
@ComponentScan(basePackages="soundsystem") 으로 한다
이와 같이 할시 기본 베이스패키지는 사용하지못한다
packages 복수이기때문에 여러 패키지가 스캔 되도록 할수있다
@ComponentScan(basePackages={"soundsystem", "videosystem"})
하지만 이경우 typeSafe하지않다 실수로 이름을 잘못쓰거나 하는경우가 발생할수있따
그래서
@ComponentScan(basePakagesClasses={CDPlayer.class, DVDPlayer.class}) 와 같이 교체된다
String으로 지정하는 대신 클래스배열로 지정한다
클래스가 어떤 패키지안에있든 베이스패키지로서 사용된다
* 스캔될 페이지 안의 비어있는 마커 인터페이스 생성을 고려해야한다
마커인터페이스 : 리팩토링이 쉽도록 인터페이스에대한 레퍼런스만 가지게되고 실제 어플리케이션 코드에 대한 레퍼런스를 사용하지 않을 수 있다.
의존성이 필요하면 오토와이어링이 필요하다
@Autowired : 자동으로 의존성 객체를 처리한다
오토와이어는 어떤 메소드든지 다 붙일수있다 ex) 생성자, 일반 메소드, 세터 메소드 등
1개의 빈이 일치하면 그 빈이 와이어링되고 못찾으면 예외를 발생시킨다 예외 발생을 피하기위해서 required를 false로 설정한다
다중빈이 일치하면 예외를 발생시킨다
오토와이어를 사용할때는 항상 null체크를 해야한다 아니면 NullPointerException이 생길수있다
@Autowired로 와이어링이 힘들경우 @Inject를 사용해도된다
둘다 스프링에서 지원하며 둘중 어느것을 사용해도 상관없다 좀 더 자신에게 맞는것을 사용하면된다.
@Autowired를 검증하기위해서 Junit을 이용
외부 라이브러리의 소스코드를 가지고있지않으므로 오토와이어는 불가능하다
그런 경우에는 명시적인 설정을 해야한다
명시적 설정에는 java_config, xml_config가 있으며 javaconfig가 좀더 강력하고 리팩토링이 쉽고 타입세이프하다 자바코드이기때문에
javaConfig는 설정용 코드이며 다른 자바코드와 완전히 동일하지는않다
javaConfig는 단순한 설정코드이며 다른어떤 비즈니스에도 영향을 미치지않는다 원래의 목적과 혼동되어 사용되서는 안된다
JavaConfig의 핵심은 @Configuration으로 애너테이트하는것
@Configuration : 설정 클래스로 식별하고 스프링 ApplicationContext에서 만들어진 빈의 자세한 내용이 포함될 수 있다는것을 나타낸다.
@Bean : 이 메소드가 스프링 ApplicationContext에서 빈으로 등록된 객체를 반환해야함을 나타냄
@Bean이 등록된 메소드는 궁극적으로 빈 인스턴슬르 만드는 로직을 포함한다
@Bean은 애너테이트된 메소드와 동일한 ID를 받는다
다른 ID를 사용하려면 @Bean(name="lonelyHeartsClubBand") name 속성을 사용
@Bean 메소드로 만들어진 빈은 1개만 존재하며 다시 메소드가 호출되면 스프링으 중간에 멈추고 이미만들어진것을 리턴해준다
@Bean 메소드의 이름이 서로 다르고 안에 만드는 빈이 같다면 스프링이 그 빈이 만들어진 빈임을 확인하고 만들어진것을 리턴해준다.
@Bean 메소드의 매개변수로 필요한 빈을 넣는방법은
스프링이 이 메소드를 호출할때 매개변수를 설정 메소드로 오토와이어링한다 그리고 몸체에서 이걸 사용한다
오랜시간 스프링이 xml설정을 해왔기에 어떻게 사용하는지 아는것이 중요하다
새로 작성하는 스프링은 자동설정, javaConfig를 사용하는것을 추천한다
xml 스키마 설정
javaConfig의 @Configuration 와 같은부분
<?xml version=n1.0n encoding="UTF-8"?>
<beans xmlns=nhttp://www.springframework.org/schema/beans"
xmlns:xsi=nhttp://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans•xsd
http://www.springframework.org/schema/context">
<!-- configuration details go here -->
</beans>
스프링 툴을 사용하여 XML 설정 만들기 스프링 X M L 설정 파일을 만들고 관리하
는 가장 쉬운 방법은 STS(Spring Tool Suite) 사용이다(https://spring.io/tools/sts). ST S 메뉴의
File -> New -> 스프링 빈 설정 파일에서 스프링 X M L 설정 파일을 생성하고, 가능한 설정
네임스페이스 중 하나를 선택한다.
빈 와이어링을 위한 가장 간단한 XML 요소는 스프링 빈 스키마(schema)에 포함되며. X M L 파일의 루트 네임스페이스로 선언된다. <beans> 요소, 즉 스프링 설정 파일의 루트 요소 이 스키마 중 한 요소다.
<bean class="soundsystem.SgtPeppers" />
javaconfig의 @Bean과 같다
id값을 주지않으면 클래스명으로 id가 생성된다
각 빈에 id 애트리뷰트를 통해
선택된 자신의 이름을 부여하는 것이 일반적으로 좋은 아이디어다
xml은 자바타입의 컴파일타임의 검증도움을 받지못한다
IDE를 이용하여 스프링 XML설정의 유효성을 확인할수있다
XML에서 빈설정은 오로지 하나의방법만있다 <bean>요소를 사용하고 클래스 애트리뷰트를 지정하는것이다.
xml로 di를 선언하는 방법
1. <constructor-arg>
2. c-네임스페이스
<constructor-arg>방식이 c-네임스페이스보다 더 보기 어렵다
생성자를 이용한 DI 방식
<bean id="cdPlayer" class="soundsystem.CDP1ayer">
<constructor-arg ref="compactDisc" />
</bean>
id가 cdPlayer인 빈을 생성하고 id가 compactDisc인 빈에 대한 레퍼런스를 생성자의 매개변수로 준다
c네임스페이스의 스키마 선언
xmlns:c="http://www.springframework.org/schema/c"
생성자를 이용한 DI방식
<bean id=McdPlayerM class="soundsystem.CDPlayer"
c :cd-ref="compactDi sc" />
C - C-네임스페이스 접두어
cd - 생성자 인자명
-ref - 빈 레퍼런스 주입
"compactdisc" - 주입용 빈 ID
C-네임스페이스가 constructor-args보다 조금더 간결하다
c :_0-ref="compactDisc"
생성자 인자대신 파라미터인덱스를 넣어줄수도있다 첫번째문자가 숫자는 안되니 _를 표시한다
생성자 인자를 구별하기위해서 인덱스가 더 낫다
c :_-ref="compactDisc"
파라미터가 하나라면 위와같이 _만있어도 된다.
<bean id=McompactDiscM class="
soundsystem.BlankDisc">
〈constructor-arg value="Sgt. Pepper's Lonely Hearts Club Band" />
<constnjctor-arg value="The Beatles" />
</bean>
constructor-arg 는 직접 생성자 인자로 value 속성을 사용하여 값을 줄수도있다
<bean id=ncompactDisc"
class="soundsystem.BlankDisc"
c:_title="Sgt. Pepper's Lonely Hearts Club Band"
c:_artist="The Beatles" />
c-네임스페이스는 파라미터 인덱스를 사용하여 동일 리터럴을 와이어링한다
cbean i d="compactDi sc"
class="soundsystem.BlankDisc"
c:_0="Sgt. Pepperls Lonely Hearts Club Band"
c:_l="The Beatles" />
위와 같이 인덱스번호만으로도 접근할수있다
오로지 1개의 생성자 인자를 가진다면 아래와같이 표현할수있다
<bean id="compactDiscM class="soundsystem.BlankDisc"
c:_="Sgt. Pepper's Lonely Hearts Club Band" />
<constructor-arg>는 c - 네임스페이스가 할 수 없는 컬렉션 와이어링을 할수있다
<bean id="compactDisc" class="soundsystem.BlankDisc">
<constructor-arg value="Sgt. Pepper's Lonely Hearts Club Band" />
<constructorᅳarg value="The Beatles" />
<constructor-arg>
<list>
<value>Sgt. Pepper's Lonely Hearts Club Band</value>
<value>With a Little Help from My Friends</value>
<value>Lucy in the Sky with Diamonds</value>
<value>Getting Better</value>
<value>Fixing a Hole</val니e>
<!-- ...other tracks omitted for brevity... -->
</list>
</constructor-arg>
</bean>
<list>요소를 사용해 값의목록이 생성자 인자로 전달된다
<value>는 값
<ref>는 빈
<bean id="beatlesDiscography" class = "soundsystem. Di scography">
<constructor—arg value="The Beatles" />
<constructor-arg>
<list>
<ref bean="sgtPeppers" />
<ref bean="whiteAlbum" />
<ref bean="hardDaysNight" />
<ref bean=Mrevolver" />
</list>
</constructor-arg>
</bean>
<list> 대신 <set>을 이용할수도있다
list와 set의 차이
1. java.util.list 와 java.util.set
2. java.util.set은 중복값이 삭제되고 순서가 고려되지않음
컬렉션 와이어링에서는 constructor-arg가 c-네임스페이스보다 좋다
public class CDPlayer implements MediaPlayer {
private CompactDi sc compactDisc;
@Autowired
public void setCompactDisc(CompactDisc compactDisc) {
this.compactDisc = compactDisc;
}
위와같이 어떠한 생성자나, 어떠한 하드의존성도 가지지않는다면
<bean id="cdPlayer"
class=Msoundsystem.CDPlayer">
〈property name="compactDisc" ref="compactDisc" />
</bean>
프로퍼티를 이용한 주입이 가능하다
c-네임스페이스에서는 프로퍼티 대안으로 p-네임스페이스를 제공한다
사용전
xmlns:p="http://www.springframework.org/schema/p"
p-네임스페이스를 선언해야한다
〈bean id="cdPlayer"
class=Msoundsystem.CDPlayer"
p :compactDisc-ref="compactDisc" />
위와같이 와이어링 할수있다
p-네임스페이스와 c-네임스페이스는 같은 명명규칙을 따른다
private String title;
private String artist;
private List<String> tracks;
public void setTitie(String title) {
this.title = title;
}
public void setArtist(String artist) {
this.artist = artist;
위와 같이 반드시 와이어링이 필요하지않다면
〈bean id="reallyBlankDi sc"
class=Msoundsystem.BlankDisc" />
간단하게 할수있다
하지만 잘 작동하지않는다
그래서 프로퍼티를 연결해야한다
value를 이용하여 값을 전달할수있다
<bean id="compactDiscM
class=,lsoundsystem. BlankDi scn>
〈property name="title"
value="Sgt. Pepper's Lonely Hearts Club Band" />
〈property name="artist" value="The Beatles" />
<property name="tracksM>
<list>
<value>Sgt. Pepper's Lonely Hearts Club Band</value>
<value>With a Little Help from My Friends</value>
<value>Lucy in the Sky with Diamonds</value>
<value>Getting Better</val니e>
<value>Fi)dng a H이 e</value>
<!-- ...other tracks omitted for brevity... -->
</list>
</property>
</bean>
컬렉션와이어링을 할때는 p-네임스페이스를 사용할수없다
p-네임스페이스는 목록을 지정하는 간편한 방법이없다
util-네임스페이스를 사용해야한다
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
util-네임스페이스 선언
<util:list> 요소를 이용하여 리스트 빈을 만들수있다
<util:list id="trackList">
<value>Sgt. Pepper's Lonely Hearts Club Band</value>
<value>With a Little Help from My Friends</value>
<value>Lucy in the Sky with Diamonds</value>
<value>Getting Better</value>
<value>Fixing a Hole</value>
< !一ᅳ ...other tracks omitted for brevity... __>
</util:list>
<bean id=McompactDisc"
class=Msoundsystem.BlankDisc"
p:title="Sgt. Pepper1s Lonely Hearts Club Band"
p:artist="The Beatles"
p :tracks-ref="trackList" />
리스트빈을 ref로 넣어 와이어링한다.
util-네임스페이스 요소
<util:constant> : 타입에 public static 필드를 참조하고, 빈으로 노출한다.
<util:list> : 값 또는 참조 대상이 java.util.List인 빈을 만든다.
<util:map> : 값 또는 참조 대상이 java.utiLMap인 빈을 만든다.
<util:properties> : java.util.Properties인 빈을 만든다.
<util:property-path> : 빈 프로퍼티를 참조하고(또는 중첩된 프로퍼티),빈으로서 노출한다.
<util:set> : 값 또는 참조 대상이 java.util.Set인 빈을 만든다
자동설정, javaconfig, xmlconfig 무엇이든 혼합해서 사용해도된다
중요한건 오토와이어링은 스프링 컨테이너 내의 모든 빈을 고려한다
명시적 설정은 xml을 하든 java를 하든 개발자에게 맡긴다
각 설정들을 합치는건 추후에
스프링 프레임워크의 핵심은 스프링 컨테이너
명시적인 설정과 관련된 유지보수 비용을 가능한 한 피하기 위해 자동 설정을 강력히 추
천한다. 명시적으로 스프링을 설정한다 하더라도, XML 설정보다 Java 기반의 설정을ᅳ 더 강
력하고 타입세이프하며 리팩토링 가능하므로一더 추천한다
종속객체 주입은 스프링에서 작업의 중요한 부분
---------------------------------------------------------
간단 정리
우선순위
자동설정 > javaConfig > XMLConfig
자동설정 : @ComponentScan, @Autowired
javaConifg : @Configuration, @Bean
xmlConfig : <bean>, <constructor-arg>, <property>, c-네임스페이스, p-네임스페이스, util-네임스페이스
@Configuration은 설정 클래스라는 표시
@Bean은 명시적 설정을 하기위한 어노테이션 몸체는 빈을 생성해주는 코드
<bean> : @Bean과 같이 xml에서 빈을 생성하기위한것 id값을 주지않으면 클래스명과 똑같은 id가 만들어짐
<constructor-arg> : 생성자를 통해 DI를 하는것
<bean id="dvdPlayer" class="com.douzone.springcontainer.videosystem.DVDPlayer">
<constructor-arg ref="digitalVideoDisc"/>
</bean>
dvdPlayer라는 빈이 생성되면서 생성자 매개변수에 digitalVideoDisc를 DI 시켜줌
ref 대신 value로 값도 넣어줄수있음
<constructor-arg value="어쩌구"/> 순서를 구분하려면 name or index를 사용
<constructor-arg name="어쩌구" value="어쩌구"/>
<constructor-arg index=0 value="어쩌구"/>
기본적으로 constructor-arg보다 c-네임스페이스가 가독성이 좋다
컬렉션 와이어링은 c-네임스페이스로 안되기때문에 constructor-arg사용
<list>
<values> </value>
</list>
<list>
<ref bean=""/>
</list>
<bean id="dvdPlayer" class="com.douzone.springcontainer.videosystem.DVDPlayer" c:dvd-ref="digitalVideoDisc"/>
c - c-네임스페이스를 뜻함
dvd - 생성자의 매개변수 명
ref - 빈 레퍼런스
"digitalVideoDisc" - 레퍼런스값
c:_0 인덱스 활용가능
c:_ 인덱스가 1개면 숫자생략
c:title 변수이름도 가능
<property>는 생성자가 아닌 set메소드를 이용
<property name="어쩌구" ref="어쩌구"/>