【问题标题】:How to add bean programmatically to Spring context?如何以编程方式将 bean 添加到 Spring 上下文?
【发布时间】:2017-08-18 16:33:42
【问题描述】:

我想从一些配置中创建自定义子上下文,并以编程方式另外添加一些 bean。

我阅读了关于BeanDefinitionRegistryPostProcessor 的答案https://stackoverflow.com/a/4540762/258483,但不明白如何使用它。如果我编写了BeanDefinitionRegistryPostProcessor 的实现,那么接下来该怎么做呢?添加到上下文中?但这是一个问题:如何将 bean 添加到上下文中!如果我能够将BeanDefinitionRegistryPostProcessor 添加到上下文中,那我为什么要问如何添加bean?

问题是我有上下文并想向其中添加 bean。

我知道我可以实例化 bean 并自动装配它们

Context#getAutowireCapableBeanFactory().createBean(klass);

但这显然只是连接类,而不是将其添加到上下文中?

【问题讨论】:

标签: java spring


【解决方案1】:

原来是我自己回答的here,这里也重复一下。

实际上AnnotationConfigApplicationContext 是从AbstractApplicationContext 派生的,其中有一个空的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);

【讨论】:

    【解决方案2】:

    Spring 5.0 开始,您可以直接使用ApplicationContext 动态注册您的bean。

    GenericApplicationContext ac = ....;
    // example
    ac.registerBean("myspecialBean", Integer.class, () -> new Integer(100));
    // using BeanDefinitionCustomizer
    ac.registerBean("myLazySpecialBean", Integer.class, () -> new Integer(100), (bd) -> bd.setLazyInit(true));
    

    在此处查看javadoc,了解registerBean 的不同API

    【讨论】:

      猜你喜欢
      • 2015-01-31
      • 2011-05-31
      • 2010-12-29
      • 1970-01-01
      • 2015-06-24
      • 1970-01-01
      • 1970-01-01
      • 2014-02-27
      相关资源
      最近更新 更多