面试官:“Spring中的BeanFactory和FactoryBean的区别是什么?”

BeanFactory和FactoryBean是Spring框架中名字相似但功能完全不同的两个核心接口,也是面试高频题之一。很多开发者容易混淆它们的作用,甚至误以为两者是“父子关系”。本文从源码层面解析两者的设计差异,并结合实际场景说明它们的用途,帮你彻底理清这两个概念!


一、BeanFactory:Spring的“大管家”

1. 核心职责

BeanFactory是Spring容器的根接口,负责管理所有Bean的生命周期依赖关系。它是Spring IOC(控制反转)的核心实现,提供了以下能力:

  • 创建Bean:根据配置或注解实例化Bean。

  • 管理Bean:存储Bean定义(BeanDefinition)和Bean实例。

  • 获取Bean:通过getBean()方法从容器中获取Bean。

2. 源码解析

BeanFactory接口定义了一系列基础方法,核心代码如下:

public interface BeanFactory {
    // 根据名称获取Bean实例
    Object getBean(String name) throws BeansException;
    // 判断Bean是否存在
    boolean containsBean(String name);
    // 获取Bean的类型
    Class<?> getType(String name) throws NoSuchBeanDefinitionException;
    // 其他方法...
}

常见实现类

  • DefaultListableBeanFactory:Spring默认的Bean工厂实现。

  • ApplicationContext(应用上下文):在BeanFactory基础上扩展了更多功能(如国际化、事件发布)。


二、FactoryBean:自定义Bean的“工厂”

1. 核心职责

FactoryBean是一个特殊的Bean接口,用于定制复杂对象的创建逻辑。当某个Bean的创建过程无法通过简单配置完成时(例如需要动态生成代理对象、连接外部资源等),可以通过实现FactoryBean接口来自定义生成逻辑。

2. 源码解析

FactoryBean接口定义了三个核心方法:

public interface FactoryBean<T> {
    // 返回实际需要的Bean实例
    T getObject() throws Exception;
    // 返回Bean的类型
    Class<?> getObjectType();
    // 是否是单例
    boolean isSingleton();
}

关键点

  • 当从BeanFactory中获取FactoryBean类型的Bean时,实际返回的是getObject()方法生成的实例。

  • 如果想获取FactoryBean本身,需要在Bean名称前加&符号(例如&myFactoryBean)。


三、BeanFactory vs FactoryBean:本质区别

对比项BeanFactoryFactoryBean
角色Spring容器的核心接口,管理所有Bean。一个特殊的Bean,用于自定义其他Bean的创建。
功能Bean的创建、存储、管理。定制单个Bean的创建逻辑。
使用场景所有Bean的通用管理。复杂对象创建(如MyBatis的SqlSessionFactory)。
获取方式直接通过getBean("beanName")获取Bean。通过getBean("&factoryBeanName")获取FactoryBean本身。

四、通过源码看FactoryBean的工作流程

假设有一个FactoryBean实现类MyFactoryBean

public class MyFactoryBean implements FactoryBean<User> {
    @Override
    public User getObject() {
        return new User("Spring");  // 自定义创建User对象
    }

    @Override
    public Class<?> getObjectType() {
        return User.class;
    }
}

1. 注册FactoryBean到容器

在Spring配置中声明:

<bean id="userFactory" class="com.example.MyFactoryBean"/>

2. 获取Bean的流程

  • 获取User实例:调用getBean("userFactory")时,Spring会调用MyFactoryBean.getObject(),返回User对象。

  • 获取FactoryBean本身:调用getBean("&userFactory"),返回MyFactoryBean实例。

源码逻辑
AbstractBeanFactory中,通过getObjectForBeanInstance方法判断是否为FactoryBean:

protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName) {
    // 如果name以"&"开头,直接返回FactoryBean本身
    if (BeanFactoryUtils.isFactoryDereference(name)) {
        return beanInstance;
    }
    // 否则返回FactoryBean创建的Bean
    if (beanInstance instanceof FactoryBean) {
        return getObjectFromFactoryBean((FactoryBean<?>) beanInstance, name, beanName);
    }
    return beanInstance;
}

五、实际应用场景

场景1:动态代理对象生成

Spring的ProxyFactoryBean用于创建AOP代理对象。例如:

<bean id="userServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="target" ref="userService"/>
    <property name="interceptorNames">
        <list>
            <value>myInterceptor</value>
        </list>
    </property>
</bean>

运行 HTML

  • 通过userServiceProxy获取的是代理对象,而非ProxyFactoryBean本身。

场景2:集成第三方框架

MyBatis的SqlSessionFactoryBean是一个典型的FactoryBean,用于创建SqlSessionFactory

@Bean
public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) {
    SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
    factoryBean.setDataSource(dataSource);
    return factoryBean;
}
  • Spring容器中实际存储的是SqlSessionFactory实例,而非SqlSessionFactoryBean


六、常见问题与避坑指南

问题1:为什么获取FactoryBean时得到的是它创建的对象?

答案:Spring的设计规定,默认返回FactoryBean.getObject()的结果。若需获取FactoryBean本身,需在Bean名称前加&

问题2:FactoryBean和@Bean注解有什么区别?

答案

  • @Bean注解用于配置类中定义Bean,创建逻辑由Spring处理。

  • FactoryBean用于更复杂的创建逻辑(如条件判断、动态生成)。

问题3:FactoryBean能否依赖其他Bean?

答案:可以!FactoryBean本身是一个Bean,可以注入其他依赖,例如:

public class MyFactoryBean implements FactoryBean<User> {
    @Autowired
    private Environment env;

    @Override
    public User getObject() {
        // 使用env配置信息创建User
        return new User(env.getProperty("user.name"));
    }
}

七、总结

  • BeanFactory:Spring容器的“大管家”,负责所有Bean的管理。

  • FactoryBean:一个“特殊员工”,负责定制某些Bean的创建过程。

  • 核心区别:BeanFactory是容器级接口,FactoryBean是Bean级接口。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

孙悟饭Z

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值