티스토리 뷰

반응형

Bean을 생성하는 3가지 방법

1. @Component 애노테이션으로 생성하기

스프링부트에서 가장 보편적으로 사용하는 방법으로 @Component 애노테이션을 사용할 수 있다. 개발자가 직접 작성한 Class에만 사용할 수 있다.

@Component
public class MyComponent1 implements InitializingBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("MyComponent1.afterPropertiesSet");
    }
}

2. @Bean 애노테이션으로 생성하기

주로 외부 라이브러리의 객체들을 Bean으로 만들때 사용하거나, 같은 타입의 빈을 여러개 생성하고 싶을 때 사용한다.

@Configuration
public class MyConfiguration {
    @Bean
    public MyComponent2 myComponent2() {
        return new MyComponent2();
    }
}
public class MyComponent2 implements InitializingBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("MyComponent2.afterPropertiesSet");
    }
}

3. BeanFactory 사용하기

자주 사용되는 방법은 아니지만 Bean 생성을 동적으로 만들고 싶을때 고려하는 방법이다.

@Configuration
public class MyConfiguration {
    public MyConfiguration(GenericApplicationContext applicationContext) {
        MyComponent3 myComponent3 = new MyComponent3();
        ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
        beanFactory.registerSingleton("myComponent3", myComponent3);
    }
}
public class MyComponent3 implements InitializingBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("MyComponent3.afterPropertiesSet");
    }
}

 

BeanFactory로 Bean 생성시에 주의 할 점

오늘 포스팅은 Bean 생성 방법을 복습하기 위해서 쓴것이 아니다.

예제 코드들을 보면 알겠지만 Class 들이 모두 InitializingBean 인터페이스를 구현하고 있고, 이는 스프링 프레임워크에서 제공하는 인터페이스다.  구현해야 하는 메서드는 Bean이 생성된 이후에 실행되어야 하는 코드들을 선언하는 초기화 메서드다. 

 

애플리케이션을 빌드하여서 InitializingBean의 afterPropertiesSet() 메서드가 정상적으로 호출되는지 확인하면 다음과 같다.

MyComponent1, MyComponent2의 메서드는 정상적으로 호출되었지만, MyComponent3의 메서드는 호출되지 않았다. 1,2번 방식으로 Bean을 선언할 경우 스프링 컨테이너가 라이프사이클을 완벽히 관리하여 해당 메서드를 호출(invoke)하지만 BeanFactory를 이용하는 경우는 호출되지 않았다.

 

3번 방식에 경우 아래와 같이 직접 호출을 해줘야 한다.

beanFactory.initializeBean(myComponent3, "myComponent3");

 

문제는 InitializingBean을 구현한 (외부 라이브러리) 객체를 BeanFactory로 만들때 발생한다. 외부 라이브러리 객체는 스프링 컨테이너가 완전히 관리해 줄 것을 기대하고 해당 메서드에 기능을 추가하였는데, 개발자가 임의로 BeanFactory를 사용하여 만든경우 의도한대로 초기화가 되지 않는 것이다. 

 

스프링에서 자주 쓰는 레디스 클라이언트 LettuceConnectionFactory를 살펴보면 InitializingBean을 구현하고 있다. 만약 LettuceConnectionFactory를 BeanFactory로 생성 후 초기화하지 않는다면, 의도한대로 동작하지 않게 된다.

 

이와 유사한 메서드로 DisposableBean 인터페이스가 있는데, 이는 Bean이 파괴(Destory)될 때 실행되어야 하는 코드들을 선언하는 것이다. 일반적인 경우라면 대개 싱글톤으로 생성하여 관련이 없겠지만, 혹여나 Bean을 Destory해야 한다면 해당 메서드의 라이플사이클도 염두를 해야한다.

 

한줄요약

BeanFactory로 Bean을 생성시에 해당 객체가 InitializingBean 인터페이스를 구현하고 있다면 생성 후 반드시 초기화 해주자!

반응형
댓글