Spring 에서 객체변수의 인스턴스를 얻어오는 방식은 3가지 방법이 있다.


1. 자동묶기 방식
 - 해당 bean을 컨테이너에 등록시 autowire 지시자를 이용하여 자동묶기를 한다.
   일반적으로 xml파일과 java파일에 아래와 같이 코딩한다.
   해당 java소스에는 반드시 set메소드가 존재해야 한다.
   단, constructor 방식을 사용할 경우에는 생성자가 주입을 담당하기 때문에
   굳이 set메소드가 존재하지 않아도 된다.
  
  1.1. application-context.xml
    ...생략...
    <bean id="sqlMapClientUtil" class="com.local.util.SqlMapClientUtil" autowire="byName">
    </bean>
    ...생략...

  1.2. SqlMapClientUtil.java
    ...생략...
    private SqlMapClient sqlMapClient;
   
    public void setSqlMapClient(SqlMapClient sqlMapClient) {
    this.sqlMapClient = sqlMapClient;
    }
    ...생략...

*   기타 autowire 옵션 

   1) byName : 프로퍼티의 이름과 같은 이름을 갖는 빈 객체를 설정
   2) byType : 프로퍼티의 타입과 같은 타입을 갖는 빈객체를 설정
   3) constructor : 생성자 파라미터 타입과 같은 타입을 갖는 빈객체를 생성자에 전달

   4) autodetect : constructor 방식을 먼저 적용하고, byType 방식을 적용하여 의존 객체를 설정
    

byName를 제외한 방식의 경우 2개 이상의 bean이 검색될 경우 아래와 같은 Exception을 발생시키게 된다.
org.springframework.beans.factory.UnsatisfiedDependencyException                    

이러한 경우 autowire 방식이 아닌 직접지정 방식을 사용해야 한다.
      
타입에 의한 자동와이어링은 타입이 같은 빈이 두 개 이상 존재하는 경우에는 적용되지 못한다.

이름에 의한 자동와이어링은 프로퍼티 이름과 빈의 아이디만 비교하면 되기 때문에 상대적으로 빠르다.

하지만 타입을 비교하는 것은 String으로 된 이름을 비교할 때보다 느리다. 

게다가 자동와이어링은 빈의 모든 프로퍼티에 일괄 적용되어 대상이 아니어도 비교하는 작업이 일어나게 된다.​

 



2. 직접 지정방식

 - 해당 bean을 컨테이너에 등록시 주입할 property를 아래와 같이 지정한

.

  2.1. application-context.xml
    ...생략...
    <bean id="sqlMapClientUtil" class="com.local.util.SqlMapClientUtil">
      <property name="sqlMapClient" ref="sqlMapClient"/>
    </bean>
    ...생략...

  2.2. SqlMapClientUtil.java
    ...생략...
    private SqlMapClient sqlMapClient;
   
    public void setSqlMapClient(SqlMapClient sqlMapClient) {
    this.sqlMapClient = sqlMapClient;
    }
    ...생략...
    
 * 생성자 방식을 사용할 경우 아래와 같이 지정한다.
    <constructor-arg type="java.lang.String" index="0">
        <value>config/service/serviceContext-config.xml</value>
    </constructor-arg>
    인자의 순서와 타입에 주의하도록 한다.
    java 다형성에 의해 생성자가 여러개 정의되어 있는 경우
    인자의 순서와 타입에 의해 생성자가 결정된다.

 


 

 

3. bean으로 등록되지 않은 클래스에서 동적 얻어오는 방식
 - 컨테이너에 등록된 bean에 객체를 주입할때 위와 같은 방식으로 할 수도 있지만
   bean으로 등록하지 않은 유틸클래스에서 해당 객체를 주입할 필요가 있을때가 있다.
   유틸클래스로 사용될 클래스를 모두 bean 컨테이너에 명시하고, autowire를 하던지
   직접 지정하는 것도 한 방법이다.
   하지만 지금부터 소개하는 아래의 방식이 더 깔끔한 방식 임을 알고 있으면 된다.
   아래의 방식은 application-context 자체를 객체로 얻어서 해당 객체에서 관리되는

   bean객체를 얻어올 수 있다는 점을 이용한다.
  
   그렇기 때문에 프록시 역할을 하게될 application-context 객체를 얻어오는 클래스를

   구현하고 최소한 해당 클래스는 bean으로 등록되어 있어야 한다.
  
  3.1. application-context 객체를 얻어올 클래스 구현.
    - ApplicationContextAware 인터페이스를 구현한 클래스여야 한다.
      해당 인터페이스에는 아래와 같은 1개의 메소드가 존재한다.
     
      public abstract interface ApplicationContextAware
      {
        public abstract void setApplicationContext(ApplicationContext paramApplicationContext)
          throws BeansException;
      }
     
      해당 메소드를 구현해서 application-context 객체를 구하면 된다.
      아래는 해당 인터페이스를 구현한 실제 클래스 예이다.
    
      ...생략...
      public class ApplicationContextUtil implements ApplicationContextAware{
    
        private static ApplicationContext context;
       
        public void setApplicationContext(ApplicationContext ac)throws BeansException {
        ApplicationContextUtil.context = ac;
       }
       
       public static ApplicationContext getContext(){
        return ApplicationContextUtil.context;
       }
      ...생략...

  3.2. 컨테이너 등록
    - 위에서 구현한 ApplicationContextUtil 을 bean으로 등록한다.
    
     <bean id="applicationContextUtil" class="com.local.util.ApplicationContextUtil" autowire="byName">
     </bean>
     
  3.3. 유틸 클래스에서 ApplicationContextUtil 을 통해 객체를 주입한다.
    - 아래와 같이 application-context 객체에서 getBean()메소드를 통해 컨테이너에 존재하는 bean 객체를 얻어올 수 있다.
  
      localeResolver = (LocaleResolver)ApplicationContextUtil.getContext().getBean( "localeResolver"); 

 

Posted by mypiece
,