Spring之FactoryBean

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本身,而是FactoryBeangetObject()方法返回的对象。

例如使用传统的方式配置下面的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")

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容