[Spring] Custom classloader 를 적용해 Bean 생성하기

우선 내부에서 Custom classloader 로 객체를 생성하는 클래스를 생성한다.
이 때 BeanFactory 클래스나 인터페이스를 상속 할 필요는 없다.

CustomBeanFacotry class

public class CustomBeanFactory {

	public Object getBean(String name, Object... constArgs) {
		CustomClassLoader loader = new CustomClassLoader();
		try {
			Class<?> clazz = loader.findClass(name);
			Class<?>[] constClasses = new Class<?>[constArgs.length];
			for (int i = 0; i < constArgs.length; i++) {
				constClasses[i] = constArgs[i].getClass();
			}

			Constructor<?> constructor = clazz.getConstructor(constClasses);
			Object returnVal = constructor.newInstance(constArgs);
			return returnVal;
		} catch (Exception e) {
			return null;
		}
	}
}

BeanFactory의 역할을 수행하기 때문에 CustomBeanFactory 와 getBean으로 명명했지만 원하는 클래스명, 메소드 명으로 변경해도 무관하다.

다양한 클래스에 재사용될 수 있게끔 Object[] 형태로 생성자 argument 를 받아와 객체를 생성하도록 함.

단, 호출하려는 생성자 파라미터로 인터페이스가 있으면 getClass로 클래스를 가져올 수 없다. getInterface로 인터페이스를 조회할 수 있으나, 다수의 인터페이스를 상속하고 있을 경우 어느 인터페이스를 선택해야할 지 CustomBeanFactory는 알 수 없음.

인터페이스를 파라미터로 갖는 생성자를 사용하고 싶을 경우, Spring Framework 에서 bean 인스턴스 생성시 constructor 목록에서 적절한 constructor 를 찾는 로직을 사용하여 구현할 수 있다.
org.springframework.beans.factory.support.ConstructorResolver

bean 등록

<bean id="customBeanFactory" class="com.test.CustomBeanFactory" />

<bean id="customLoadedClass" factory-bean="customBeanFactory" factory-method="getBean">
	<constructor-arg index="0" value="CustomLoadedClass" /> <!-- class name -->
	<constructor-arg index="1"> <!-- constructor arguments -->
		<list>
			<value>const-arg1</value>
			<value>const-arg2</value>
			<ref bean="constArgumentBeanRef" /> <!-- bean ref 로 객체를 넘길 수도 있음 -->
		</list>
	</constructor-arg>
</bean>

좋은 웹페이지 즐겨찾기