본문 바로가기

Spring/Spring

(SPRING) Dynamically register bean

만약 클라이언트 코드가 스프링 컨테이너에 의해 관리되지 않는 오브젝트를 등록해야 한다면 BeanDefinition을 사용해야 한다.

스프링은 BeanDefinitionRegistry의 메서드를 사용함으로써 BeanDefinition을 등록한다.

https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/support/BeanDefinitionRegistry.html

 

BeanDefinitionRegistry (Spring Framework 5.2.4.RELEASE API)

Interface for registries that hold bean definitions, for example RootBeanDefinition and ChildBeanDefinition instances. Typically implemented by BeanFactories that internally work with the AbstractBeanDefinition hierarchy. This is the only interface in Spri

docs.spring.io


BeanDefinition

BeanDefinition은 빈의 인스턴스에 대한 정보를 담고 있다. 

해당 인터페이스는 setter 메서드를 가지고 있다. scope을 지정하는 setter를 예로 들 수 있다.

void setScope(@Nullable String scope);

GenericBeanDefinition

GenericBeanDefinition은 일반적으로 사용되는 BeanDefinition의 구현체이다.

Bean 클래스, Bean의 특징 생성자의 인자 값 및 property 값을 지정할 수 있다.


GenericBeanDefinition의 사용

public class GenericBeanDefinitionExample {
    public static void main(String[] args) {
        DefaultListableBeanFactory context = new DefaultListableBeanFactory();

        GenericBeanDefinition gbd = new GenericBeanDefinition();
        gbd.setBeanClass(MyBean.class);


        MutablePropertyValues mpv = new MutablePropertyValues();
        mpv.add("date", new Date());

        gbd.setPropertyValues(mpv);
        context.registerBeanDefinition("myBeanName", gbd);

        MyBean bean = context.getBean(MyBean.class);
        bean.doSomething();
        
    }
}

실행결과


다른 Bean을 참조로 주입

public class MyBean {
    private OtherBean otherBean;

    public void setOtherBean(OtherBean otherBean) {
        this.otherBean = otherBean;
    }

    public void doSomething() {
        otherBean.doSomething();
    }

}
public class InjectionOtherBean {

    public static void main(String[] args) {
        DefaultListableBeanFactory context = new DefaultListableBeanFactory();


        /*************************OtherBean Class*************************/
        GenericBeanDefinition gbd = new GenericBeanDefinition();
        gbd.setBeanClass(OtherBean.class);
        context.registerBeanDefinition("other", gbd);
        /*************************OtherBean Class*************************/


        /*************************MyBean Class*************************/
        GenericBeanDefinition gbd2 = new GenericBeanDefinition();
        gbd2.setBeanClass(MyBean.class);

        MutablePropertyValues mpv = new MutablePropertyValues();
        mpv.addPropertyValue("otherBean", context.getBean("other"));

        gbd2.setPropertyValues(mpv);
        context.registerBeanDefinition("myBean", gbd2);
        /*************************MyBean Class*************************/

        MyBean bean = context.getBean(MyBean.class);
        bean.doSomething();
    }
}

실행결과


BeanFactoryPostProcessor의 사용

BeanFactoryPostProcessor는 클라이언트 코드가 bean definition을 커스터마이징 하게끔 할 수 있도록 도와준다.

BeanFactoryPostProcessor의 postProcessBeanFactory 메서드는 모든 definition들이 로드된 이후에 스프링의 startup 프로세스에 의해 호출된다.

하지만 어떠한 빈도 아직 초기화되지는 않은 상태이다.

void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

예시코드

public class MyConfigBean implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

        GenericBeanDefinition gbd = new GenericBeanDefinition();
        gbd.setBeanClass(MyBean.class);
        gbd.getPropertyValues().add("strProp", "my string property");

        ((DefaultListableBeanFactory)beanFactory).registerBeanDefinition("myBeanName", gbd);


    }
}
@Configuration
public class MyConfig {
    @Bean
    MyConfigBean myConfigBean() {
        return new MyConfigBean();
    }
}
public class MyConfigBean implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

        GenericBeanDefinition gbd = new GenericBeanDefinition();
        gbd.setBeanClass(MyBean.class);
        gbd.getPropertyValues().add("strProp", "my string property");

        ((DefaultListableBeanFactory)beanFactory).registerBeanDefinition("myBeanName", gbd);


    }
}

실행결과


Code Link

https://github.com/mike6321/Spring/tree/master/SpringBoot/demoapplicationcontextexercise

 

mike6321/Spring

Contribute to mike6321/Spring development by creating an account on GitHub.

github.com