Whiteship's Note


BeanFactoryAware 테스트

Spring/Chapter 3 : 2007.05.09 15:34


    @Test
    public void testBeanFactoryAware() {
        BeanFactory beanFactory = bean.getBeanFactory();
        assertNotNull(beanFactory);
    }

테스트 코드는 간단합니다. 이전 글에 사용했던 클레스에 BeanFactoryAware 인터페이스를 추가로 구현합니다.

public class BeanLifeCycleTestBean implements BeanFactoryAware, ... {

    ... 생략

    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("setBeanFactory() 실행합니다.");
        this.beanFactory = beanFactory;
    }

    public BeanFactory getBeanFactory() {
        return beanFactory;
    }

}

테스트를 실행하면 테스트가 통과 하는 걸 확인 할 수 있습니다. 그리고 Output 창을 통해 확인 하면 다음과 같습니다.

setBeanName() 실행합니다.
setBeanClassLoader() 실행합니다.
setBeanFactory() 실행합니다.

BeanFactoryAware 사용 예
ObjectFactoryCreatingFactoryBean 사용 예

이 인터페이스를 구현한 클레스들..
AbstractAdvisorAutoProxyCreator, AbstractAutoProxyCreator, AbstractBeanFactoryBasedTargetSource, AbstractBeanFactoryBasedTargetSourceCreator, AbstractBeanFactoryPointcutAdvisor, AbstractFactoryBean, AbstractPoolingTargetSource, AbstractPrototypeBasedTargetSource, AnnotationAwareAspectJAutoProxyCreator, AspectJAwareAdvisorAutoProxyCreator, BeanConfigurerSupport, BeanFactoryDataSourceLookup, BeanNameAutoProxyCreator, BeanReferenceFactoryBean, CommonsPoolTargetSource, DefaultAdvisorAutoProxyCreator, DefaultBeanFactoryPointcutAdvisor, HibernateAccessor, HibernateAccessor, HibernateInterceptor, HibernateInterceptor, HibernateTemplate, HibernateTemplate, HibernateTransactionManager, HibernateTransactionManager, LazyInitTargetSource, LazyInitTargetSourceCreator, ListFactoryBean, MapFactoryBean, MBeanExporter, MethodInvokingFactoryBean, MethodInvokingJobDetailFactoryBean, MethodLocatingFactoryBean, ObjectFactoryCreatingFactoryBean, OpenSessionInViewInterceptor, OpenSessionInViewInterceptor, PersistenceAnnotationBeanPostProcessor, PersistenceExceptionTranslationInterceptor, PersistenceExceptionTranslationPostProcessor, PreferencesPlaceholderConfigurer, PropertyPathFactoryBean, PropertyPlaceholderConfigurer, PrototypeTargetSource, ProxyFactoryBean, QuickTargetSourceCreator, ScopedProxyFactoryBean, ScriptFactoryPostProcessor, ServiceLocatorFactoryBean, ServletContextPropertyPlaceholderConfigurer, SetFactoryBean, SimpleBeanFactoryAwareAspectInstanceFactory, SimpleBeanTargetSource, ThreadLocalTargetSource, TransactionProxyFactoryBean
엄청나게 많습니다.

주로 다른 Bean을 lock up 할 수 있는 factory사 필요할 때 사용합니다. 특정 객체만을 뽑아낼 factory가 필요하다면 FactoryBean을 사용하면 되는데 이때도 이 인터페이스를 사용할 수 있기 때문에 위의 구현체들의 반정도는 XXXFactoryBean 입니다.

FactroyBean을 사용하는 이유는 '만들 수 없는 것'을 FactoryBean으로 만들기 이 글에서 확인할 수 있으며 주로 객체 생성에 복잡한 설정과 로직이 필요한 경우에 사용하며 따라서 다른 프레임워크와 연동하는 객체가 필요한 경우에 자주 사용하며 위의 구현체 중에 또 절반 정도는 그러한 구현체에 해당합니다.


top

Write a comment.


BeanFactoryAware 사용 예

Spring/Chapter 3 : 2007.03.12 11:21


Member 가 영화표를 구매 하려고 합니다. 매번 구매하는 영화표는 다른 객체여야 겠죠? Ticket은 prototype으로 하고 Member는 singleton으로 하겠습니다.

티켓 두 개는 달라야 합니다.
   @Test public void singlePrototype(){
       ...
       assertNotSame(ticket1, ticket2);
   }

티켓 두 개는 하나의 멤버가 산거죠.
   @Test public void singlePrototype(){
       ...
       Ticket ticket1 = Member.getTicket();
       Ticket ticket2 = Member.getTicket();
       assertNotSame(ticket1, ticket2);
   }

멤버는 keesun12라는 bean이라고 하면 다음과 같이 테스트 케이스가 만들어집니다.
   @Test public void singlePrototype(){
       Member keesun12 = getMember("keesun12");
       Ticket ticket1 = keesun12.getTicket();
       Ticket ticket2 = keesun12.getTicket();
       assertNotSame(ticket1, ticket2);
   }

