1. Введение
Фабричные методы могут быть полезным методом для сокрытия сложной логики создания в одном вызове метода.
Хотя обычно мы создаем bean-компоненты в Spring с помощью конструктора или внедрения полей , мы также можем создавать bean-компоненты Spring с помощью фабричных методов .
В этом руководстве мы углубимся в создание bean-компонентов Spring с использованием методов экземпляра и статической фабрики.
2. Метод фабрики экземпляров
Стандартная реализация шаблона фабричного метода заключается в создании метода экземпляра, который возвращает желаемый компонент.
Кроме того, мы можем настроить Spring для создания желаемого bean-компонента с аргументами или без них .
2.1. Без аргументов
Мы можем создать класс Foo
, который представляет создаваемый bean-компонент:
public class Foo {}
Затем мы создаем класс InstanceFooFactory
, который включает фабричный метод createInstance
, который создает наш bean-компонент Foo
:
public class InstanceFooFactory {
public Foo createInstance() {
return new Foo();
}
}
После этого настраиваем Spring:
- Создайте bean-компонент для нашего фабричного класса (
InstanceFooFactory
) - Используйте атрибут
factory-bean
для ссылки на наш factory bean - Используйте атрибут
factory-method
для ссылки на наш заводской метод (createInstance
)
Применив это к конфигурации Spring XML, мы получим:
<beans ...>
<bean id="instanceFooFactory"
class="com.foreach.factorymethod.InstanceFooFactory" />
<bean id="foo"
factory-bean="instanceFooFactory"
factory-method="createInstance" />
</beans>
Наконец, мы автоматически связываем желаемый компонент Foo .
Затем Spring создаст наш bean-компонент, используя наш фабричный метод createInstance
:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/factorymethod/instance-config.xml")
public class InstanceFooFactoryIntegrationTest {
@Autowired
private Foo foo;
@Test
public void givenValidInstanceFactoryConfig_whenCreateFooInstance_thenInstanceIsNotNull() {
assertNotNull(foo);
}
}
2.2. С аргументами
Мы также можем предоставить аргументы нашему методу фабрики экземпляров, используя элементstructor -arg
в нашей конфигурации Spring.
Во-первых, мы создаем класс Bar
, который использует аргумент:
public class Bar {
private String name;
public Bar(String name) {
this.name = name;
}
// ...getters & setters
}
Затем мы создаем класс фабрики экземпляров InstanceBarFactory
с фабричным методом, который принимает аргумент и возвращает bean-компонент Bar
:
public class InstanceBarFactory {
public Bar createInstance(String name) {
return new Bar(name);
}
}
Наконец, мы добавляем элемент конструктора-аргумента
к нашему определению bean-компонента Bar
:
<beans ...>
<bean id="instanceBarFactory"
class="com.foreach.factorymethod.InstanceBarFactory" />
<bean id="bar"
factory-bean="instanceBarFactory"
factory-method="createInstance">
<constructor-arg value="someName" />
</bean>
</beans>
Затем мы можем автоматически связать наш bean-компонент Bar
так же, как мы сделали это для нашего bean-компонента Foo
:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/factorymethod/instance-bar-config.xml")
public class InstanceBarFactoryIntegrationTest {
@Autowired
private Bar instance;
@Test
public void givenValidInstanceFactoryConfig_whenCreateInstance_thenNameIsCorrect() {
assertNotNull(instance);
assertEquals("someName", instance.getName());
}
}
3. Метод статической фабрики
Мы также можем настроить Spring для использования статического метода в качестве фабричного метода.
Хотя методы фабрики экземпляров следует отдавать предпочтение, этот метод может быть полезен, если у нас есть существующие, устаревшие статические методы, которые производят желаемые компоненты. Например, если фабричный метод возвращает синглтон, мы можем настроить Spring для использования этого фабричного метода синглтона.
Подобно методам фабрики экземпляров, мы можем настраивать статические методы с аргументами и без них.
3.1. Без аргументов
Используя наш класс Foo
в качестве желаемого bean-компонента, мы можем создать класс SingletonFooFactory
, который включает фабричный метод createInstance
, возвращающий одноэлементный экземпляр Foo
:
public class SingletonFooFactory {
private static final Foo INSTANCE = new Foo();
public static Foo createInstance() {
return INSTANCE;
}
}
На этот раз нам нужно создать только один компонент. Этот bean-компонент требует только два атрибута:
class
— объявляет наш фабричный класс (SingletonFooFactory
)factory-method
— объявляет статический метод factory (createInstance
)
Применив это к нашей XML-конфигурации Spring, мы получим:
<beans ...>
<bean id="foo"
class="com.foreach.factorymethod.SingletonFooFactory"
factory-method="createInstance" />
</beans>
Наконец, мы автоматически связываем наш bean-компонент Foo
, используя ту же структуру, что и раньше:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/factorymethod/static-foo-config.xml")
public class SingletonFooFactoryIntegrationTest {
@Autowired
private Foo singleton;
@Test
public void givenValidStaticFactoryConfig_whenCreateInstance_thenInstanceIsNotNull() {
assertNotNull(singleton);
}
}
3.2. С аргументами
Хотя нам следует по возможности избегать изменения состояния статических объектов, таких как наш синглтон , мы все же можем передавать аргументы в наш статический фабричный метод.
Для этого мы создаем новый фабричный метод, который принимает нужные нам аргументы:
public class SingletonBarFactory {
private static final Bar INSTANCE = new Bar("unnamed");
public static Bar createInstance(String name) {
INSTANCE.setName(name);
return INSTANCE;
}
}
После этого мы настраиваем Spring для передачи нужного аргумента с помощью элементаstructor -arg :
<beans ...>
<bean id="bar"
class="com.foreach.factorymethod.SingletonBarFactory"
factory-method="createInstance">
<constructor-arg value="someName" />
</bean>
</beans>
Наконец, мы автоматически подключаем наш компонент Bar
, используя ту же структуру, что и раньше:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/factorymethod/static-bar-config.xml")
public class SingletonBarFactoryIntegrationTest {
@Autowired
private Bar instance;
@Test
public void givenValidStaticFactoryConfig_whenCreateInstance_thenNameIsCorrect() {
assertNotNull(instance);
assertEquals("someName", instance.getName());
}
}
4. Вывод
В этой статье мы рассмотрели, как настроить Spring для использования методов экземпляра и статической фабрики — как с аргументами, так и без них.
Хотя создание bean-компонентов с помощью конструктора и внедрения полей более распространено, фабричные методы могут быть удобны для сложных шагов создания и устаревшего кода.
Код, использованный в этой статье, можно найти на GitHub .