FactoryBean 是用作在IoC 容器中创建其他 bean 的工厂bean 。从概念上讲,FactoryBean 与factory method非常相似,但它是 Spring 特定的 bean,可以在 bean 构建过程中被 Spring IoC 容器识别,并且可以被容器用来实例化其他 bean。
使用 FactoryBean 创建 bean
要创建一个工厂 bean,您所要做的就是FactoryBean
通过您的创建者 bean 类实现接口,该类将创建实际的其他 bean。或者为了简单起见,您可以扩展AbstractFactoryBean
类。
通过扩展AbstractFactoryBean
类,您的工厂 bean 可以简单地覆盖createInstance()
创建目标 bean 实例的方法。此外,您必须在getObjectType()
方法中返回目标 bean 的类型才能使自动装配功能正常工作。
public class EmployeeFactoryBean extends AbstractFactoryBean<Object>
{
/This method will be called by container to create new instances
@Override
protected Object createInstance() throws Exception
{
//code
}
//This method is required for autowiring to work correctly
@Override
public Class<EmployeeDTO> getObjectType() {
return EmployeeDTO.class;
}
}
为什么要使用FactoryBean?
FactoryBean主要用于实现框架设施。这里有些例子:
- 从 JNDI 中查找对象(例如数据源)时,可以使用
JndiObjectFactoryBean
. - 当使用经典 Spring AOP 为 bean 创建代理时,您可以使用
ProxyFactoryBean
. - 在 IoC 容器中创建 Hibernate 会话工厂时,可以使用
LocalSessionFactoryBean
.
在大多数情况下,您很少需要编写任何自定义工厂 bean,因为它们是特定于框架的,并且不能在 Spring IoC 容器的范围之外使用。
FactoryBean 演示
在这个例子中,我正在创建一个FactoryBean 来实例化不同类型的Employee
对象,例如它们的manager、director等,并带有一些预填充的属性。
我们的EmployeeDTO
班级是这样的。
public class EmployeeDTO {
private Integer id;
private String firstName;
private String lastName;
private String designation;
//Setters and Getters are hidden behind this comment.
@Override
public String toString() {
return "Employee [id=" + id + ", firstName=" + firstName
+ ", lastName=" + lastName + ", type=" + designation + "]";
}
}
EmployeeFactoryBean
类扩展AbstractFactoryBean
类并实现它的两个方法createInstance()
和getObjectType()
.
import com.howtodoinjava.demo.model.EmployeeDTO;
public class EmployeeFactoryBean extends AbstractFactoryBean<Object>
{
private String designation;
public String getDesignation() {
return designation;
}
public void setDesignation(String designation) {
this.designation = designation;
}
//This method will be called by container to create new instances
@Override
protected Object createInstance() throws Exception
{
EmployeeDTO employee = new EmployeeDTO();
employee.setId(-1);
employee.setFirstName("dummy");
employee.setLastName("dummy");
//Set designation here
employee.setDesignation(designation);
return employee;
}
//This method is required for autowiring to work correctly
@Override
public Class<EmployeeDTO> getObjectType() {
return EmployeeDTO.class;
}
}
您将Employee
在上下文文件中定义各种类型,如下所示。
<bean id="manager" class="com.howtodoinjava.demo.factory.EmployeeFactoryBean">
<property name="designation" value="Manager" />
</bean>
<bean id="director" class="com.howtodoinjava.demo.factory.EmployeeFactoryBean">
<property name="designation" value="Director" />
</bean>
要测试上述FactoryBean,请使用以下代码:
public class TestSpringContext
{
@SuppressWarnings("resource")
public static void main(String[] args)
{
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
EmployeeDTO manager = (EmployeeDTO) context.getBean("manager");
System.out.println(manager);
EmployeeDTO director = (EmployeeDTO) context.getBean("director");
System.out.println(director);
}
}
输出:
Employee [id=-1, firstName=dummy, lastName=dummy, type=Manager]
Employee [id=-1, firstName=dummy, lastName=dummy, type=Director]
如您所见,它EmployeeFactoryBean
使用相同的工厂方法创建了两个不同的员工对象。
获取 FactoryBean 实例本身
如果你想获取EmployeeFactoryBean
它自己的实例,那么你可以在 bean name 之前添加一个“&”。
EmployeeFactoryBean factory = (EmployeeFactoryBean) context.getBean("&director");
System.out.println(factory.getDesignation());
System.out.println(factory.getObjectType());
System.out.println(factory.getObject());
输出:
Director
class com.leftso.demo.model.EmployeeDTO
Employee [id=-1, firstName=dummy, lastName=dummy, type=Director]
原创文章,作者:kepupublish,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/243592.html