2016-09-06 5 views
1

В моем приложенииContext у меня есть несколько Beans, созданных в том же стиле. Поэтому у меня есть много дублированных кодов, на которых написано FactoryBean для каждого из этих компонентов. Эти бобы имеют общую основу, реализуя весь один специальный интерфейс.Как создать фасоль по типу весной?

Я хотел бы переместить все, что было создано на фабрике. Это можно было бы обеспечить Methode как этого

<T extends CommonInterface> T createInstance(Class<T> clazz); 

Там я мог бы реализовать все экземпляр, необходимый для создания одного из моих специальных бобов.

Моя реализация будет называться пружиной для

@Autowired 
private MyCommonInterfaceImplementation impl; 

таким образом

createInstance(MyCommonInterfaceImplementation.class) 

До сих пор я смотрел на BeanFactory и FactoryBean, как кажется, не я ищу.

Любые предложения?

+0

Почему вы не используете аннотацию '@ Component'? –

+0

@MartinFrey, как помогает аннотация компонента в этом случае? Может быть, я полностью понимаю вопрос, но в этом случае я в этом случае аннотации не является решением –

ответ

1

почему бы не использовать @bean

@Bean 
public MyCommonInterfaceImplementation getMyCommonInterfaceImplementation(){ 
    return MyBeanFactory.createInstance(MyCommonInterfaceImplementation.class); 
} 

//should autowire here 
@Autowired 
private MyCommonInterfaceImplementation impl; 
+0

ОК, это намного лучше, чем реализация каждый раз FactoryBean. Но у меня есть что-то около 30 Бобов, ведущих к 30 методам @Bean, которые делают все то же самое. Возможность создания компонента по классу была бы большой помощью. – mibutec

0

С весны 4.3 вы больше не должны аннотировать классы боба, и вы можете позволить им быть создан с помощью componentscan.

@Configuration @ComponentScan( value = "some.package.path", includeFilters = { @Filter(type = ASSIGNABLE_TYPE, value = { MyClass1.class, MyClass2.class, MyClass3.class }) })

Это фактически создает бобы для трех классов, перечисленных там. Пример должен работать и без фильтров (все в пакете становится bean-компонентом). Это работает до тех пор, пока классы имеют один конструктор, который можно использовать для автоустройства. Я не думаю, что можно фильтровать для всех реализаций определенного интерфейса, а затем зарегистрировать компонент.

Для этого вы можете что-то сделать с помощью ContextListener и, например, используйте рефлексию, чтобы узнать, какие классы нужно создать, а затем использовать context.autowire (..) для инъекции любых зависимостей из вашего контекста. Немного взломан, но это может сработать.

@Override public void onApplicationEvent(ContextRefreshedEvent event) { ApplicationContext context = event.getApplicationContext(); MyClass bean = context .getAutowireCapableBeanFactory() .autowire(MyClass.class, Autowire.BY_NAME.value(), true); ... }

Это все еще оставляет проблему, как получить боб, зарегистрированного в контексте курса.

Возможно, вы также сможете адаптировать ответ на this SO question о том, как программно добавлять компоненты.

1

В принципе, вы должны указать аннотацию @Bean на «фабрику», только если вам нужна специальная обработка во время создания компонента.

Если все может быть @Autowired, либо сеттеры, поля или одного конструктора, и ничего больше должно быть сделано на боба во время инициализации, вы можете просто объявить аннотацию @Component на каждой реализации своего интерфейса. Это работает до тех пор, пока в вашем приложении активен component scanning. Результатом будет то, что для каждого компонента весна создаст компонент, который вы можете использовать.

Я пишу это на мобильном телефоне, поэтому показ кода не самый лучший.Просто следуйте инструкциям по @ComponentScan, или если вам нужно, сообщите мне, и я могу увеличить этот ответ на примере.

0

И наконец, лучший подход, который я нашел, использует ConfigurationClassPostProcessor. В качестве примера я использовал https://github.com/rinoto/spring-auto-mock

Но, поскольку для создания бобов из ничего сложнее и «слишком много магии», мы решили явно создать эти бобы через @Bean.

Спасибо за ваши ответы.