Spring5核心原理-FactoryBean详解

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主要用于实现框架设施。这里有些例子:

  1. 从 JNDI 中查找对象(例如数据源)时,可以使用JndiObjectFactoryBean.
  2. 当使用经典 Spring AOP 为 bean 创建代理时,您可以使用ProxyFactoryBean.
  3. 在 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

(0)
上一篇 2022年4月11日 21:45
下一篇 2022年4月11日 21:46

相关推荐

发表回复

登录后才能评论