В настоящее время вы не можете не надеяться, что эта функция будет доступна в ближайшее время.
Вы можете отслеживать связанные проблемы https://github.com/angular/angular-cli/issues/10709
Да, вы можете сделать это с помощью вашей пользовательской реализации BeanFactoryPostProcessor.
Вот простой пример.
Предположим, что у нас есть две компоненты. Одна из них - зависимость для другой.
Первый компонент:
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
public class MyFirstComponent implements InitializingBean{
private MySecondComponent asd;
private MySecondComponent qwe;
public void afterPropertiesSet() throws Exception {
Assert.notNull(asd);
Assert.notNull(qwe);
}
public void setAsd(MySecondComponent asd) {
this.asd = asd;
}
public void setQwe(MySecondComponent qwe) {
this.qwe = qwe;
}
}
Как вы могли видеть, ничего особенного в этом компоненте нет. Он имеет зависимость от двух разных экземпляров MySecondComponent.
Второй компонент:
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Qualifier;
@Qualifier(value = "qwe, asd")
public class MySecondComponent implements FactoryBean {
public Object getObject() throws Exception {
return new MySecondComponent();
}
public Class getObjectType() {
return MySecondComponent.class;
}
public boolean isSingleton() {
return true;
}
}
Это немного сложнее. Вот две вещи, чтобы объяснить. Первый - @Qualifier - аннотация, содержащая имена компонентов MySecondComponent. Это стандартная, но вы свободны реализовать свои собственные. Позже вы увидите немного.
Второе, что нужно упомянуть, - это реализация FactoryBean. Если bean реализует этот интерфейс, он предназначен для создания некоторых других экземпляров. В нашем случае он создает экземпляры с типом MySecondComponent.
Самая сложная часть - реализация BeanFactoryPostProcessor:
import java.util.Map;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
Map<String, Object> map = configurableListableBeanFactory.getBeansWithAnnotation(Qualifier.class);
for(Map.Entry<String,Object> entry : map.entrySet()){
createInstances(configurableListableBeanFactory, entry.getKey(), entry.getValue());
}
}
private void createInstances(
ConfigurableListableBeanFactory configurableListableBeanFactory,
String beanName,
Object bean){
Qualifier qualifier = bean.getClass().getAnnotation(Qualifier.class);
for(String name : extractNames(qualifier)){
Object newBean = configurableListableBeanFactory.getBean(beanName);
configurableListableBeanFactory.registerSingleton(name.trim(), newBean);
}
}
private String[] extractNames(Qualifier qualifier){
return qualifier.value().split(",");
}
}
Что она делает? Он проходит через все бобы, аннотированные с помощью @Qualifier, извлекает имена из аннотации и затем вручную создает бобы этого типа с указанными именами.
Вот конфигурация Spring:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean class="MyBeanFactoryPostProcessor"/>
<bean class="MySecondComponent"/>
<bean name="test" class="MyFirstComponent">
<property name="asd" ref="asd"/>
<property name="qwe" ref="qwe"/>
</bean>
</beans>
Последнее, что нужно заметить здесь, хотя вы можете сделать это, вы не должны, если это не обязательно, потому что это не совсем естественный способ конфигурации. Если у вас более одного экземпляра класса, лучше придерживаться конфигурации XML.
Вдохновленный ответом воска , реализация может быть более безопасной и не пропускать другую пост-обработку, если добавлены определения, а не построены одиночные:
public interface MultiBeanFactory<T> { // N.B. should not implement FactoryBean
T getObject(String name) throws Exception;
Class<?> getObjectType();
Collection<String> getNames();
}
public class MultiBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
Map<String, MultiBeanFactory> factories = beanFactory.getBeansOfType(MultiBeanFactory.class);
for (Map.Entry<String, MultiBeanFactory> entry : factories.entrySet()) {
MultiBeanFactory factoryBean = entry.getValue();
for (String name : factoryBean.getNames()) {
BeanDefinition definition = BeanDefinitionBuilder
.genericBeanDefinition(factoryBean.getObjectType())
.setScope(BeanDefinition.SCOPE_SINGLETON)
.setFactoryMethod("getObject")
.addConstructorArgValue(name)
.getBeanDefinition();
definition.setFactoryBeanName(entry.getKey());
registry.registerBeanDefinition(entry.getKey() + "_" + name, definition);
}
}
}
}
@Configuration
public class Config {
@Bean
public static MultiBeanFactoryPostProcessor() {
return new MultiBeanFactoryPostProcessor();
}
@Bean
public MultiBeanFactory<Person> personFactory() {
return new MultiBeanFactory<Person>() {
public Person getObject(String name) throws Exception {
// ...
}
public Class<?> getObjectType() {
return Person.class;
}
public Collection<String> getNames() {
return Arrays.asList("Joe Smith", "Mary Williams");
}
};
}
}
Названия bean все еще происходят из любого места, например, пример воска @Qualifier
. Существуют различные другие свойства в определении компонента, включая способность наследовать от самого завода.
Это невозможно. Вы получаете дублирующее исключение.
Это также далеко не оптимально с такими данными конфигурации, как это в ваших классах реализации.
Если вы хотите использовать аннотации, вы можете настроить свой класс с помощью Конфигурация Java :
@Configuration
public class PersonConfig {
@Bean
public Person personOne() {
return new Person("Joe", "Smith");
}
@Bean
public Person personTwo() {
return new Person("Mary", "Williams");
}
}
Мне просто пришлось решить аналогичный случай. Это может сработать, если вы можете переопределить класс.
// This is not a @Component
public class Person {
}
@Component
public PersonOne extends Person {
public PersonOne() {
super("Joe", "Smith");
}
}
@Component
public PersonTwo extends Person {
public PersonTwo() {
super("Mary","Williams");
}
}
Тогда просто используйте PersonOne или PersonTwo всякий раз, когда вам нужно автоустановить конкретный экземпляр, а везде просто используйте Person.