Java 如何将动态创建的实例用作Spring autowiring中使用的bean
在Java 如何将动态创建的实例用作Spring autowiring中使用的bean,java,spring,Java,Spring,在注释ConfigWebApplicationContext中,我有一些特定实例需要用于自动布线。下面是演示错误的代码。当然,我的情况要复杂得多,实例是在运行时确定的。我在spring配置时发现了这些实例,这就是为什么如果下面的代码能够工作,就可以了。我试过了,但是它抛出了NoSuchBeanDefinitionException,即使ctx.getBean能够找到它。实现这一目标的正确方法是什么 import org.springframework.beans.factory.annotati
注释ConfigWebApplicationContext
中,我有一些特定实例需要用于自动布线。下面是演示错误的代码。当然,我的情况要复杂得多,实例是在运行时确定的。我在spring配置时发现了这些实例,这就是为什么如果下面的代码能够工作,就可以了。我试过了,但是它抛出了NoSuchBeanDefinitionException
,即使ctx.getBean
能够找到它。实现这一目标的正确方法是什么
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
class Scratch {
static class MyClass {
}
@Configuration
static class TestConfig {
@Autowired
private MyClass myClass;
}
public static void main(String[] args) {
MyClass requiredInstance = new MyClass();
final AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.refresh(); // Throws "BeanFactory not initialized..." on next line if this not here
ctx.getBeanFactory().registerSingleton("myClass", requiredInstance);
// Also tried: ((DefaultListableBeanFactory)ctx.getAutowireCapableBeanFactory()).registerSingleton("myClass", requiredInstance);
System.out.println(ctx.getBean(MyClass.class)); // Outputs "Scratch$MyClass@1804f60d"
ctx.register(TestConfig.class);
ctx.refresh(); // Throws "NoSuchBeanDefinitionException: No qualifying bean of type 'Scratch$MyClass' available:"
}
}
在这里找到了一个解决方案。我在别处看到过BeanFactoryPostProcessor,但他们没有展示如何创建实例。这个例子展示了我所需要的工厂机制
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
class Scratch {
static class MyClass {
}
@Configuration
static class TestConfig {
@Autowired
private MyClass myClass;
}
public static void main(String[] args) {
final AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(TestConfig.class);
ctx.register(DynamicBeanFactoryProcessor.class);
ctx.refresh();
System.out.println(ctx.getBean("myClass")); // Outputs "Scratch$MyClass@1804f60d"
System.out.println(ctx.getBean(MyClass.class)); // Outputs "Scratch$MyClass@1804f60d"
}
@Configuration
public static class DynamicBeanFactoryProcessor implements BeanFactoryPostProcessor {
public <T> T createInstance(Class<T> c) {
return c.cast(new MyClass()); // Create dynamic instance here
}
@Bean
public DynamicBeanFactoryProcessor dynamicBeanFactoryProcessor() {
return new DynamicBeanFactoryProcessor();
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
((BeanDefinitionRegistry)beanFactory).registerBeanDefinition("myClass",
BeanDefinitionBuilder.genericBeanDefinition(MyClass.class)
.setFactoryMethodOnBean("createInstance", "dynamicBeanFactoryProcessor")
.addConstructorArgValue(MyClass.class)
.getBeanDefinition());
}
}
}
import org.springframework.beans.BeansException;
导入org.springframework.beans.factory.annotation.Autowired;
导入org.springframework.beans.factory.config.BeanFactoryPostProcessor;
导入org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
导入org.springframework.beans.factory.support.BeanDefinitionBuilder;
导入org.springframework.beans.factory.support.BeanDefinitionRegistry;
导入org.springframework.context.annotation.Bean;
导入org.springframework.context.annotation.Configuration;
导入org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
课堂擦伤{
静态类MyClass{
}
@配置
静态类TestConfig{
@自动连线
私人MyClass MyClass;
}
公共静态void main(字符串[]args){
最终注释ConfigWebApplicationContext ctx=新注释ConfigWebApplicationContext();
寄存器(TestConfig.class);
寄存器(DynamicBeanFactoryProcessor.class);
ctx.refresh();
System.out.println(ctx.getBean(“myClass”);//输出“Scratch”$MyClass@1804f60d"
System.out.println(ctx.getBean(MyClass.class));//输出“Scratch”$MyClass@1804f60d"
}
@配置
公共静态类DynamicBeanFactoryProcessor实现BeanFactoryPostProcessor{
公共T createInstance(c类){
返回c.cast(new MyClass());//在此处创建动态实例
}
@豆子
公共DynamicBeanFactoryProcessor DynamicBeanFactoryProcessor(){
返回新的DynamicBeanFactoryProcessor();
}
@凌驾
public void后处理beanFactory(ConfigurableListableBeanFactory beanFactory)引发BeanException{
((BeanDefinitionRegistry)beanFactory).registerBeanDefinition(“myClass”,
BeanDefinitionBuilder.genericBeanDefinition(MyClass.class)
.setFactoryMethodOnBean(“createInstance”、“dynamicBeanFactoryProcessor”)
.addConstructorArgValue(MyClass.class)
.getBeanDefinition());
}
}
}
当您刷新一个注释ConfigWebApplicationContext
时,它会清除其底层BeanFactory
并创建一个新的,并使用新的来初始化bean。MyClass
bean之后将无法用于注入。当通过@Configuration
层次结构没有可用的MyClass
bean时,拥有一个依赖于MyClass
的TestConfig
是没有意义的。好吧,那么我有没有办法配置一个bean工厂类型的东西,可以在配置过程中注入我需要的实例?