그리고 구현을 아래 처럼 합니다.
class Member {
...
    Ticket ticket;
...
    public Ticket getTicket() {
        return ticket;
    }

    public void setTicket(Ticket ticket) {
        this.ticket = ticket;
    }
}

그리고 설정은 아래 처럼 Member는 singleton으로.. TIcket은 prototype으로 했습니다.
    <!-- BeanFactoryAware -->
    <bean id="keesun12" class="beanConfiguration.Member">
        <property name="ticket" ref="ticket1" />
    </bean>

    <bean id="ticket1" class="beanConfiguration.Ticket" scope="prototype"/>

테스트는 당연히 통과 하지 않습니다. 두개의 티켓 객체가 같기 때문이죠. 이걸 해결하려고 다음과 같이 구현한 부분을 수정합니다.
1. ticket 필드를 삭제합니다. setTicket 메소드도 삭제합니다. getTicket은 남겨둬야겠죠.
2. Member 클래스가 BeanFactoryAware 인터페이스를 구현합니다.
3. BeanFactory 타입의 변수 추가합니다.
그럼 다음 처럼 됩니다.
class Member implements BeanFactoryAware {
...
    BeanFactory ticketFactory;
...
    Ticket getTicket(){
       return (Ticket)ticketFactory.getBean("ticket");
    }
...
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }
}

설정부분에서 더이상 ticket을 DI를 이용하지 않으므로 더 단순해 졌네요.
    <bean id="keesun12" class="beanConfiguration.Member" />

    <bean id="ticket" class="beanConfiguration.Ticket" scope="prototype" />

이제 테스트는 통과 합니다.

'Spring > Chapter 3' 카테고리의 다른 글

BeanFactoryPostProcessor 사용 예  (0) 2007.03.13
BeanPostProcessor 사용 예  (0) 2007.03.13
3.7. Container extension points  (0) 2007.03.13
3.6. Bean definition inheritance  (0) 2007.03.12
ObjectFactoryCreatingFactoryBean 사용 예  (0) 2007.03.12
BeanFactoryAware 사용 예  (1) 2007.03.12
BeanFactoryAware  (0) 2007.03.12
init-method & destroy-method  (0) 2007.03.10
InitializingBean & DisposableBean  (0) 2007.03.10
Bean's Life Cycle  (0) 2007.03.10
The IoC container  (0) 2007.03.10
top

  1. 마을5 2011.11.07 13:49 PERM. MOD/DEL REPLY

    <aop:scoped-proxy />를 사용해 보세요.

Write a comment.


BeanFactoryAware

Spring/Chapter 3 : 2007.03.12 10:51


어떤 클래스에서 bean을 꺼낼(look up) 수 있는 factory가 필요하다면 BeanFactoryAware 인터페이스를 구현하거나.. 다른 방법도 있습니다.

 void setBeanFactory(BeanFactory beanFactory)

구현해야 할 메소드는 요고 하나 있습니다.

Reference에서는 이 인터페이스를 사용하는 것은 IoC답지 않고[각주:1] 소스코드가 Spring framwork에 종속성이 생기기 때문에 다른 방법을 사용한 예제를 보여 주고 있습니다.[각주:2]

3.3 맨 끝에서 Method Injection에 관한 부분에서 이게 필요한 상황이 나왔었습니다. 예를 들어 A가 singleton이고 B가 prototyp인데 A가 B를 가지고 있으면.. B는 prototype인데도 하나의 A가 한번만 만들어 지니까 A가 다른 bean에 참조 되거나 look up 됐을 때 마다 B가 새로 생기는게 아니라 기본에 만들어져있던 A를 계속 쓰게 되는 상황을.. BeanFactoryAware 인터페이스를 사용해서 해결할 수 있다고 했었습니다. 물론 그것 보다 더 좋은 방법은 Method Injection인데 아직 공부를 안해서 모르겠네요.

BeanFactoryAware 사용 예
ObjectFactoryCreatingFactoryBean 사용 예
  1. Dependency Lookup은 IoC답지 않은 것으로 생각하는 것 갔습니다. 어떤 책에서는 IoC 중에 DL과 DI가 있고 DI중에 Setter Injection과 Costructor Injection, Method Injection이 있다고 써놨던 것 같은데.. 햇갈리네요. [본문으로]
  2. ObjectFactoryCreatingFactoryBean 이것을 사용하여 설정 파일에서 DI를 사용하는 방법입니다. [본문으로]

'Spring > Chapter 3' 카테고리의 다른 글

BeanPostProcessor 사용 예  (0) 2007.03.13
3.7. Container extension points  (0) 2007.03.13
3.6. Bean definition inheritance  (0) 2007.03.12
ObjectFactoryCreatingFactoryBean 사용 예  (0) 2007.03.12
BeanFactoryAware 사용 예  (1) 2007.03.12
BeanFactoryAware  (0) 2007.03.12
init-method & destroy-method  (0) 2007.03.10
InitializingBean & DisposableBean  (0) 2007.03.10
Bean's Life Cycle  (0) 2007.03.10
The IoC container  (0) 2007.03.10
3.5. Customizing the nature of a bean  (0) 2007.03.10
top

Write a comment.