ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Spring Core] 공식문서 공부 - 1.3.2 Instantiating Bean
    JAVA/Spring 2022. 8. 22. 10:37

    https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-factory-class

     

    Core Technologies

    In the preceding scenario, using @Autowired works well and provides the desired modularity, but determining exactly where the autowired bean definitions are declared is still somewhat ambiguous. For example, as a developer looking at ServiceConfig, how do

    docs.spring.io

    이번 글에서는 Bean을 인스턴스화 하는 방법들에 대해서 다룬다.

     

    Bean 정의는 하나 이상의 객체를 생성하는데 필요한 필수적인 레시피이다.

    IoC 컨테이너는 요청에 따라서 해당 named Bean에 대한 레시피를 찾고, 

    실제 객체 생성을 위한 Bean 정의들로 구성된 구성 메타데이터(configuration metadata)를 사용한다.

     

    XMl 기반 구성 메타데이터를 사용하는경우에는

    <bean /> 요소 내의 class 속성에 인스턴스화 되어야할 객체의 타입(또는 클래스)을 명시해주어야 한다.

    이 class 속성은 무조건 채워야한다.

     

    다음으로, class 속성은 크게 2가지 방식으로 다룰 수 있다.

    • new 연산자과 비슷하게 Ioc 컨테이너가 해당 Bean의 생성자를 호출함으로써 직접적으로 해당 Bean을 생성하는 경우에, class 속성에 생성될 bean class를 명시하는 방식. 일반적으로 이 방식을 사용한다.
    • class 속성에 객체 생성을 위한 정적 팩토리 메소드를 포함한 실제 클래스를 명시하는 방식. IoC 컨테이너가 Bean을 생성하기 위해 클래스 내의 정적 팩토리 메소드를 사용하는 것은 일반적이지 않다.

     


    Instantiation with a Constructor

    바로 위에서 class 속성을 다루는 2가지 방식을 소개했는데, 먼저 첫 번째 방식에 대해서 설명한다.

     

    생성자 방식으로 Bean을 생성할 경우 우리가 일반적으로 작성하는 클래스들은 거의 모두 Spring에서 쓸 수 있다고 보면 된다. class 속성에 bean class를 명시하는 것만으로도 충분하다. 그러나 특정 Bean에 어떤 타입의 IoC를 사용하는지에 따라서 기본 생성자가 필요한 경우도 있다.

     

    Spring IoC 컨테이너는 사용자가 관리하기를 원하는 어떤 클래스든 관리할 수 있다.

    예를 들어, true JavaBeans, actual JavaBeans, Bean 스타일이 아닌 클래스 등 여러가지를 관리할 수 있다.

     

    XML 기반 구성 메타데이터에서는 아래와 같이 bean class를 명시할 수 있다.

    <bean id="exampleBean" class="examples.ExampleBean"/>
    
    <bean name="anotherExample" class="examples.ExampleBeanTwo"/>

    생성자로 인수를 전달하는 매커니즘과 객체가 생성된 이후 객체 인스턴스 프로퍼티들을 설정하는 매커니즘은 Injecting Dependency 부분에서 다룬다.

     


    Instatiation with Static Factory Method

    다음으로 두 번째 방식에 대해 설명한다.

     

    정적 팩토리 메소드를 통해 생성되는 Bean을 정의하려면 class 속성뿐만 아니라 factory-method 속성 또한 채워야한다.

    먼저 정적 팩토리 메소드를 포함하는 클래스를 class 속성에 명시하고,

    해당 클래스의 정적 팩토리 메소드 이름을 factory-method 속성에 명시하면 된다.

     

    이렇게 정적 팩토리 메소드를 통해 생성된 객체는 마치 생성자를 통해 생성된 객체처럼 다룰 수 있다.

     

    XML 기반 구성 메타데이터에서 정적 팩토리 메서드를 통해 생성되는 Bean의 정의는 아래와 같이 작성할 수 있다.

    <bean id="clientService"
        class="examples.ClientService"
        factory-method="createInstance"/>

    아래는 위에 작성한 Bean 정의대로 작동하는 자바 클래스의 코드이다.

    package example;
    
    public class ClientService {
        private static ClientService clientService = new ClientService();
        private ClientService() {}
    
        public static ClientService createInstance() {
            return clientService;
        }
    }

     


    Instantiation by Using an Instance Factory Method

    동적 팩토리 메소드를 통해 새로운 Bean을 생성하는 방법은 정적 팩토리 메소드 방법과 유사하다.

    IoC 컨테이너가 이미 컨테이너 내에 존재하는 Bean의 동적 팩토리 메소드를 호출하여 새로운 Bean을 생성하는 방식이다.

     

    이 방법을 사용하기 위해서는 XML 기반 구성 메타데이터에 Bean 정의를 할 때, class 속성에 아무런 값도 넣지 않고 비워둬야 한다. 그 대신 factory-bean 속성에다가 인스턴스 팩토리 메소드를 가지고 있는 Bean의 이름을 명시하면된다.

    factory-method 속성에는 정적 팩토리 메소드 방법과 똑같이 해당 팩토리 메소드의 이름을 명시하면 된다.

     

    아래는 인스턴스 팩토리 메소드를 통해 새로운 Bean을 생성하는 예시이다.

    <!-- 인스턴스 팩토리 메서드 createInstance()를 포함한 factory bean -->
    <bean id="serviceLocator" class="examples.DefaultServiceLocator">
        <!-- inject any dependencies required by this locator bean -->
    </bean>
    
    <!-- 인스턴스 팩토리 메서드를 통해 생성될 Bean -->
    <bean id="clientService"
    	<!--class 속성에는 아무런 값도 넣지 않았음-->
        factory-bean="serviceLocator"
        factory-method="createClientServiceInstance"/>
    public class DefaultServiceLocator {
    
        private static ClientService clientService = new ClientServiceImpl();
    
        public ClientService createClientServiceInstance() {
            return clientService;
        }
    }

     

    만약 팩토리 클래스가 2개 이상의 팩토리 메서드를 가지고 있는 경우 해당 메소드들을 통해 생성되는 객체를 각각 Bean으로 등록할 수 있다.

    <bean id="serviceLocator" class="examples.DefaultServiceLocator">
        <!-- inject any dependencies required by this locator bean -->
    </bean>
    
    
    <!-- 같은 serviceLocator Bean 내에 존재하는 서로다른 팩토리 메소드들 -->  
    <bean id="clientService"
        factory-bean="serviceLocator"
        factory-method="createClientServiceInstance"/>
    
    <bean id="accountService"
        factory-bean="serviceLocator"
        factory-method="createAccountServiceInstance"/>
    public class DefaultServiceLocator {
    
        private static ClientService clientService = new ClientServiceImpl();
    
        private static AccountService accountService = new AccountServiceImpl();
    
        public ClientService createClientServiceInstance() {
            return clientService;
        }
    
        public AccountService createAccountServiceInstance() {
            return accountService;
        }
    }

     

    공식문서를 읽을 때 factory bean과 FactoryBean은 다르므로 주의하자.

    factory bean: Spring IoC 컨테이너 내에 존재하며, 정적 또는 인스턴스 팩토리 메소드를 통해 새로운 객체를 생성하는 Bean.
    FactoryBean: FactoryBean 인터페이스를 구현한 클래스.

    전자는 소문자로, 후자는 대문자로 쓰는 듯 하다.

     


    Determining a Bean's Runtime Type

    특정한 Bean의 런타임 타입을 알아내고 싶으면 BeanFactory 인터페이스의 getType() 메소드를 사용하면 된다.

    이 getType() 메소드는 해당 Bean에 대해 getBean() 메소드가 리턴하는 객체의 타입을 리턴한다.

    댓글

Designed by Tistory.