Spring的BeanFactory和FactoryBean,傻傻分不清楚?!

做者:gcdd1993 来源:http://www.javashuo.com/article/p-ahaojrud-bv.htmlhtml

1. 官方定义

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

2. 源码解析

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

写一个小例子试验下: SimpleBean:spring

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

Spring配置文件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="simpleBean" class="base.SimpleBeanFactoryBean"/>
</beans>

测试方法:yii

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

控制台结果:ide

经过名称获取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的实例。学习

一个小例子:测试

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

以上能够修改成单例模式,能够作成线程安全的单例,可塑性较高。网站

配置文件config.xml:ui

<?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的实例

3. 总结

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

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

file

欢迎关注个人公众号::一点教程。得到独家整理的学习资源和平常干货推送。 若是您对个人系列教程感兴趣,也能够关注个人网站:yiidian.com

相关文章
相关标签/搜索