簡體   English   中英

以編程方式將 Bean 添加到 Spring Web App 上下文

[英]Add Bean Programmatically to Spring Web App Context

由於插件架構,我試圖以編程方式向我的 web 應用程序添加一個 bean。 我有一個通過@Component注釋創建的 Spring bean,我正在實現ApplicationContextAware接口。

我的覆蓋函數如下所示:

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

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

基本上,我無法弄清楚如何將 bean 添加到給定 setApplicationContext 的 applicationContext 對象中。 誰能告訴我我是如何以錯誤的方式解決這個問題的?

好的,這就是我最終得到的解決方案:

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

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

這是一個簡單的代碼:

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

在 Spring 3.0 中,您可以讓 bean 實現BeanDefinitionRegistryPostProcessor並通過BeanDefinitionRegistry添加新 bean。

在以前的 Spring 版本中,您可以在BeanFactoryPostProcessor執行相同的操作(盡管您需要將BeanFactoryBeanDefinitionRegistry ,這可能會失敗)。

為什么你需要它是GenericWebApplicationContext類型?
我認為您可能可以使用任何 ApplicationContext 類型。

通常你會使用一個 init 方法(除了你的 setter 方法):

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

你可以使用任何一種來連接 bean

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

或者

AutowireCapableBeanFactory.initializeBean(Object existingbean, String beanName)

實際上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);

首先初始化屬性值

MutablePropertyValues mutablePropertyValues = new MutablePropertyValues();
mutablePropertyValues.add("hostName", details.getHostName());
mutablePropertyValues.add("port", details.getPort());

DefaultListableBeanFactory context = new DefaultListableBeanFactory();
GenericBeanDefinition connectionFactory = new GenericBeanDefinition();
connectionFactory.setBeanClass(Class);
connectionFactory.setPropertyValues(mutablePropertyValues);

context.registerBeanDefinition("beanName", connectionFactory);

添加到bean列表

ConfigurableListableBeanFactory beanFactory = ((ConfigurableApplicationContext) applicationContext).getBeanFactory();
beanFactory.registerSingleton("beanName", context.getBean("beanName"));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM