假设我们有一个简单的@Configuration
:
@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和Bars。
现在假设我们已经有FooBarConfiguration
的实例,我们希望通过Spring创建Foos和Bars,并使用这个实例。有没有办法实现这个目标?
如何使用配置对象的现有实例创建注释配置的bean?
PS。使用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());
答案 0 :(得分:2)
这是不可能的,因为Spring的@Configuration
的某些功能需要类增强,而这在现有实例上是无法完成的。
例如,您可以按如下方式重写配置:
@Configuration
public class FooBarConfiguration {
@Bean
public Foo createFoo() {
return new FooImpl();
}
@Bean
public Bar createBar() {
return new BarImpl(createFoo());
}
}
并且您仍然会获得Foo
的完全初始化的实例,因为对createFoo()
的调用将被截获。
答案 1 :(得分:2)
这是我自己的变体:
@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());
}
但是,我不确定这是“好”还是“官方”的方式。
答案 2 :(得分:0)
在春天你基本上要么:
强制你的FooBarConfiguration 单身人士(不依赖于IoC 容器来强制执行此操作 - 例如 使用枚举或其他方法实现 单身人士模式)
将您的FooBarConfiguration包装在FooBarConfigurationFactory中,并使用类似MethodInvokingFactoryBean的方法来调用它。
直接在FooBarConfiguration上公开静态工厂方法,并使用与#2相同的技术。