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

作者:gcdd1993

来源:https://www.cnblogs.com/gcdd/p/12292360.html

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属性的方法。

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

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>

测试方法:

    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<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:

<?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

发布了41 篇原创文章 · 获赞 8 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/ericxu1116/article/details/104508734