Рубрики
Без рубрики

Как использовать весенний завод?

Краткое руководство по API Spring FactoryBean с примерами.

Автор оригинала: baeldung.

1. Обзор

В контейнере для весенних бобов есть два вида бобов: обычные бобы и фабричные бобы. Spring использует первые напрямую, в то время как последние могут создавать сами объекты, которые управляются фреймворком.

И, проще говоря, мы можем построить заводскую фасоль, реализовав org.springframework.beans.factory.FactoryBean интерфейс.

2. Основы фабричной фасоли

2.1. Реализация FactoryBean

Давайте сначала рассмотрим интерфейс FactoryBean :

public interface FactoryBean {
    T getObject() throws Exception;
    Class getObjectType();
    boolean isSingleton();
}

Давайте обсудим три метода:

  • GetObject() – возвращает объект, созданный фабрикой, и это объект, который будет использоваться контейнером Spring
  • getObjectType() – возвращает тип объекта, который создает этот FactoryBean
  • isSingleton() – обозначает, является ли объект, созданный этим FactoryBean , одноэлементным

Теперь давайте реализуем пример FactoryBean . Мы реализуем Инструментальную фабрику , которая производит объекты типа Инструмент :

public class Tool {

    private int id;

    // standard constructors, getters and setters
}

Инструментальный завод сам по себе:

public class ToolFactory implements FactoryBean {

    private int factoryId;
    private int toolId;

    @Override
    public Tool getObject() throws Exception {
        return new Tool(toolId);
    }

    @Override
    public Class getObjectType() {
        return Tool.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }

    // standard setters and getters
}

Как мы видим, Tool Factory – это FactoryBean , который может производить Tool объекты.

2.2. Используйте FactoryBean С Конфигурацией на основе XML

Давайте теперь посмотрим, как использовать наш Инструментальный завод .

Мы начнем создавать инструмент с конфигурацией на основе XML – factorybean-spring-ctx.xml :



    
        
        
    

Затем мы можем проверить, правильно ли введен объект Tool :

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:factorybean-spring-ctx.xml" })
public class FactoryBeanXmlConfigTest {
    @Autowired
    private Tool tool;

    @Test
    public void testConstructWorkerByXml() {
        assertThat(tool.getId(), equalTo(1));
    }
}

Результат теста показывает, что нам удалось внедрить объект инструмента, созданный Tool Factory , со свойствами, которые мы настроили в factorybean-spring-ctx.xml .

Результат теста также показывает, что контейнер Spring использует объект, созданный FactoryBean , вместо самого себя для внедрения зависимостей.

Хотя контейнер Spring использует возвращаемое значение метода FactoryBean ‘s GetObject() в качестве компонента, вы также можете использовать сам FactoryBean .

Чтобы получить доступ к Заводской , вам просто нужно добавить “&” перед именем компонента.

Давайте попробуем получить фабричный боб и его идентификатор фабрики свойство:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:factorybean-spring-ctx.xml" })
public class FactoryBeanXmlConfigTest {

    @Resource(name = "&tool")
    private ToolFactory toolFactory;

    @Test
    public void testConstructWorkerByXml() {
        assertThat(toolFactory.getFactoryId(), equalTo(9090));
    }
}

2.3. Используйте FactoryBean С Конфигурацией на Основе Java

Использование FactoryBean с конфигурацией на основе Java немного отличается от конфигурации на основе XML, вы должны явно вызвать метод FactoryBean ‘s GetObject () .

Давайте преобразуем пример в предыдущем подразделе в пример конфигурации на основе Java:

@Configuration
public class FactoryBeanAppConfig {
 
    @Bean(name = "tool")
    public ToolFactory toolFactory() {
        ToolFactory factory = new ToolFactory();
        factory.setFactoryId(7070);
        factory.setToolId(2);
        return factory;
    }

    @Bean
    public Tool tool() throws Exception {
        return toolFactory().getObject();
    }
}

