Spring Bean容器中有两者类型bean:普通bean和工厂bean。前者Spring直接使用,而后者能产生被框架管理的对象。我们可以实现org.springframework.beans.factory.FactoryBean 接口构建工厂bean。
1. 基本工厂bean
2.1 实现FactoryBean
首先看FactoryBean接口定义:
public interface FactoryBean {
T getObject() throws Exception;
Class<?> getObjectType();
boolean isSingleton();
}
- getObject() – 返回工厂创建的对象,可以被Spring容器使用的对象。
- getObjectType() – 返回工厂创建对象的类型
- isSingleton() – 返回工厂创建对象是否为单例对象
现在实现一个示例,创建ToolFactory类负责创建Tool类型对象:
public class Tool {
private int id;
// standard constructors, getters and setters
}
ToolFactory类:
public class ToolFactory implements FactoryBean<Tool> {
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
}
ToolFactory 实现了 FactoryBean接口,负责创建Tool对象。
1.2 基于Java Configuration使用FactoryBean
当然也可以基于xml,这里使用java 方式配置,需要显示调用getObject()方法。
@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));
}
}
为了访问FactoryBean,需要在bean名称前面增加&符号。
有时需要在FactoryBean创建之后、getObject方法执行之前执行一些属性操作,如属性检查。可以实现InitializingBean 接口或使用 @PostConstruct 注解.
2. 抽象工厂bean
Spring还提供了AbstractFactoryBean,作为FactoryBean实现的简单模板超类。使用这个基类可以更方便实现工厂bean,创建单例或原型对象。
下面示例展示如何使用AbstractFactoryBean创建单例或原型对象。
public class SingleToolFactory extends AbstractFactoryBean<Tool> {
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
}
AbstractFactoryBean默认singleton属性为true,即单例方式。
下面创建非单例工厂类:
public class NonSingleToolFactory extends AbstractFactoryBean<Tool> {
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
}
配置工厂bean,Java方式于上面一致,这里使用xml方式:
<beans ...>
<bean id="singleTool" class="com.baeldung.factorybean.SingleToolFactory">
<property name="factoryId" value="3001"/>
<property name="toolId" value="1"/>
</bean>
<bean id="nonSingleTool" class="com.baeldung.factorybean.NonSingleToolFactory">
<property name="factoryId" value="3002"/>
<property name="toolId" value="2"/>
</bean>
</beans>
现在测试被注入的对象是否于期望一致:
@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);
}
}
从上面测试结果看,SingleToolFactory 产生单例对象, NonSingleToolFactory 产生原型对象.
3. 总结
使用FactoryBean封装复杂的构造逻辑非常方便。本文介绍了如何实现并配置FactoryBean,包括FactoryBean 和 AbstractFactoryBean。
本文参考链接:https://blog.csdn.net/neweastsun/article/details/115361419