为什么我们写的Spring,几乎都在用ApplicationContext?

图片

故事场景:购买你的座驾

BeanFactory — “高性能发动机套件”

BeanFactory 就像一个高性能的发动机核心套件

  • • 你得到的是什么:
    你从工厂订购了一套“引擎核心”(BeanFactory)。你得到的是一个箱子,里面装着引擎、活塞、变速器等最核心的部件。它具备了驱动汽车所需的一切基本能力(Bean的实例化和依赖注入)。

  • • 它的特点 (懒加载):
    这个引擎套件送到你家车库时,它并不会自动点火启动。它只是静静地待在那里。只有当你第一次坐进驾驶舱,拧动点火钥匙的那一刻(调用getBean()),引擎才会“轰”的一声被组装并启动起来。

  • • 它缺少什么:
    它只有引擎。没有车身、没有轮胎、没有空调(AOP)、没有导航系统(国际化)、没有车载音响(事件发布)。你只有最核心的动力单元,如果你想把它变成一辆能开上路的车,你得自己动手去整合所有其他部件。

  • • 谁会用它?
    只有那些资源极其有限(比如在内存极小的嵌入式设备上)或者需要极致启动速度的“骨灰级玩家”,才会选择从一个引擎套件开始构建。

ApplicationContext — “出厂即顶配的豪华轿车”

ApplicationContext 则是一辆从工厂里直接开出来的、功能完备的豪华轿车

  • • 你得到的是什么:
    你订购了一辆“豪华轿车”。这辆车的核心,正是那款高性能引擎(ApplicationContext 继承了 BeanFactory),但工厂已经为它装配好了一切。

  • • 它的特点 (饿汉式加载):
    当这辆车被交付到你家门口时(Spring容器启动时),工厂已经对它进行了全面的质检。引擎早已点火预热,所有系统都已经自检完毕,随时可以出发。这确保了你一上车就能立刻开走,并且所有潜在的装配问题都在出厂前就已暴露并解决了。

  • • 它多了什么?(核心区别)
    除了强大的引擎 (BeanFactory 的功能) 之外,这辆“豪华轿车”还配备了:

    • • 智能悬挂系统 (AOP): 能根据路况自动调整,提供平稳的驾乘体验。

    • • 多语言导航系统 (国际化): 能用不同语言为你指路。

    • • 行车警报系统 (事件发布): 轮胎气压低、油量不足时会自动提醒你。

    • • 后备箱和储物格 (资源加载): 可以方便地存取地图、工具等各种资源。

故事总结:

特性

BeanFactory

 (发动机套件)

ApplicationContext

 (豪华整车)

本质关系核心/基础扩展/高级

 (ApplicationContext is-a BeanFactory)

加载策略懒加载

 (第一次用才启动)

饿汉式加载

 (出厂时就已启动)

功能集基础

 (只有Bean管理)

全面

 (Bean管理 + AOP, I18N, 事件等)

核心比喻只提供最核心的引擎提供一辆功能完备的汽车
一句话总结我是Spring的心脏,但只是个零件。我是Spring的完整形态,拿来就能开。

结论与现代实践:
在任何现代的Spring应用(尤其是Spring Boot)中,我们几乎总是与ApplicationContext打交道BeanFactory更多的是作为底层的基础设施存在。ApplicationContext提供的“开箱即用”的丰富功能和“启动时故障检测”的饿汉式加载模式,对于构建复杂的企业级应用来说,是不可或缺的。

技术解析与代码示例

核心关系:继承与扩展

ApplicationContext 继承自 BeanFactory 接口。你可以把 ApplicationContext 看作是 BeanFactory 的一个“超集”或“加强版”。它包含了 BeanFactory 的所有功能,并在此基础上提供了大量额外的企业级特性。

特性

BeanFactoryApplicationContext
本质

Spring IoC容器的根接口,最基础的容器。

BeanFactory

子接口,功能更全面的容器。

Bean加载懒加载 (Lazy)

:默认情况下,Bean在第一次被调用 (getBean()) 时才被创建。

饿汉式 (Eager)

:默认情况下,容器启动时就创建所有单例Bean。

提供功能

基础的Bean生命周期管理、依赖注入。

包含BeanFactory所有功能,并额外提供:AOP集成、国际化、事件发布、资源加载等。

代码示例:懒加载 vs 饿汉式

我们将通过代码直观地看到这两种加载策略的区别。

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

// 一个简单的Bean,它的构造函数会打印信息,以便我们观察创建时机
class MyBean {
    public MyBean() {
        System.out.println(">>> MyBean object has been created!");
    }
}

// Spring的配置类
@Configuration
class AppConfig {
    @Bean
    public MyBean myBean() {
        return new MyBean();
    }
}


public class FactoryVsContextDemo {
    public static void main(String[] args) {
        System.out.println("--- 1. 演示 ApplicationContext (饿汉式加载) ---");
        // 1. 创建 ApplicationContext 容器
        //    注意观察控制台输出!
        System.out.println("Context is about to be created.");
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        System.out.println("Context has been created.");
        // **你会发现,"MyBean object has been created!" 在这里已经被打印出来了!**
        // **这证明了 ApplicationContext 在启动时就 eagerly 创建了所有单例Bean。**

        System.out.println("Now, let's get the bean...");
        MyBean beanFromContext = context.getBean(MyBean.class);
        System.out.println("Got bean from context: " + beanFromContext);


        System.out.println("\n" + "---".repeat(20) + "\n");
        

        // BeanFactory 接口没有直接的注解实现类,通常我们使用其实现,但其行为是懒加载
        // 为了方便,我们知道 ApplicationContext 本身就是一个 BeanFactory
        System.out.println("--- 2. 演示 BeanFactory 的概念 (懒加载) ---");
        System.out.println("ApplicationContext is also a BeanFactory.");
        BeanFactory factory = context; // 向上转型
        
        // 假如我们有一个真正的、纯粹的 BeanFactory 实现(如 XmlBeanFactory,但已废弃),
        // 那么 Bean 的创建会延迟到 getBean() 调用时。
        // ApplicationContext 默认行为是饿汉式,但我们可以通过注解 @Lazy 来模拟懒加载
        System.out.println("For a lazy-loaded bean (or a pure BeanFactory), the creation happens only when you call getBean().");
        System.out.println("Since our context already created the bean, getting it again won't re-create it.");
        MyBean beanFromFactory = factory.getBean(MyBean.class);
        System.out.println("Got bean from factory: " + beanFromFactory);
    }
}

代码结论:

  • • ApplicationContext 在new AnnotationConfigApplicationContext(AppConfig.class)这一行执行时,就会立即创建MyBean的实例。

  • • BeanFactory 的核心思想(懒加载)是在调用getBean()才去创建MyBean的实例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

java干货

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

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

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

打赏作者

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

抵扣说明:

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

余额充值