Spring 如何使用@Configuration的现有实例创建注释配置bean?
假设我们有一个简单的Spring 如何使用@Configuration的现有实例创建注释配置bean?,spring,dependency-injection,annotations,guice,Spring,Dependency Injection,Annotations,Guice,假设我们有一个简单的@配置: @Configuration public class FooBarConfiguration { @Bean public Foo createFoo() { return new FooImpl(); } @Bean @Autowired public Bar createBar(Foo foo) { return new BarImpl(foo); } } 此类可与A
@配置
:
@Configuration
public class FooBarConfiguration {
@Bean
public Foo createFoo() {
return new FooImpl();
}
@Bean
@Autowired
public Bar createBar(Foo foo) {
return new BarImpl(foo);
}
}
此类可与AnnotationConfigApplicationContext
一起使用,以生成Foo
和Bar
实例:
final ApplicationContext applicationContext =
new AnnotationConfigApplicationContext(FooBarConfiguration.class);
final Foo foo = applicationContext.getBean(Foo.class);
final Bar bar = applicationContext.getBean(Bar.class);
assertSame(foo, bar.getFoo());
在上面的示例中,Spring将创建一个新的FooBarConfiguration
实例,并使用它生成Foos和bar
现在假设我们已经有了一个FooBarConfiguration
的实例,我们希望通过Spring用这个实例创建Foos和bar。有没有办法做到这一点
如何使用配置对象的现有实例创建注释配置bean?
另外,使用Google Guice,解决方案非常简单:
public class FooBarConfiguration implements Module {
@Provides
@Singleton
public Foo createFoo() {
return new FooImpl();
}
@Override
public void configure(Binder binder) {
}
@Provides
@Inject
@Singleton
public Bar createBar(Foo foo) {
return new BarImpl(foo);
}
}
final FooBarConfiguration fooBarConfiguration = ...; // Our instance
final Injector injector = Guice.createInjector(fooBarConfiguration);
final Foo foo = injector.getInstance(Foo.class);
final Bar bar = injector.getInstance(Bar.class);
assertSame(foo, bar.getFoo());
这是不可能的,因为Spring的
@Configuration
的某些功能需要类增强,而这在现有实例上是无法实现的
例如,您可以按如下方式重写配置:
@Configuration
public class FooBarConfiguration {
@Bean
public Foo createFoo() {
return new FooImpl();
}
@Bean
public Bar createBar() {
return new BarImpl(createFoo());
}
}
您仍然会得到一个完全初始化的Foo
实例,因为对createFoo()
的调用将被拦截 以下是我自己的变体:
@Test
public void createFromConfigurationInstance() {
final FooBarConfiguration fooBarConfiguration = new FooBarConfiguration();
final DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
final AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new AnnotatedBeanDefinitionReader(
beanFactory);
annotatedBeanDefinitionReader.register(FooBarConfiguration.class);
beanFactory.registerSingleton("fooBarConfiguration",
fooBarConfiguration);
final ConfigurableApplicationContext applicationContext = new GenericApplicationContext(
beanFactory);
applicationContext.refresh();
final Foo foo = applicationContext.getBean(Foo.class);
final Bar bar = applicationContext.getBean(Bar.class);
assertSame(foo, bar.getFoo());
}
然而,我不确定这是一种“好”还是“正式”的方式。在春季,你基本上必须:
您不需要
createBar
上的@Inject
注释。对!以及Spring示例中的@Autowired。我对基于注释的配置相当陌生,我主要是一个老派的SpringXML配置专家为什么需要使用配置类的现有实例而不是新实例?也许还有另一种方法可以达到你的目标…@meriton:简短的回答是因为我试图将一些基于Guice的DI东西从Guice移植到Spring。一个较长的答案是,这种方法允许对bean创建过程进行更多的编程控制。这里有一个例子。假设您有一个创建HTTP服务器(如Jetty)的bean工厂,您所需要做的就是提供一个端口。您的应用程序希望在运行时决定此端口。比较“Guice方式”和“Spring方式”,Guice的维护级别配置似乎要优雅得多。我真的不明白为什么直接模拟在Guice中工作是不可能的。我对某些功能不起作用表示满意,但一般来说,“这里的实例带有注释类,使用它们创建应用程序上下文”必须是可能的。当使用基于java的配置时,不作为Spring的配置类子类工作。2.调用工厂bean的方法如何知道使用哪个工厂?如何让spring在工厂创建的配置中创建bean?