[英]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
執行相同的操作(盡管您需要將BeanFactory
為BeanDefinitionRegistry
,這可能會失敗)。
為什么你需要它是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.