스프링에서는 빈으로 관리할 수 없는 몇몇 객체들을
빈으로 활용할 수 있게끔 하기 위해 FactoryBean 기능을 제공하고 있습니다.
말 그대로 Bean을 뽑아내는 공장역할을 하는 클래스이죠.
예제코드로 살펴봅시다.
구성은 이러합니다
express 라는 메시지를 담고있는 객체를 FactoryBean에서 뽑아내며
xml은 Spring의 주입에 필요한 설정을 해주는 파일이고
Test는 테스트 클래스입니다.
위에서부터 볼까요
public class express {
String express;
private express(String express) {
this.express = express;
}
public String getExpress() {
return express;
}
public static express newMessage(String express) {
return new express(express);
}
}
먼저 모델클레스인 express 클래스입니다.
getter가 있고 생성자가 있습니다.
호출됬을 때 새로운 인스턴스를 보내주기 위한 static 메소드가 있는 것이 특징이네요.
package proxy2;
import org.springframework.beans.factory.FactoryBean;
public class ExpressFactoryBean implements FactoryBean<express> {
String expressFactory;
public void setExpressFactory(String expressFactory) {
this.expressFactory = expressFactory;
}
@Override
public express getObject() throws Exception {
return express.newMessage(this.expressFactory);
}
@Override public Class<? extends express> getObjectType() {
return express.class;
}
@Override public boolean isSingleton() {
return true;
}
}
ExpressFactoryBean 클래스입니다.
FactoryBean 기능을 구현하기 위해서는 제네릭 클래스인 인터페이스를 구현할 필요가 있습니다.
expressFactory 멤버변수와 setter를 제외하면
밑의 override 메소드 세개는 구현사항입니다.
첫번째는 공장에서 새로운 객체를 뽑아주듯이 get으로 express 객체를 되돌려주는 메소드입니다.
getObjectType 메소드는 구현한 클래스를 반환해주는 메소드입니다.
isSingletone 메소드는 생성되는 객체를 싱글톤(한개의 객체)로만 설정할 것인가를 정하는
설정 메소드입니다. true면 주소값을 계속 재사용하며 false면 매번 재생성하겠죠.
테스트 코드를 보기전에 잠깐 xml 파일을 볼까요
<bean id="express" class="proxy2.ExpressFactoryBean">
<property name="expressFactory" value="express value" />
</bean>
xml 파일에는 FactoryBean 클래스의 expressFactory 변수에 express 라는 문자열을 주입해주고 있습니다.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:proxy2/FactoryBeanTest-context.xml") // FactoryBeanTest-context.xml Auto Referencing
public class FactoryBeanTest {
@Autowired ApplicationContext context;
@Test public void getFromFactoryBean() {
Object express = context.getBean("express");
System.out.println(((express)express).getExpress());
// result = value in FactoryBeanTest-context.xml
}
@Test public void getFactoryBean() throws Exception {
Object factory = context.getBean("&express"); // get bean itself not a object
if(factory.getClass() == ExpressFactoryBean.class)
System.out.println("True");
}
}
테스트 코드를 한번 봅시다.
ApplicationContext 를 주입을 통해 가져오고 있으며
getFromFactoryBean에서는 context 파일을 이용하여 express를 가져옵니다.
여기서 중요한 것은 express는 빈 그자체를 이야기 하는 것이 아닌
express 아이디로 등록된 FactoryBean을 호출하는 것입니다.
호출된 Factory는 자기자신의 멤버변수에 value값을 넣고 그 value 값을 참조하는
getObject 메소드를 이용해 객체를 하나 리턴해줍니다.
그렇다면 빈 그자체를 가져오고 싶을 때는 어떻게 해야할까요?
위의 코드처럼 ID 앞에 &를 붙이면 됩니다.
그러면 빈 그자체를 가져오게 됩니다. 빈 그자체를 가져오는지 테스트하기 위해서
가져온 빈을 getClass() 를 하여 클래스를 만들어보고, Factory 빈 그대로랑 비교하는 코드를 짜봤습니다.
결과는 어떻까요?
알맞게 나옵니다.
FactoryBean 인터페이스를 사용하는 이유는
getObject의 객체 생성 기능에 있습니다. 테스트에서 보신대로 빈 그자체를 리턴하는 것이 아닌
FactoryBean 이 관리하는 객체를 리턴해줬죠.
생성자를 비공개로 해놓고 스태틱 팩토리 메소드로 객체를 생성해 내보내주는 클래스는
일반적인 방법으로는 스프링이 빈으로 관리하기 어렵습니다.
하지만 이러한 방법을 사용하면 스태틱 팩토리 메소드를 사용하는 클래스라도 스프링이 빈 관리하에 둘 수 있게 됩니다.
그림으로 한번 볼까요
직접만들어서 틀릴 수도 있지만
제 이해대로라면 이런 그림이 나올 수 있겠네요
'프로그래밍 > Web-Spring' 카테고리의 다른 글
SpringFramework - ProxyFactoryBean 예제로 알아보기 (0) | 2018.02.19 |
---|---|
JDBC 트랜잭션과 트랜잭션 추상화 (Transaction, Abstraction of Transaction) (0) | 2018.02.10 |
스프링 프레임워크 - Junit Test (0) | 2018.02.04 |