FactoryBean的使用
一般情況下,Spring 通過反射機(jī)制利用bean 的 class屬性指定實現(xiàn)類來實例化bean瞎疼。在某些情況下水援,實例化 bean 的過程不叫復(fù)雜魄鸦,如果按照傳統(tǒng)的方式宴杀,則需要在<bean>
中提供大量的配置信息,配置的靈活度受限拾因,這時候采用編碼的方式可能會得到一個簡單的方法旺罢。Spring提供了一個org.springframework.bean.FactoryBean的工廠接口,用戶可以通過實現(xiàn)該接口定制實例化的bean绢记。
FactoryBean接口對于Spring框架來說占用重要的地位扁达,Spring本身就提供了特別多的FactoryBean的實現(xiàn)。它們隱藏了實例化復(fù)雜bean的細(xì)節(jié)蠢熄,給上層應(yīng)用帶來了便利跪解。FactoryBean的源碼如下:
public interface FactoryBean<T> {
@Nullable
T getObject() throws Exception;
@Nullable
Class<?> getObjectType();
default boolean isSingleton() {
return true;
}
}
在該接口中定義了三個方法:
-
T getObejct()
: 返回由FactoryBean創(chuàng)建的bean實例,如果isSingleton()返回true签孔,則該實例會放到Spring容器中實例緩存池中叉讥。 -
boolean isSingleton()
:返回有FactoryBean創(chuàng)建的bean的實例的作用域是singleton還是prototype,這里默認(rèn)返回的是true饥追,也就是默認(rèn)是singleton bean图仓。 -
Class<T> getObjectType()
: 返回FactoryBean創(chuàng)建的 bean的類型。
當(dāng)配置文件中<bean>
的class屬性配置實現(xiàn)的是FactoryBean時判耕,通過getBean()方法返回的不是FactoryBean
本身透绩,而是FactoryBean
的getObject()
方法返回的對象翘骂。
例如使用傳統(tǒng)的方式配置下面的Student的<bean>
的時壁熄,Student的每一個屬性都會對應(yīng)一個<property>
元素的標(biāo)簽帚豪。
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的方式實現(xiàn)就更靈活一些,通過下面的逗號分隔符的方式一次性地為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,男" />
當(dāng)調(diào)用getBean("student")
時,Spring通過反射機(jī)制發(fā)現(xiàn)StudentFactoryBean#getObject()
方法的返回昌执。如果希望獲取StudentFactoryBean
的實例烛亦,則需要使用getBean(beanName)
方法時在beanName前顯示的加上 "&" 前綴,例如getBean("&student")
懂拾。