ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Camel][Spring] 팩토리 방식의 Spring Bean 설정
    Spring/개념 정리 2020. 4. 22. 18:02

    팩토리 방식의 Spring Bean 설정

    일반적으로 객체를 생성하기 위해 사용하는 방법으로는 new 키워드를 사용하는 방법이 있습니다.

     

     하지만 객체를 생성하기 위해 static 메소드를 사용해야하는 경우가 발생할 수 있습니다. 그리고 new 키워드로 객체를 생성한 후 복잡한 과정의 초기화를 진행하기도 합니다. XML을 사용해 DI 설정을 하면 앞서 언급한 두가지의 경우에서 문제가 생길 수 있습니다. 

     

     그래서 스프링에서는 위와 같은 경우를 해결하기 위해 또 다른 객체 생성방식을 제공하고 있습니다. 객체생성에 사용되는 static 메소드 지정FactoryBean 인터페이스를 이용한 객체 생성 처리가 바로 그것입니다. 

     

    1. 객체 생성을 위한 Static 메소드 지정

     스프링은 기본적으로 객체를 생성할 때 생성자를 사용합니다. 하지만 static 메소드를 사용해서 객체를 생성해야 할 경우가 생길 수 있는데, 이 경우 <bean> 태그에 factory-method 속성을 추가해줌으로써 스프링은 생성자를 사용하는 것이 아닌 static 메소드를 사용해서 빈 객체를 생성할 수 있습니다. 사용방법은 아래와 같습니다. 

    public abstract class AnimalFactory {
    	// 객체를 구하려면 instance 메소드를 사용해야 한다.
    	public static AnimalFactory instance(Properties props) {  
        		return new DefaultAnimalFactory(props);
        	}
        
        	protected AnimalFactory() {
        	}
        
          	public abstract Animal create();
     
    }
    AnimalFactory fac = AnimalFactory.instance(props);
    <bean id="factory" class="com.ex.AnimalFactory" 
    		factory-method="instance">
            <constructor-arg> <!-- static 메소드의 파라미터로 전달된다. -->
            	<props>
                		<prop key="server">123.12.12.123</prop>
                	</props>
            </constructor-arg>
    	
    </bean>

     

    2. FactoryBean 인터페이스를 이용한 객체 생성 처리

     개발과정에서 객체를 생성하고 초기화하는 과정이 일반적인 객체 생성 과정과 다소 차이가 있는 경우가 발생할 수 있습니다. 아래의 코드를 먼저 확인하겠습니다. 

    AnimalFactoryBuilder builder = new AnimalFactoryBuilder();
    builder.server("123.12.12.123")
    		.port(8080)
            .contentType(type==null ? "json" : type)
            .encoding("utf-8");
    AnimalFactory animalFactory = builder.build();
    animalFactory.init();

    위의 코드에서 스프링 빈으로 정의하고 싶은 타입은 AnimalFactory입니다. 이때 XML을 사용해서 AnimalFactory 타입의 빈을 정의하기에는 AnimalFactory객체를 생성하는 과정이 다소 복잡해집니다.

     

     하지만 이런 경우 사용하는 것이 바로 FactoryBean 인터페이스입니다. 

     

    FactoryBean 인터페이스는 아래와 같은 형태로 정의되어 있습니다. 

    package org.springframework.beans.factory;
    
    public interface FactoryBean<T> {
    	T getObject throws Exception; // 실제 스프링 빈으로 사용될 객체를 반환.
          	Class<?> getObjectType(); // 스프링 빈으로 사용될 객체릐 타입을 반환.
        	boolean isSingleton();	// getObject 메소드가 매번 동일한 객체를 반환하면 true를 반환,
            			// getObject 메소드가 매번 새로운 객체를 반환하면 false를 반환.
    }

    <bean> 태그에서 지정한 클래스나 @Bean 어노테이션이 적용된 메소드가 생성하는 객체가 FactoryBean 인터헤이스를 구현한 경우, 스프링은 getOject 메소드가 반환하는 객체를 실제 빈 객체로 사용하게됩니다. 

     즉, 이것은 FactoryBean 인터페이스를 적절히 구현하면 생성자나 static 메소드가 아닌 다른 방법으로 생성되는 객체를 스프링 빈으로 사용할수 있게되는 것입니다. 

     

    FactortBean의 사용방법은 아래와 같습니다. 

    package org.springframework.beans.factory.FactoryBean;
    
    // AnimalFactoryBean 클래스가 생성할 스프링 빈 객체의 타입은 AnimalFactory이기 때문에 
    // FactoryBean의 제네릭 타입 파라미터로 AnimalFactory를 사용한다.
    public class AnimalFactoryBean 
    			implements FactoryBean<AnimalFactory>{ 
    	private AnimalFactory animalFactory;
        
        	private String server;
        	private int port;
        	private String contentType;
        	private String encoding = "utf8";
        
        	public void setServer( String server) {
        		this.server = server;
        	}
        
        	public void setPort( int port) {
        		this.port = port;
        	}
            
    	public void setContentType( String contentType) {
        		this.contentType = contentType;
        	}
            
        	public void setEncoding( String encoding ) {
        		this.encoding = encoding;
        	}
            
            @Override
            public AnimalFactory getObject() throws Exception {
            	
                	if(this.animalFactory != null )
                		return this.animalFactory;
                
                	AnimalFactoryBuilder builder = new AnimalFactoryBuilder();
    		builder.server(server)
    			.port(port)
            		.contentType(contentType)
            		.encoding(encoding);
    		AnimalFactory animalFactory = builder.build();
    		animalFactory.init();
            
                	//매번 동일한 객체를 반환하기 위해 생성한 객체를 animalFactory 필드에 보관한다.
                    this.animalFactory = animalFactory;
                	return this.animalFactory;
            }
            
            @Override
            public Class<?> getObjectType() {
            	return AnimalFactory.class;
            }
            
            @Override
            public boolean isSingleton() {
            	return true;
            }
            
    }
    <bean id="animalFactory" class="com.ex.AnimalFactoryBean">
            <property name="server" value="123.12.12.123"/>
            <property name="port" value="8080"/>
            <property name="contentType" value="json"/>
    </bean>

     

    댓글

Camel`s Tistory.