Ссылка на Autowire beans в список по типу
У меня есть один класс, который имеет список объектов типа Daemon
.
class Xyz {
List<Daemon> daemons;
}
Моя конфигурация spring выглядит следующим образом.
<bean id="xyz" class="package1.Xyz">
<property name="daemons" ref="daemonsList">
</bean>
<bean id="daemon1" class="package1.DaemonImpl1"/>
<bean id="daemon2" class="package1.DaemonImpl2"/>
<bean id="daemonsList" class="java.util.ArrayList">
<constructor-arg>
<list>
<ref bean="daemon1" />
<ref bean="daemon2" />
</list>
</constructor-arg>
</bean>
Теперь вместо явной проводки каждой реализации демона в списке можно автоматически автоушилить все beans типа Daemon
автоматически в списке. Проблема, которую я пытаюсь решить, заключается в том, что если кто-то создает bean новой реализации класса Daemon
и забывает подключить его к списку.
Я видел этот вопрос где-то в stackoverflow, но не смог найти его снова. Извинения за это.
Ответы
Ответ 1
Это должно работать так (удалите bean-компонент ArrayList из вашего XML):
public Class Xyz {
private List<Daemon> daemons;
@Autowired
public void setDaemons(List<Daemon> daemons){
this.daemons = daemons;
}
}
Я не думаю, что есть способ сделать это в XML.
Смотри: 3.9.2. @Autowired
и @Inject
:
Также возможно предоставить все bean-компоненты определенного типа из ApplicationContext, добавив аннотацию к полю или методу, который ожидает массив этого типа:
public class MovieRecommender {
@Autowired
private MovieCatalog[] movieCatalogs;
// ...
}
То же самое относится к типизированным коллекциям:
public class MovieRecommender {
private Set<MovieCatalog> movieCatalogs;
@Autowired
// or if you don't want a setter, annotate the field
public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs) {
this.movieCatalogs = movieCatalogs;
}
// ...
}
Кстати, @Ordered
с Spring 4.x, эти списки можно упорядочивать автоматически с @Ordered
механизма @Ordered
.
Ответ 2
Ну, это может быть достигнуто двумя способами, как указано в Spring Documentation.
Ниже приводится выдержка из документации.
С помощью ByType или режима конструктора автосцепок вы можете связывать массивы и типизированные коллекции.
1. autowire = "byType"
Автоматическое подключение с использованием "byType" может быть достигнуто, если тип bean-компонента, определенного в xml, соответствует типу списка.
Пример:
Motor.java
package com.chiranth;
public interface Motor
{
public void start();
}
ElectricMotor1.java
package com.chiranth;
public class ElectricMotor1 implements Motor
{
public void start()
{
System.out.println("Motor 1 Started.");
}
}
ElectricMotor2.java
package com.chiranth;
public class ElectricMotor2 implements Motor
{
public void start()
{
System.out.println("Motor 2 Started.");
}
}
TeslaModelX.java
package com.chiranth;
import java.util.List;
public class TeslaModelX
{
private List<Motor> motor;
public List<Motor> getMotor()
{
return motor;
}
public void setMotor(List<Motor> motor)
{
this.motor = motor;
}
public void goForward()
{
for(Motor m :motor)
m.start();
System.out.println("Going Forward.");
}
}
Spring.xml
<?xml version = "1.0" encoding = "UTF-8"?>
<beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation = "http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="electricMotor1" class="com.chiranth.ElectricMotor1"/>
<bean id="electricMotor2" class="com.chiranth.ElectricMotor2"/>
<bean id="modelX" class="com.chiranth.TeslaModelX" autowire="byType"/>
</beans>
Test.java
package com.chiranth;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test
{
public static void main(String[] args)
{
ApplicationContext context= new ClassPathXmlApplicationContext("Spring.xml");
TeslaModelX modelx=(TeslaModelX)context.getBean("modelX");
modelx.goForward();
}
}
ВЫХОД:
Motor 1 Started.
Motor 2 Started.
Going Forward.
2. autowire = "конструктор"
Автопроводка с использованием "конструктора" может быть достигнута, если тип bean-компонента, определенного в xml, соответствует типу аргумента в конструкторе.
Пример:
Учитывая вышеизложенное, Motor.java, ElectricMotor1.java и ElectricMotor2.java.
TeslaModelX.java
package com.chiranth;
import java.util.List;
public class TeslaModelX
{
private List<Motor> motor;
public TeslaModelX(List<Motor> motor)
{
this.motor=motor;
}
public void goForward()
{
for(Motor m:motor)
m.start();
System.out.println("Going Forward.");
}
}
Spring.xml
<beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation = "http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="electricMotor1" class="com.chiranth.ElectricMotor1"/>
<bean id="electricMotor2" class="com.chiranth.ElectricMotor2"/>
<bean id="modelX" class="com.chiranth.TeslaModelX" autowire="constructor"/>
</beans>
Test.java
package com.chiranth;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test
{
public static void main(String[] args)
{
ApplicationContext context= new ClassPathXmlApplicationContext("Spring.xml");
TeslaModelX modelX=(TeslaModelX)context.getBean("modelX");
modelX.goForward();
}
}
ВЫХОД:
Motor 1 Started.
Motor 2 Started.
Going Forward.