BeanFactory与factoryBean 区别,请用源码分析,及spring中涉及的点,及应用场景

BeanFactory 和 FactoryBean 都是 Spring 框架中的核心接口,且有着不同的目的和应用场景。我们可以从源码角度分析它们的区别,并探讨它们的作用和应用场景。

1. BeanFactory

BeanFactory 是 Spring 中最基本的容器接口之一。它定义了 Spring 容器的基本操作方法,比如获取 Bean 对象、初始化 Bean 等。

关键方法
复制代码

java

public interface BeanFactory { Object getBean(String name) throws BeansException; Object getBean(String name, Object... args) throws BeansException; boolean containsBean(String name); boolean isSingleton(String name) throws NoSuchBeanDefinitionException; boolean isPrototype(String name) throws NoSuchBeanDefinitionException; }

功能:
  • BeanFactory 负责根据 Bean 的名称和配置来获取 Bean 实例。
  • 它通过 getBean() 方法来从容器中获取 Bean。
  • 它不负责实例化单例 Bean 直到调用 getBean() 时才实例化,所以它是懒加载的(Lazy Initialization)。
适用场景:
  • 在大多数情况下,我们通常使用 ApplicationContext 来代替 BeanFactory,因为 ApplicationContext 是 BeanFactory 的子接口,并且提供了更多的功能(如国际化、事件传播、AOP 等)。
  • 如果你的应用非常轻量,且只需要基础的 Bean 管理功能,可以使用 BeanFactory。

2. FactoryBean

FactoryBean 是 Spring 中的一个接口,它允许开发者控制 Bean 的实例化过程。通过实现 FactoryBean 接口,开发者可以自定义 Bean 的创建逻辑。

关键方法
复制代码

java

public interface FactoryBean<T> { T getObject() throws Exception; Class<?> getObjectType(); boolean isSingleton(); }

功能:
  • getObject():返回一个新的或现有的对象。通过 FactoryBean,你可以创建复杂的 Bean 实例,或者返回非标准的对象类型。
  • getObjectType():返回该 FactoryBean 创建的对象的类型。
  • isSingleton():如果这个 FactoryBean 创建的对象是单例的,则返回 true;否则返回 false。
适用场景:
  • 当你需要自定义 Bean 的创建逻辑时,使用 FactoryBean 是一个非常好的选择。典型的场景包括:
    • 工厂模式:需要动态地创建不同类型的 Bean。
    • 第三方库的适配 :当你需要将第三方库中的某些对象集成到 Spring 容器中时,可以通过 FactoryBean 来封装其创建过程。
    • 动态代理 :如果需要在 Spring 容器中管理动态代理对象,可以通过 FactoryBean 进行创建。

3. BeanFactory 与 FactoryBean 的区别

特性 BeanFactory FactoryBean
目的 管理 Spring 容器中的所有 Bean 自定义 Bean 的创建过程
主要功能 获取 Bean、管理 Bean 生命周期 创建特定的 Bean 实例,控制 Bean 的初始化逻辑
实现方式 通过 getBean() 获取 Bean 通过 getObject() 创建 Bean,通常与工厂模式结合使用
使用场景 基本的 Bean 管理与获取 需要自定义 Bean 创建过程时,或者动态 Bean 的情况
是否懒加载 默认是懒加载(对于单例 Bean) 根据 isSingleton() 的实现来决定 Bean 的生命周期

4. Spring 中的应用场景

4.1 BeanFactory 的应用

BeanFactory 一般在 Spring 中并不直接使用,开发者更多的是使用 ApplicationContext。但是,在一些内存或性能特别敏感的应用场景下,BeanFactory 仍然有它的价值。例如,当你只需要非常简单的 Bean 获取功能时,可以通过 BeanFactory 实现更加轻量的容器。

4.2 FactoryBean 的应用
  • 动态代理对象 :FactoryBean 可以用来创建动态代理。例如,Spring AOP 会使用 FactoryBean 来创建代理对象。
  • 第三方库集成 :某些第三方库的对象可能无法直接作为 Spring Bean 创建。这时可以通过 FactoryBean 来封装这些对象的创建过程,使它们能够被 Spring 容器管理。
  • 复杂 Bean 初始化 :当 Bean 的初始化过程复杂,需要多步处理时,可以使用 FactoryBean 来处理 Bean 的实例化。
示例:FactoryBean 的使用
java 复制代码
public class MyBeanFactory implements FactoryBean<MyBean> {
    
    @Override
    public MyBean getObject() throws Exception {
        return new MyBean();  // 这里是自定义的创建逻辑
    }

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

    @Override
    public boolean isSingleton() {
        return true;  // 如果需要单例,返回 true
    }
}

在配置文件中,使用 FactoryBean 创建 MyBean:

<bean id="myBean" class="com.example.MyBeanFactory"/>

总结:

  • BeanFactory 是 Spring 中最基础的容器接口,负责获取和管理 Bean。
  • FactoryBean 是一个工厂接口,允许你自定义 Bean 的创建逻辑,并将其交给 Spring 管理。
  • 使用 BeanFactory 时你只能获取已经存在的 Bean,而使用 FactoryBean 时可以控制 Bean 的创建过程,适用于复杂的初始化或自定义实例化的场景。

通过理解这两个接口的区别,可以帮助开发者在合适的场景下选择合适的接口和方式来管理 Bean 的生命周期和创建。

实际应用场景

BeanFactory

复制代码
<T> T getBean(String var1, Class<T> var2) throws BeansException;
java 复制代码
        String statuseServiceBeanname = STATE_SERVICE_PRE + stateMachineType;
        IStatusService iStatusService = abstractStateMachineEngine.getApplicationContext().getBean(statuseServiceBeanname, IStatusService.class);

FactoryBean - getObject

java 复制代码
    @Bean(name = "mallSqlSessionFactory")
    public SqlSessionFactory mallSqlSessionFactory(@Qualifier("mallDataSource") DataSource dataSource)
            throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        Interceptor[] plugins =  new Interceptor[]{new PageHelper()};
        bean.setPlugins(plugins);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mybatis/mappers/*.xml"));
        return bean.getObject();
    }
相关推荐
字节渡客10 小时前
Redis键明明过期了,业务还在读到旧数据
数据库·redis·spring
daidaidaiyu10 小时前
ThingsBoard 集群的核心逻辑源码分析
java
我可能是个假开发11 小时前
FTP Unicode 文件名导致 `550` 的问题分析与解决方案
java·开发语言·spring
caoerzhong12 小时前
中小企业上 WMS 该先上哪几块:JeeWMS 开源 Java 仓库管理系统的分批上线清单
java·python·开源
【JAVA】玩家13 小时前
Spring核心原理全解析:从零到生产实战
java·后端·spring
Wang's Blog13 小时前
Java框架 SpringCloud 快速入门: 实现 Feign 最佳实践(抽取方式)
java·spring cloud
MandalaO_O14 小时前
IDEA 开发(快捷键 + 调试 + 序列化)
java·ide·intellij-idea
xiaoqiMikko15 小时前
JVM 线上排查实战(七):jps 看不见它、jstack 连不上它,可它明明活得好好的
java·jvm
狼爷15 小时前
Rust/Go/Java/Python/PHP 大比拼:负载下后端框架到底差多少?
java·后端·编程语言
念何架构之路15 小时前
zap扩展生态与总结
java·前端·数据库