복붙노트

[SPRING] Spring Web App Context에 프로그램 적으로 Bean 추가하기

SPRING

Spring Web App Context에 프로그램 적으로 Bean 추가하기

플러그인 아키텍처로 인해 웹 애플리케이션에 프로그래밍 방식으로 빈을 추가하려고합니다. @Component 주석을 통해 생성 된 Spring 빈을 가지고 있고 ApplicationContextAware 인터페이스를 구현하고있다.

내 무시 기능은 다음과 같습니다.

@Override
public void setApplicationContext(ApplicationContext applicationContext)
        throws BeansException {

    // this fails
    this.applicationContext = (GenericWebApplicationContext) applicationContext;
 }

기본적으로, 나는 setApplicationContext에 주어진 applicationContext 객체에 bean을 추가하는 방법을 알 수 없다. 아무도 내가이 잘못된 방향으로 어떻게 갈 것인지 말해 줄 수 있습니까?

좋아,이게 내가 해결책으로 끝난 것이다.

@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry bdr)
        throws BeansException {
    BeanDefinition definition = new RootBeanDefinition(
            <My Class>.class);

    bdr.registerBeanDefinition("<my id>", definition);
}

해결법

  1. ==============================

    1.Spring 3.0에서는 빈이 BeanDefinitionRegistryPostProcessor를 구현하고 BeanDefinitionRegistry를 통해 새로운 빈을 추가 할 수있다.

    Spring 3.0에서는 빈이 BeanDefinitionRegistryPostProcessor를 구현하고 BeanDefinitionRegistry를 통해 새로운 빈을 추가 할 수있다.

    이전 버전의 Spring에서는 BeanFactoryPostProcessor에서 동일한 작업을 수행 할 수 있습니다 (BeanFactory를 BeanDefinitionRegistry로 캐스팅해야하지만 실패 할 수 있음).

  2. ==============================

    2.다음은 간단한 코드입니다.

    다음은 간단한 코드입니다.

    ConfigurableListableBeanFactory beanFactory = ((ConfigurableApplicationContext) applicationContext).getBeanFactory();
    beanFactory.registerSingleton(bean.getClass().getCanonicalName(), bean);
    
  3. ==============================

    3.GenericWebApplicationContext 유형으로 왜 필요합니까? 아마 당신은 어떤 ApplicationContext 타입으로도 작업 할 수 있다고 생각합니다.

    GenericWebApplicationContext 유형으로 왜 필요합니까? 아마 당신은 어떤 ApplicationContext 타입으로도 작업 할 수 있다고 생각합니다.

    일반적으로 (setter 메소드 외에도) init 메소드를 사용합니다.

    @PostConstruct
    public void init(){
        AutowireCapableBeanFactory bf = this.applicationContext
            .getAutowireCapableBeanFactory();
        // wire stuff here
    }
    

    그리고 다음 중 하나를 사용하여 콩을 연결합니다.

    AutowireCapableBeanFactory.autowire (Class, int mode, boolean dependencyInject)

    또는

    AutowireCapableBeanFactory.initializeBean (Objectbeanbean, String beanName)

  4. ==============================

    4.실제로 AbstractApplicationContext에서 파생 된 AnnotationConfigApplicationContext는 비어있는 postProcessBeanFactory 메소드가 남아 있습니다.

    실제로 AbstractApplicationContext에서 파생 된 AnnotationConfigApplicationContext는 비어있는 postProcessBeanFactory 메소드가 남아 있습니다.

    /**
     * Modify the application context's internal bean factory after its standard
     * initialization. All bean definitions will have been loaded, but no beans
     * will have been instantiated yet. This allows for registering special
     * BeanPostProcessors etc in certain ApplicationContext implementations.
     * @param beanFactory the bean factory used by the application context
     */
    protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    }
    

    이것을 활용하려면 다음과 같이 보이는 AnnotationConfigApplicationContextProvider 클래스를 생성하십시오 (Vertx 인스턴스 예제에서 제공하는 대신 MyClass를 사용할 수 있습니다).

    public class CustomAnnotationApplicationContextProvider {
    private final Vertx vertx;
    
    public CustomAnnotationApplicationContextProvider(Vertx vertx) {
        this.vertx = vertx;
    }
    
    /**
     * Register all beans to spring bean factory
     *
     * @param beanFactory, spring bean factory to register your instances
     */
    private void configureBeans(ConfigurableListableBeanFactory beanFactory) {
        beanFactory.registerSingleton("vertx", vertx);
    }
    
    /**
     * Proxy method to create {@link AnnotationConfigApplicationContext} instance with no params
     *
     * @return {@link AnnotationConfigApplicationContext} instance
     */
    public AnnotationConfigApplicationContext get() {
        return new AnnotationConfigApplicationContext() {
    
            @Override
            protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
                super.postProcessBeanFactory(beanFactory);
                configureBeans(beanFactory);
            }
        };
    }
    
    /**
     * Proxy method to call {@link AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(DefaultListableBeanFactory)} with our logic
     *
     * @param beanFactory bean factory for spring
     * @return
     * @see AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(DefaultListableBeanFactory)
     */
    public AnnotationConfigApplicationContext get(DefaultListableBeanFactory beanFactory) {
        return new AnnotationConfigApplicationContext(beanFactory) {
    
            @Override
            protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
                super.postProcessBeanFactory(beanFactory);
                configureBeans(beanFactory);
            }
        };
    }
    
    /**
     * Proxy method to call {@link AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(Class[])} with our logic
     *
     * @param annotatedClasses, set of annotated classes for spring
     * @return
     * @see AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(Class[])
     */
    public AnnotationConfigApplicationContext get(Class<?>... annotatedClasses) {
        return new AnnotationConfigApplicationContext(annotatedClasses) {
    
            @Override
            protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
                super.postProcessBeanFactory(beanFactory);
                configureBeans(beanFactory);
            }
        };
    }
    
    /**
     * proxy method to call {@link AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(String...)} with our logic
     *
     * @param basePackages set of base packages for spring
     * @return
     * @see AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(String...)
     */
    public AnnotationConfigApplicationContext get(String... basePackages) {
        return new AnnotationConfigApplicationContext(basePackages) {
    
            @Override
            protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
                super.postProcessBeanFactory(beanFactory);
                configureBeans(beanFactory);
            }
        };
    }
    }
    

    ApplicationContext를 생성하는 동안 당신은

    Vertx vertx = ...; // either create or for vertx, it'll be passed to main verticle
    ApplicationContext context = new CustomAnnotationApplicationContextProvider(vertx).get(ApplicationSpringConfig.class);
    
  5. from https://stackoverflow.com/questions/4540713/add-bean-programmatically-to-spring-web-app-context by cc-by-sa and MIT license