2010-07-14 4 views
4

Предположим, мы имеем простой @Configuration:Как создать настроенные аннотации компоненты с существующим экземпляром @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 и используйте его для производства фолов и баров.

Теперь предположим, что мы уже имеем экземпляр из FooBarConfiguration, и мы хотим создать FOOS и бары через Spring с это очень экземпляра. Есть ли способ сделать это?

Как создать компоненты, сконфигурированные с аннотациями, с существующим экземпляром объекта конфигурации?


пс. С помощью 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

Вам не нужна аннотация '@ Inject' на' createBar'. – whiskeysierra

+0

Правильно! Также как пример @Autowired in Spring. Я довольно новичок в конфигурации на основе аннотаций, я в основном хардкор oldschool Spring XML config guy. :) – lexicore

+0

Зачем вам нужно использовать существующий экземпляр класса конфигурации, а не новый?Возможно, есть еще один способ достичь вашей цели ... – meriton

ответ

2

Это невозможно, потому что некоторые особенности весны @Configuration требуют усиления класса, который не может быть сделано на существующем экземпляре.

Например, вы можете переписать конфигурацию следующим образом:

@Configuration 
public class FooBarConfiguration { 

    @Bean 
    public Foo createFoo() { 
     return new FooImpl(); 
    } 

    @Bean 
    public Bar createBar() { 
     return new BarImpl(createFoo()); 
    } 
} 

, и вы все равно получите полностью инициализированный экземпляр Foo, потому что вызов createFoo() будет перехвачен.

+0

Я действительно не понимаю, почему это невозможно, если прямой аналог работает в Guice. Я в порядке с некоторыми функциями, которые не работают, но общая вещь «вот примеры с аннотированными классами, из контекста приложения из них» должно быть возможным. – lexicore

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()); 

    } 

Однако, я не уверен, что это «хорошо» или «официальный» способ.

0

Весной вы в основном должны либо:

  1. Force ваш FooBarConfiguration быть одноплодной (не полагаясь на контейнер IoC для обеспечения этого - например реализовать с помощью перечисления или другой Singleton шаблон)

  2. Оберните свою FooBarConfiguration в FooBarConfigurationFactory и используйте что-то вроде MethodInvokingFactoryBean для ее вызова.

  3. Экспозиция статического метода фабрики, непосредственно на FooBarConfiguration, и использовать ту же технику, что и # 2.

+0

1. не работает как подкласс Spring под классом конфигурации при использовании java-based-config. 2. Как ваш метод, ссылающийся на заводские компоненты, знает, какую фабрику использовать? Как бы вы создали весну, чтобы создать бобы в конфигурации, созданной фабрикой? – meriton

Смежные вопросы