如何以编程方式向Spring上下文中添加bean?

7
我想从一些配置中创建自定义子上下文,并以编程方式添加一些bean。
我阅读了有关BeanDefinitionRegistryPostProcessor的答案https://dev59.com/Wm855IYBdhLWcg3wGQNM#4540762,但不知道如何使用它。如果我编写BeanDefinitionRegistryPostProcessor的实现,那么接下来该怎么做呢?添加到上下文中吗?但这就是问题所在:如何向上下文添加bean!如果我能够将BeanDefinitionRegistryPostProcessor添加到上下文中,那么为什么还要问如何添加bean呢?
问题在于我有一个上下文并希望向其中添加bean。
我知道我可以实例化bean并使用自动装配。
Context#getAutowireCapableBeanFactory().createBean(klass);

但这似乎只是将类连接起来,而没有将其添加到上下文中?


1
你基本上需要将bean添加到创建新Spring上下文时获取的上下文中,查看此链接:https://dev59.com/bGUp5IYBdhLWcg3wXGoZ#15329777 - Japu_D_Cret
这个回答解决了你的问题吗?将Bean以编程方式添加到Spring Web应用程序上下文 - akop
3个回答

17

Spring 5.0 开始,您可以直接使用 GenericApplicationContext 动态地注册您的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。


2
我正在使用Spring 5.3(Spring Boot v2.7.1),但是registerBean()ApplicationContext中无法识别。我做错了什么? - WebViewer

1

以下是我原先回答这里时的内容,再次重复一遍。

实际上,AnnotationConfigApplicationContext 是从 AbstractApplicationContext 派生而来的,而 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);

请不要重复自己。请标记问题为重复。 - akop

1

我在当前应用程序中使用这个,因为我已经有一个想要注册的对象。 我可以将applicationContext注入为一个bean。

private void registerAsBean(
  ApplicationContext injectedApplicationContext, 
  MyClass objectToRegisterAsBean, 
  String beanName) {

    AutowireCapableBeanFactory beanFactory = 
      injectedApplicationContext.getAutowireCapableBeanFactory();
    beanFactory.initializeBean(objectToRegisterAsBean, beanName);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接