Затем мы проверяем, правильно ли введен объект Tool :

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = FactoryBeanAppConfig.class)
public class FactoryBeanJavaConfigTest {

    @Autowired
    private Tool tool;
 
    @Resource(name = "&tool")
    private ToolFactory toolFactory;

    @Test
    public void testConstructWorkerByJava() {
        assertThat(tool.getId(), equalTo(2));
        assertThat(toolFactory.getFactoryId(), equalTo(7070));
    }
}

Результат теста показывает тот же эффект, что и предыдущий тест конфигурации на основе XML.

3. Способы инициализации

Иногда вам нужно выполнить некоторые операции после установки FactoryBean , но до вызова метода GetObject () , например, проверка свойств.

Этого можно достичь, реализовав интерфейс InitializingBean или используя аннотацию @PostConstruct .

Более подробная информация об использовании этих двух решений была представлена в другой статье: Руководство по запуску логики при запуске весной .

4. AbstractFactoryBean

Spring предоставляет AbstractFactoryBean в качестве простого суперкласса шаблонов для реализаций FactoryBean . С помощью этого базового класса мы теперь можем более удобно реализовать фабричный компонент, который создает одноэлементный или прототипный объект.

Давайте реализуем Single Tool Factory и Non Single Tool Factory , чтобы показать, как использовать AbstractFactoryBean как для одноэлементного, так и для прототипного типа:

public class SingleToolFactory extends AbstractFactoryBean {

    private int factoryId;
    private int toolId;

    @Override
    public Class getObjectType() {
        return Tool.class;
    }

    @Override
    protected Tool createInstance() throws Exception {
        return new Tool(toolId);
    }

    // standard setters and getters
}

А теперь не синглтонная реализация:

public class NonSingleToolFactory extends AbstractFactoryBean {

    private int factoryId;
    private int toolId;

    public NonSingleToolFactory() {
        setSingleton(false);
    }

    @Override
    public Class getObjectType() {
        return Tool.class;
    }

    @Override
    protected Tool createInstance() throws Exception {
        return new Tool(toolId);
    }

    // standard setters and getters
}

Кроме того, XML-конфигурация для этих заводских компонентов:



    
        
        
    

    
        
        
    

Теперь мы можем проверить, вводятся ли свойства объектов Worker , как мы ожидаем:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:factorybean-abstract-spring-ctx.xml" })
public class AbstractFactoryBeanTest {

    @Resource(name = "singleTool")
    private Tool tool1;
 
    @Resource(name = "singleTool")
    private Tool tool2;
 
    @Resource(name = "nonSingleTool")
    private Tool tool3;
 
    @Resource(name = "nonSingleTool")
    private Tool tool4;

    @Test
    public void testSingleToolFactory() {
        assertThat(tool1.getId(), equalTo(1));
        assertTrue(tool1 == tool2);
    }

    @Test
    public void testNonSingleToolFactory() {
        assertThat(tool3.getId(), equalTo(2));
        assertThat(tool4.getId(), equalTo(2));
        assertTrue(tool3 != tool4);
    }
}

Как мы видим из тестов, Single Tool Factory производит одноэлементный объект, а Non Single Tool Factory производит объект-прототип.

Обратите внимание, что нет необходимости устанавливать свойство singleton в Single Tool Factory , потому что в Abstract Factory значение свойства singleton по умолчанию равно true .

5. Заключение

Использование FactoryBean может быть хорошей практикой для инкапсуляции сложной логики построения или упрощения настройки настраиваемых объектов весной.

Итак, в этой статье мы представили основы реализации нашего FactoryBean , как использовать его как в конфигурации на основе XML, так и в конфигурации на основе Java, а также некоторые другие различные аспекты FactoryBean , такие как инициализация FactoryBean и AbstractFactoryBean .

Как всегда, полный источник находится на GitHub .