FactoryBean的使用
一般情况下,Spring 通过反射机制利用bean 的 class属性指定实现类来实例化bean。在某些情况下,实例化 bean 的过程不叫复杂,如果按照传统的方式,则需要在<bean>
中提供大量的配置信息,配置的灵活度受限,这时候采用编码的方式可能会得到一个简单的方法。Spring提供了一个org.springframework.bean.FactoryBean的工厂接口,用户可以通过实现该接口定制实例化的bean。
FactoryBean接口对于Spring框架来说占用重要的地位,Spring本身就提供了特别多的FactoryBean的实现。它们隐藏了实例化复杂bean的细节,给上层应用带来了便利。FactoryBean的源码如下:
public interface FactoryBean<T> {
@Nullable
T getObject() throws Exception;
@Nullable
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}
在该接口中定义了三个方法:
-
T getObejct()
: 返回由FactoryBean创建的bean实例,如果isSingleton()返回true,则该实例会放到Spring容器中实例缓存池中。 -
boolean isSingleton()
:返回有FactoryBean创建的bean的实例的作用域是singleton还是prototype,这里默认返回的是true,也就是默认是singleton bean。 -
Class<T> getObjectType()
: 返回FactoryBean创建的 bean的类型。
当配置文件中<bean>
的class属性配置实现的是FactoryBean时,通过getBean()方法返回的不是FactoryBean
本身,而是FactoryBean
的getObject()
方法返回的对象。
例如使用传统的方式配置下面的Student的<bean>
的时,Student的每一个属性都会对应一个<property>
元素的标签。
public class Student {
private String sid;
private String name;
private String clazz;
private char sex;
public String getSid() {
return sid;
}
public void setSid(String sid) {
this.sid = sid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getClazz() {
return clazz;
}
public void setClazz(String clazz) {
this.clazz = clazz;
}
public char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
@Override
public String toString() {
return "Student{" +
"sid='" + sid + '\'' +
", name='" + name + '\'' +
", clazz='" + clazz + '\'' +
", sex=" + sex +
'}';
}
}
如果使用FactoryBean的方式实现就更灵活一些,通过下面的逗号分隔符的方式一次性地为Student的所有属性指定配置值:
public class StudentFactoryBean implements FactoryBean<Student> {
private String studentInfo;
@Override
public Student getObject() throws Exception {
Student student = new Student();
String[] infos = studentInfo.split(",");
student.setSid(infos[0]);
student.setName(infos[1]);
student.setClazz(infos[2]);
student.setSex(infos[3].charAt(0));
return student;
}
@Override
public Class<?> getObjectType() {
return Student.class;
}
public String getStudentInfo() {
return studentInfo;
}
public void setStudentInfo(String studentInfo) {
this.studentInfo = studentInfo;
}
}
有了这一个StudentFactoryBean后,就可以在配置文件中使用下面的这种方法配置StudentBean了。
<bean id="student" class="top.mcwebsite.bean.StudentFactoryBean"
p:studentInfo="04161000,张三,计科1901,男" />
当调用getBean("student")
时,Spring通过反射机制发现StudentFactoryBean#getObject()
方法的返回。如果希望获取StudentFactoryBean
的实例,则需要使用getBean(beanName)
方法时在beanName前显示的加上 "&" 前缀,例如getBean("&student")
。