Spring进阶(BeanFactory与ApplicationContext)

前言:

在使用Spring(包括SpringBoot与SpringCloud)做了一些项目之后,总感觉有点机械式的完成任务,为了更好的理解Spring,开始更加深入学习Spring底层实现原理。

BeanFactory:

可以将方法、类在启动Spring之后注册成Bean对象交由Spring管理,这个过程涉及到BeanFactory的相关操作。

BeanFactory能做哪些事:

一般启动SpringBoot项目都需要这样写:

java 复制代码
@SpringBootApplication
public class A01Application {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(A01Application.class, args);
    }
}

使用 SpringApplication.run 方法,其中返回值为 ConfigurableApplicationContext,ConfigurableApplicationContext关系图如下:

发现两个关键点,该接口继承了一个核心接口ApplicationContext,并且ApplicationContext又间接继承了BeanFactory接口,因此可以说ApplicationContext接口是对BeanFactory进行了功能方面的扩展!

因此Spring的核心是BeanFactory!!

当然BeanFactory是一个接口,具体的实现类时则为DefaultListableBeanFactory。

java 复制代码
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable 

当然该实现类不只实现了一个接口,还包括一系列的扩展类和接口,其中注册的Bean默认是单例的,主要是由 DefaultSingletonBeanRegistry类完成注册以及存放

java 复制代码
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);

可以利用反射的原理,将私有成员变量拿出来一探究竟:

java 复制代码
 Field singletonObject = DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
        singletonObject.setAccessible(true);
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        Map<String,Object> map = (Map<String,Object>)singletonObject.get(beanFactory);
        map.forEach((k,v)->{
            System.out.println(k+"="+v);
        });

当然由于SpringApplication容器中初始化之后Bean对象设计的较多,看起来是比较费劲~

ApplicationContext:

接下来需要研究一下ApplicationContext对BeanFactory的扩展:

MessageSource:国际化资源,根据不同的区域提供翻译功能。

java 复制代码
context.getMessage("hi",null, Locale.CHINA);

ResourcePatternResolver:根据通配符匹配多个资源(磁盘路径等)

java 复制代码
context.getResources("classpath:application.properties")

ApplicationEventPublicsher:发布事件

1.创建事件:

java 复制代码
public class UserRegisteredEvent extends ApplicationEvent {

    public UserRegisteredEvent(Object source) {
        super(source);
    }
}

2.发送事件:

java 复制代码
context.publishEvent(new UserRegisteredEvent(context));

3.接收事件:

java 复制代码
@Component
public class Component2 {

    @EventListener
    public void reviver(UserRegisteredEvent event) {
        System.out.println(event);
    }
}

结果如下:

test.a01.UserRegisteredEventsource=org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@2cc3ad05, started on Sun May 17 00:25:57 CST 2026

EnvironmentCapable:读取环境资源(系统资源、yaml等)

java 复制代码
context.getEnvironment().getProperty("JAVA_HOME")
相关推荐
知识搬运临时工6 分钟前
一个模板把 AEM 拖进 Full GC 死亡螺旋:300% CPU、7 GB 堆、310 万行堆栈
java·aws
用户4329359280510 分钟前
CoAP还是MQTT:1万只Cat.1水表三个月带宽续航实测
java
UrbanJazzerati11 分钟前
AutoHotkey v2 零基础快速入门 Part 10:给路线回放添加高精度计时,理解累计延迟与路线一致性
后端
70后写java的老码农15 分钟前
Spring Boot 3 + ShardingSphere-JDBC 实战:一次把读写分离和分库分表跑通
后端
泡海椒18 分钟前
04-饼图评级构成-信用评级构成
后端
知守观20 分钟前
多模块架构演进:横向分层 vs 纵向领域,13 个真实项目的切分对照
java·后端·微服务
时间售卖铺27 分钟前
Oracle DQL精髓:从基础到高级实战
运维·数据库·云原生·oracle
Java成神之路-35 分钟前
Java String 为什么不可变?和 HashMap 到底有什么关系?
java
paopaokaka_luck38 分钟前
基于springboot+vue的益暖微光公益服务平台(DeepSeek公益助手、善款信息追溯、志愿服务积分闭环、ECharts运营分析、活动状态自动流转)
java·前端·javascript·spring boot·mysql·架构·echarts
m0_6399069443 分钟前
MySQL 锁机制详解|表锁、行锁、意向锁,死锁成因与解决方案
数据库·mysql