如何在Spring WebApplicationContext中在运行时添加bean实例?

时间:2017-03-27 16:09:53

标签: java spring spring-mvc

所以,标题非常简单。我有一个处理程序类DynamicBeanHandler,它实现了spring提供的BeanDefinitionRegistryPostProcessor接口。在这个类中,我添加了多个SCOPE_SINGLETON bean,其bean类设置为MyDynamicBean,如下所示 -

GenericBeanDefinition myBeanDefinition = new GenericBeanDefinition();
myBeanDefinition.setBeanClass(MyDynamicBean.class);
myBeanDefinition.setScope(SCOPE_SINGLETON);
myBeanDefinition.setPropertyValues(getMutableProperties(dynamicPropertyPrefix));
registry.registerBeanDefinition(dynamicBeanId, myBeanDefinition);

方法getMutableProperties()返回MutablePropertyValues

的对象

稍后,我会SpringUtil.getBean(dynamicBeanId)获取MyDynamicBean类实现SpringUtil所需的ApplicationContextAware实例。这一切都很棒。当我想要删除其中一个实例并稍后在没有注册表实例的地方添加新实例时,就会出现问题。谁能帮我找到办法呢?

以下是课程SpringUtil -

的代码
public class SpringUtil implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringUtil.applicationContext = applicationContext;
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    public static Object getBean(String beanId) {
        return applicationContext.getBean(beanId);
    }

    public static <T> T getBean(String beanId, Class<T> beanClass) {
        return applicationContext.getBean(beanId, beanClass);
    }
}

3 个答案:

答案 0 :(得分:14)

您可以使用var client = new TcpClient { ... }; await client.ConnectAsync(...); var idleTimeout = new TaskDelayedCompletionSource(HEARTBEAT_LOST_THRESHOLD); Task heartbeatLost = idleTimeout.Task; while (...) { Task<int> readTask = client.ReadAsync(buffer, 0, buffer.Length); Task first = await Task.WhenAny(heartbeatLost, readTask); if (first == readTask) { if (ProcessData(buffer, 0, readTask.Result).HeartbeatFound) { idleTimeout.ResetDelay(HEARTBEAT_LOST_THRESHOLD); } } else if (first == heartbeatLost) { TellUserPeerIsDown(); break; } } (查看here for API)来动态删除或注册bean。

因此,在您的BeanDefinitionRegistry类中,您可以使用SpringUtil添加以下方法来删除现有的bean定义,然后使用removeBeanDefinition()添加新的bean定义。

registerBeanDefinition()

答案 1 :(得分:0)

您可以代替自动装配WebApplicationContext

@Autowired
private GenericWebApplicationContext context;

然后您可以注册新的bean或删除旧的bean并注册新的bean

AutowireCapableBeanFactory factory = context.getAutowireCapableBeanFactory();
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) factory;
registry.removeBeanDefinition("myBean");
context.registerBean("myBean", MyBean.class, () -> new MyBean());

答案 2 :(得分:0)

您可以通过以下方式以编程方式创建具有已注入依赖性的bean:

AutowireCapableBeanFactory#createBean

用指定的类完全创建给定类的新bean实例 自动装配策略。该接口中定义的所有常量都是 在这里支持。执行Bean的完全初始化,包括 所有适用的BeanPostProcessors。

@Autowired
ApplicationContext context;

AutowireCapableBeanFactory factory = context.getAutowireCapableBeanFactory();
MyDynamicBean bean = (MyDynamicBean) factory.createBean(MyDynamicBean.class, AUTOWIRE_CONSTRUCTOR, false);