Да, вы можете сделать это с помощью вашей пользовательской реализации 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.
Вы используете 'and':
type firstType =
| T1 of secondType
and secondType =
| T1 of firstType
Я понял это. Это:
type firstType =
| T1 of secondType
//................
and secondType =
| T1 of firstType
//................
Ограничение состоит в том, что типы должны быть объявлены в одном файле.