Spring的BeanFactory和FactoryBean

官方定义

  • BeanFactory:Spring Bean容器的根接口
  • FactoryBean:各个对象的工厂接口,如果bean实现了这个接口,它将被用作对象的工厂,而不是直接作为bean实例。

源码解析

BeanFactory

public interface BeanFactory {
    //标注是获取FactoryBean的实现类,而不是调用getObject()获取的实例
    String FACTORY_BEAN_PREFIX = "&";
    Object getBean(String name) throws BeansException;
     T getBean(String name, Class requiredType) throws BeansException;
    Object getBean(String name, Object... args) throws BeansException;
     T getBean(Class requiredType) throws BeansException;
     T getBean(Class requiredType, Object... args) throws BeansException;
    boolean containsBean(String name);
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
    boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
    boolean isTypeMatch(String name, Class typeToMatch) throws NoSuchBeanDefinitionException;
    Class getType(String name) throws NoSuchBeanDefinitionException;
    String[] getAliases(String name);
}

从源码的方法定义上,就可以看出,BeanFactory作为bean的容器管理器,提供了一系列获取bean以及获取bean属性的方法。

写一个小例子试验下:

SimpleBean:

public class SimpleBean {
    public void send() {
        System.out.println("Hello Spring Bean!");
    }
}

Spring配置文件config.xml:



    

测试方法:

    public static void main(String[] args) throws Exception {
        ApplicationContext context = new ClassPathXmlApplicationContext("config.xml");
        BeanFactory beanFactory = context.getAutowireCapableBeanFactory();
        System.out.println("通过名称获取bean");
        SimpleBean simpleBean = (SimpleBean) beanFactory.getBean("simpleBean");
        simpleBean.send();
        System.out.println("通过名称和类型获取bean");
        simpleBean = beanFactory.getBean("simpleBean", SimpleBean.class);
        simpleBean.send();
        System.out.println("通过类型获取bean");
        simpleBean = beanFactory.getBean(SimpleBean.class);
        simpleBean.send();
        boolean containsBean = beanFactory.containsBean("simpleBean");
        System.out.println("是否包含 simpleBean ? " + containsBean);
        boolean singleton = beanFactory.isSingleton("simpleBean");
        System.out.println("是否是单例? " + singleton);
        boolean match = beanFactory.isTypeMatch("simpleBean", ResolvableType.forClass(SimpleBean.class));
        System.out.println("是否是SimpleBean类型 ? " + match);
        match = beanFactory.isTypeMatch("simpleBean", SimpleBean.class);
        System.out.println("是否是SimpleBean类型 ? " + match);
        Class aClass = beanFactory.getType("simpleBean");
        System.out.println("simpleBean 的类型是 " + aClass.getName());
        String[] aliases = beanFactory.getAliases("simpleBean");
        System.out.println("simpleBean 的别名 : " + Arrays.toString(aliases));
    }

控制台结果:

通过名称获取bean
Hello Spring Bean!
通过名称和类型获取bean
Hello Spring Bean!
通过类型获取bean
Hello Spring Bean!
是否包含 simpleBean ? true
是否是单例? true
是否是SimpleBean类型 ? true
是否是SimpleBean类型 ? true
simpleBean 的类型是 base.SimpleBean
simpleBean 的别名 : []

FactoryBean

public interface FactoryBean {
    
    /**
     * 获取一个bean,如果配置了工厂bean,在getBean的时候,将会调用此方法,获取一个bean
     */
    T getObject() throws Exception;

    /**
     * 获取bean的类型
     */
    Class getObjectType();

    /**
     * 是否是单例
     */
    boolean isSingleton();

}

接口是泛型,定义了三个方法,其中getObject()是工厂模式的体现,将会通过此方法返回一个bean的实例。

一个小例子:

public class SimpleBeanFactoryBean implements FactoryBean {
    @Override
    public SimpleBean getObject() throws Exception {
        System.out.println("MyFactoryBean getObject");
        return new SimpleBean();
    }

    @Override
    public Class getObjectType() {
        System.out.println("MyFactoryBean getObjectType");
        return SimpleBean.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}

以上可以修改为单例模式,可以做成线程安全的单例,可塑性较高。

配置文件config.xml:



    

注意,我们在这里只配置了SimpleBeanFactoryBean,并没有配置SimpleBean,接下来看下getBean方法的输出。

ApplicationContext context = new ClassPathXmlApplicationContext("config.xml");
SimpleBean simpleBean = context.getBean(SimpleBean.class);
simpleBean.send();

控制台输出:

MyFactoryBean getObjectType
MyFactoryBean getObject
Hello Spring Bean!

由此我们可以看出FactoryBean的执行流程

  1. 通过getObjectType获取bean的类型
  2. 调用getObject方法获取bean的实例

总结

BeanFactoryFactoryBean其实没有关系,只是名称比较像而已。

  • BeanFactory是IOC最基本的容器,负责生产和管理bean,它为其他具体的IOC容器提供了最基本的规范。
  • FactoryBean是一个接口,当在IOC容器中的Bean实现了FactoryBean后,通过getBean(String BeanName)获取到的Bean对象并不是FactoryBean的实现类对象,而是这个实现类中的getObject()方法返回的对象。要想获取FactoryBean的实现类,就要getBean(&BeanName),在BeanName之前加上&。

你可能感兴趣的:(Spring的BeanFactory和FactoryBean)