없으면 에러 낼거야 @Required 가 붙은 setter 메소드는 반드시 XML 설정에 의존성 삽입이 정의 되어 있어야 합니다. (@Autowired도 안됩니다.) XML 설정에 명시적인 의존성 삽입이 없다면 런타임 예외가 던져 집니다. 이 애노테이션을 처리하기 위한 후처리기는 다음과 같습니다.
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>
자동으로 묶어 줄게 @Autowried 는 타입에 일치하는 bean을 의존성 삽입 해줍니다. 필드에 사용 할 경우 setter가 존재하지 않아도 됩니다.
@Autowried private Foo foo; 여러개의 인자를 가진 메소드에 사용 할 수 있습니다.
@Autowried public void setUp(Foo foo, Bar bar) { this.foo = foo; this.bar = bar; } @Autowired의 속성인 required의 기본값이 true이기 때문에 발견되는 bean이 없다면 예외가 던져 집니다. 발견 되는 bean이 없더라도 예외가 던져지지 않기를 원하면 required 속성을 fasle로 설정하면 됩니다.
@Autowried(required=false) private Foo foo; 일치하는 타입을 찾기 때문에 발견되는 bean이 여러개인 경우 예외가 던져 집니다. 이를 방지 하기 위해 <bean /> 요소의 추가된 속성인 primary를 설정 합니다. 발견되는 bean이 여러개 일지라도 primary가 설정된 bean이 참조 됩니다.
<bean id="foo" class="example.Foo" primary="true" /> <bean id="foo2" class="example.Foo"/> 이 애노테이션을 처리하기 위한 후처리기는 다음과 같습니다.
<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
정확한 이름을 알려줄게 @Autowired을 사용 할 때 타입으로 bean을 찾기 때문에 여러개의 bean이 발견되면 primary로 해결 했습니다. 하지만 @Qualifier를 이용해 찾으려는 bean의 id를 넘길 수 있습니다.
@Autowried @Qualifier("foo") private Foo foo; 필드에만 사용 가능 하기 때문에 메소드에 적용시 다음과 같이 설정 합니다.
@Autowried public void setUp(@Qualifier("foo") Foo foo, @Qualifier("foo2") Foo foo2) { this.foo = foo; this.foo2 = foo2; } 이 애노테이션을 처리하기 위한 후처리기는 @Autowried의 후처리기와 동일 합니다.
JSR-250 애노테이션 지원 -@Resource -@PostConstruct -@PreDestroy 위 세가지 애노테이션을 사용하기 위해서는 후처리기를 등록 해야 합니다.
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>
@Resource JNDI의 리소스 및 Spring 컨테이너의 bean을 찾아 autowring 합니다. name 속성을 생략 할 경우 해당 필드명으로 찾고 해당 bean이 발견되지 않는다면 타입으로 찾습니다.
필드에 사용 할 경우 setter가 존재하지 않아도 됩니다.
@Resource(name="dataSource") private DataSource dataSource; 한개의 인자를 가진 setter 메소드만 적용 할 수 있습니다.
@Resource(name="dataSource") public void setDataSource(DataSource dataSource) { this.dataSource = dataSource; } 타입으로 찾지 않길 원한다면 다음과 같은 설정을 합니다.
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"> <property name="fallbackToDefaultTypeMatch" value="false"></property> </bean> JNDI 리소스만 참조 하려면 다음과 같은 설정을 합니다.
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"> <property name="alwaysUseJndiLookup" value="true"/> </bean> @PostConstruct 와 @PreDestroy 기존에는 생명 주기를 다루는 방법이 2가지가 있었습니다. 1.InitializingBean, DisposableBean을 구현하는 방법 2.XML 설정파일에서 <bean /> 요소의 init-method, destroy-method 속성 설정
2.5에서 추가된 두 애노테이션은 기존의 방식과 동일한 결과를 가져 옵니다.
@PostConstruct public void init() { ... } @PreDestroy public void preDestroy() { ... } 만약 3가지 방식 모두 사용할 경우 우선순위는 애노테이션->XML설정->인터페이스 구현 입니다.
이거 하나면 OK 위에서 나온 애노테이션을 사용하기 위해서는 3가지의 BeanPostProcessor를 등록해야 했습니다. 하지만 이거 하나면 3개가 모두 등록 됩니다.
<context:annotation-config />
알아서 찾아줄게 위에서 나온 애노테이션으로 XML설정을 줄이더라도 bean 선언은 반드시 해야 했습니다. 하지만 component-scan 을 이용하면 bean선언 조차 생략 할 수 있습니다. component-scan의 대상이 되기 위해서는 스테레오타입 애노테이션을 사용해야 합니다.
4개의 스테레오타입 애노테이션 @Component - 스테레오타입 애노테이션의 조상 입니다. @Controller -Spring MVC에서 컨트롤러로 인식 합니다. @Service -역할부여 없이 스캔 대상이 되는데 비즈니스 클래스에 사용하면 될 것 같습니다. @Repository -DAO에 사용되며 DB Exception을 DataAccessException으로 변환해 줍니다.
간단한 예제 입니다. 테스트에 사용될 2개의 클래스
@Component("bar") public class Bar { }
@Component("foo") public class Foo { @Autowired private Bar bar; public Bar getBar() { return bar; } } 지정된 패키지의 하위패키지까지 재귀적으로 스테레오타입이 있는 클래스를 찾습니다. 필터를 이용해 제외 검색 대상에서 제외 시킬 수 있으며 <context:annotation-config /> 까지 자동으로 등록됩니다.
<context:component-scan base-package="example" /> 테스트는 통과 합니다.
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations={"Beans.xml"}) public class ScanTest { @Autowired private Foo foo; @Test public void fooTest() { assertNotNull(foo.getBar()); } }
@Scope를 함께 사용 하여 Scope를 설정 할 수 있습니다.
@Scope("request") @Component("bar") public class Bar { } singleton인 foo에서 request scope인 bar를 사용 하면 어떻게 될 까요? 역시 scope문제가 발생 합니다.
이 문제를 해결하기 위해 <context:component-scan /> 요소의 scoped-proxy 속성이 존재 합니다. scoped-proxy 속성은 <aop:scoped-poxy/> 요소처럼 WebApplicationContext 에서만 유효하며 "session", "globalSession", "request" 이외의 scope는 무시 됩니다.
아래 3가지 값을 지정 할 수 있습니다. no - 디폴트값, proxy를 생성하지 않습니다. interfaces - JDK Dynamic Proxy를 이용한 Proxy 생성 targetClass - CGLIB를 이용한 Proxy 생성
Bar는 인터페이스 기반이 아니기 때문에 CGLIB를 이용 했습니다.
<context:component-scan base-package="example" scoped-proxy="targetClass"/> 만약 스캔된 bean들 중 @Scope의 값이 "session", "request" 일 때 scoped-proxy 속성 값이 "targetClass", "interfaces" 가 아닐경우 예외가 던져지고 초기화에 실패 합니다.
component-scan을 이용하면 method-lookup도 불가능 하므로 참조되는 bean이 web-scope가 아니고 prototype일 경우의 문제는 해결 할수 없을것 같습니다.
출처 : http://jjaeko.tistory.com/20 |