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> T getBean(String name, Class<T> requiredType) throws BeansException;
    Object getBean(String name, Object... args) throws BeansException;
    <T> T getBean(Class<T> requiredType) throws BeansException;
    <T> T getBean(Class<T> 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屬性的方法。java

寫一個小例子試驗下:spring

SimpleBean:安全

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

Spring配置文件config.xml:ide

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context.xsd">
    <bean id="simpleBean" class="base.SimpleBeanFactoryBean"/>
</beans>

測試方法:測試

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));
    }

控制檯結果:ui

經過名稱獲取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<T> {
    
    /**
     * 獲取一個bean,若是配置了工廠bean,在getBean的時候,將會調用此方法,獲取一個bean
     */
    T getObject() throws Exception;

    /**
     * 獲取bean的類型
     */
    Class<?> getObjectType();

    /**
     * 是不是單例
     */
    boolean isSingleton();

}

接口是泛型,定義了三個方法,其中getObject()是工廠模式的體現,將會經過此方法返回一個bean的實例。線程

一個小例子:code

public class SimpleBeanFactoryBean implements FactoryBean<SimpleBean> {
    @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;
    }
}

以上能夠修改成單例模式,能夠作成線程安全的單例,可塑性較高。xml

配置文件config.xml:對象

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                        http://www.springframework.org/schema/beans/spring-beans.xsd
                        http://www.springframework.org/schema/context
                        http://www.springframework.org/schema/context/spring-context.xsd">
    <bean id="simple" class="base.SimpleBeanFactoryBean"/>
</beans>

注意,咱們在這裏只配置了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以前加上&。
相關文章
相關標籤/搜索