简体   繁体   English

如何在 Spring Boot 中动态注册 bean?

[英]How to register bean dynamically in Spring Boot?

I am looking to override the SSLContext of Spring at runtime.我希望在运行时覆盖 Spring 的 SSLContext。 Hence I am trying to find ways to register the below method as a bean dynamically.因此,我试图找到将以下方法动态注册为 bean 的方法。

For Ex .对于 Ex When a GetMapping endpoint is invoked, the below method should be injected as a bean into Spring IoC.当调用 GetMapping 端点时,以下方法应作为 bean 注入 Spring IoC。

public static SSLContext getSSLContext() throws Exception {
    TrustManager[] trustManagers = new TrustManager[] {
            new ReloadableX509TrustManager(truststoreNewPath)
    };
    SSLContext sslContext = SSLContext.getInstance("SSL");
    sslContext.init(null, trustManagers, null);
    return sslContext;
}

How can I do this?我怎样才能做到这一点?

You can use the ConfigurableBeanFactory to register beans manually at runtime.您可以使用 ConfigurableBeanFactory 在运行时手动注册 bean。

@Service
public class RegisterBeansDynamically implements BeanFactoryAware {

    private ConfigurableBeanFactory beanFactory;

    public <T> void registerBean(String beanName, T bean) {
        beanFactory.registerSingleton(beanName, bean);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = (ConfigurableBeanFactory) beanFactory;
    }
}

But keep in mind: Your context must be refreshed making other beans able getting your new bean automatically injected or they have to access them dynamically from the application context.但请记住:必须刷新您的上下文,使其他 bean 能够自动注入您的新 bean,否则它们必须从应用程序上下文动态访问它们。

The BeanFactory can also be accessed directly through the application context see this answer . BeanFactory 也可以通过应用程序上下文直接访问,请参阅此答案

you should annotate the method with @bean and class with @configuration see docs https://docs.spring.io/spring-javaconfig/docs/1.0.0.M4/reference/html/ch02s02.html您应该使用@bean 和类使用@configuration 注释方法,请参阅文档https://docs.spring.io/spring-javaconfig/docs/1.0.0.M4/reference/html/ch02s02.html

@Bean 
public static SSLContext getSSLContext() throws Exception {
TrustManager[] trustManagers = new TrustManager[] {
        new ReloadableX509TrustManager(truststoreNewPath)
};
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustManagers, null);
return sslContext;
}

Here is the demo.这是演示。

public class Demo implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        ConfigurableApplicationContext context = (ConfigurableApplicationContext)applicationContext;
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory)context.getBeanFactory();

        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(YourClass.class);

        beanDefinitionBuilder.addPropertyValue("property1", "propertyValue");
        beanDefinitionBuilder.addPropertyValue("property2", applicationContext.getBean(AnotherClass.class));


        beanFactory.registerBeanDefinition("yourBeanName", beanDefinitionBuilder.getBeanDefinition());


    }
}

You can move the register part to your method(start from BeanDefinitionBuilder ).您可以将注册部分移动到您的方法中(从BeanDefinitionBuilder开始)。 I suppose this will suit your demand.我想这将满足您的需求。

Spring 5 provides Bean registration, which can be done dynamically. Spring 5 提供了可以动态完成的 Bean 注册。 Please look at documentation here and example here .请查看此处的文档和此处的示例。

Supplier<SSLContext> sslcontextSupplier = () -> getSSLContext();
context.registerBean("sslcontext",SSLContext.class,sslcontextSupplier);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM