深入Spring IOC容器:核心组件与加载流程全解析

一、Spring容器加载全景图

在深入细节之前,先了解Spring容器启动的完整流程:

Spring容器启动加载流程如下图所示:


二、Bean定义(BeanDefinition)的读取与注册

1. BeanDefinition的核心作用

BeanDefinition是Spring容器中描述Bean的元数据对象,它定义了:

  • Bean的类类型(Class)

  • 作用域(Scope)

  • 是否懒加载(LazyInit)

  • 初始化/销毁方法

  • 依赖关系等

复制代码
// BeanDefinition接口关键属性示意
public interface BeanDefinition {
    String getBeanClassName();      // Bean类名
    String getScope();              // 作用域
    boolean isLazyInit();           // 是否懒加载
    String getInitMethodName();     // 初始化方法
    String getDestroyMethodName();  // 销毁方法
    // ... 更多属性
}

2. 三种定义Bean的方式及其统一处理

Spring支持多种方式定义Bean,但最终都会统一为BeanDefinition:

定义方式 示例 对应的解析器
XML配置 <bean class="com.service.UserService" scope="prototype"/> XmlBeanDefinitionReader
注解方式 @Component @Lazy @Scope("prototype") AnnotatedBeanDefinitionReader
Java配置类 @Bean @Scope @Lazy ConfigurationClassPostProcessor

核心设计思想 :无论哪种定义方式,最终都转换为统一的BeanDefinition对象,后续的Bean创建流程完全一致。

3. BeanDefinition读取器(BeanDefinitionReader)

Spring提供了多种读取器,用于将不同配置转换为BeanDefinition:

3.1 AnnotatedBeanDefinitionReader
复制代码
// 直接将类转换为BeanDefinition,解析类上的注解
AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(context);
reader.register(UserService.class);  // 解析@Conditional、@Scope、@Lazy等注解

支持的注解@Conditional, @Scope, @Lazy, @Primary, @DependsOn, @Role, @Description

3.2 XmlBeanDefinitionReader
复制代码
// 解析XML中的<bean>标签
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(context);
int count = reader.loadBeanDefinitions("spring.xml");  // 返回加载的Bean数量
3.3 ClassPathBeanDefinitionScanner
复制代码
// 扫描包路径,将带有@Component等注解的类转换为BeanDefinition
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(beanFactory);
scanner.scan("com.service");  // 扫描指定包

4. 编程式注册BeanDefinition

除了声明式配置,还可以编程式创建BeanDefinition:

复制代码
// 1. 创建BeanDefinition构建器
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder
    .genericBeanDefinition()
    .getBeanDefinition();

// 2. 设置Bean属性
beanDefinition.setBeanClass(UserService.class);
beanDefinition.setScope("prototype");
beanDefinition.setLazyInit(true);
beanDefinition.setInitMethodName("init");

// 3. 注册到容器
context.registerBeanDefinition("userService", beanDefinition);

5. 元数据读取器(MetadataReader)

Spring使用ASM技术读取类元数据,避免过早加载类到JVM:

复制代码
SimpleMetadataReaderFactory factory = new SimpleMetadataReaderFactory();
MetadataReader reader = factory.getMetadataReader("com.service.UserService");

// 获取类信息
ClassMetadata classMetadata = reader.getClassMetadata();
System.out.println(classMetadata.getClassName());  // com.service.UserService

// 获取注解信息
AnnotationMetadata annotationMetadata = reader.getAnnotationMetadata();
Set<String> annotationTypes = annotationMetadata.getAnnotationTypes();  // 所有注解

使用ASM的原因:启动时扫描大量类,如果全部加载到JVM会消耗大量内存,ASM可以直接读取字节码获取元数据。


三、BeanFactory:Spring容器的基础

1. BeanFactory与ApplicationContext的关系

复制代码
// ApplicationContext继承关系
public interface ApplicationContext extends 
    EnvironmentCapable, 
    ListableBeanFactory, 
    HierarchicalBeanFactory,
    MessageSource, 
    ApplicationEventPublisher, 
    ResourcePatternResolver {
    // ...
}

关键理解

  • ApplicationContextBeanFactory的子接口,具有更多高级功能

  • 实际创建ApplicationContext时,底层会创建DefaultListableBeanFactory

  • getBean()等方法实际委托给内部的BeanFactory执行

2. DefaultListableBeanFactory:功能最全的实现

DefaultListableBeanFactory是Spring中最重要、功能最全的BeanFactory实现:

复制代码
// 直接使用DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

// 注册BeanDefinition
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder
    .genericBeanDefinition(User.class)
    .getBeanDefinition();
beanFactory.registerBeanDefinition("user", beanDefinition);

// 获取Bean
User user = (User) beanFactory.getBean("user");

3. DefaultListableBeanFactory的多重功能

通过继承多个接口,DefaultListableBeanFactory拥有丰富功能:

接口 功能说明 典型用途
AliasRegistry 别名注册 一个Bean可以有多个名称
BeanDefinitionRegistry BeanDefinition注册 存储所有Bean定义
SingletonBeanRegistry 单例注册 管理单例Bean缓存
ListableBeanFactory Bean列表查询 获取所有Bean名称
HierarchicalBeanFactory 层级工厂 支持父子容器
ConfigurableBeanFactory 可配置工厂 添加后置处理器等
AutowireCapableBeanFactory 自动装配 支持@Autowired等

四、ApplicationContext:全功能的容器

1. ApplicationContext的核心优势

相比基本的BeanFactory,ApplicationContext提供了更丰富的企业级功能:

复制代码
// ApplicationContext = BeanFactory + 额外服务
AnnotationConfigApplicationContext context = 
    new AnnotationConfigApplicationContext(AppConfig.class);

// 1. BeanFactory基础功能
UserService userService = context.getBean(UserService.class);

// 2. 国际化支持
String message = context.getMessage("test", null, Locale.CHINA);

// 3. 资源加载
Resource resource = context.getResource("classpath:app.properties");

// 4. 环境变量访问
String value = context.getEnvironment().getProperty("app.name");

// 5. 事件发布
context.publishEvent(new CustomEvent(this));

2. 主要实现类对比

实现类 特点 适用场景
AnnotationConfigApplicationContext 基于注解配置,功能最全 Spring Boot、纯注解项目
ClassPathXmlApplicationContext 基于XML配置 传统XML配置项目
XmlWebApplicationContext Web环境专用 Spring MVC项目

3. 继承关系解析

复制代码
// AnnotationConfigApplicationContext的完整继承链
AnnotationConfigApplicationContext
    extends GenericApplicationContext        // 拥有BeanDefinition注册能力
    implements AnnotationConfigRegistry      // 支持@Configuration、@Bean
    
GenericApplicationContext
    extends AbstractApplicationContext       // 实现了容器生命周期管理
    implements BeanDefinitionRegistry        // BeanDefinition注册接口
    
AbstractApplicationContext
    implements ConfigurableApplicationContext // 可配置的ApplicationContext

五、Bean生命周期中的关键处理器

1. BeanPostProcessor:Bean的后置处理器

在Bean初始化前后插入自定义逻辑:

复制代码
@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
    
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        if ("userService".equals(beanName)) {
            System.out.println("初始化前:" + beanName);
            // 可以修改或包装Bean
        }
        return bean;
    }
    
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        if ("userService".equals(beanName)) {
            System.out.println("初始化后:" + beanName);
            // 可以创建代理对象
        }
        return bean;
    }
}

应用场景

  • AOP代理创建(AnnotationAwareAspectJAutoProxyCreator

  • @Autowired注解处理(AutowiredAnnotationBeanPostProcessor

  • @PostConstruct注解处理(InitDestroyAnnotationBeanPostProcessor

2. BeanFactoryPostProcessor:Bean工厂的后置处理器

在BeanFactory标准初始化之后、Bean实例化之前修改BeanDefinition:

复制代码
@Component
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        System.out.println("加工BeanFactory");
        
        // 获取并修改BeanDefinition
        BeanDefinition bd = beanFactory.getBeanDefinition("userService");
        bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
        bd.setLazyInit(true);
    }
}

应用场景

  • 属性占位符解析(PropertySourcesPlaceholderConfigurer

  • 配置类处理(ConfigurationClassPostProcessor

  • 自定义BeanDefinition修改

3. FactoryBean:自定义Bean创建

完全控制Bean的创建过程:

复制代码
@Component
public class CustomFactoryBean implements FactoryBean<UserService> {
    
    @Override
    public UserService getObject() throws Exception {
        UserService userService = new UserService();
        // 完全自定义创建逻辑
        userService.setCustomProperty("custom");
        return userService;
    }
    
    @Override
    public Class<?> getObjectType() {
        return UserService.class;
    }
    
    @Override
    public boolean isSingleton() {
        return true;
    }
}

FactoryBean vs @Bean

  • FactoryBean:只经过初始化后阶段,跳过依赖注入等标准生命周期

  • @Bean:经过完整的Bean生命周期


六、扫描过滤器:精准控制Bean注册

1. 排除过滤器(ExcludeFilter)

复制代码
@ComponentScan(
    value = "com.service",
    excludeFilters = @ComponentScan.Filter(
        type = FilterType.ASSIGNABLE_TYPE,
        classes = UserService.class  // 排除UserService类
    )
)
public class AppConfig {
}

2. 包含过滤器(IncludeFilter)

复制代码
@ComponentScan(
    value = "com.service",
    includeFilters = @ComponentScan.Filter(
        type = FilterType.ANNOTATION,
        classes = CustomAnnotation.class  // 只包含带有CustomAnnotation的类
    ),
    useDefaultFilters = false  // 关闭默认的@Component扫描
)
public class AppConfig {
}

3. 过滤器类型(FilterType)

类型 说明 示例
ANNOTATION 基于注解过滤 @Controller, @Service
ASSIGNABLE_TYPE 基于类/接口过滤 UserService.class
ASPECTJ AspectJ表达式 execution(* com.service..*.*(..))
REGEX 正则表达式 .*Service
CUSTOM 自定义过滤器 实现TypeFilter接口

默认行为 :Spring扫描时会自动添加AnnotationTypeFilter,扫描所有带有@Component注解的类。


七、ApplicationContext的高级特性

1. 国际化支持(MessageSource)

复制代码
// 1. 定义MessageSource Bean
@Bean
public MessageSource messageSource() {
    ResourceBundleMessageSource source = new ResourceBundleMessageSource();
    source.setBasename("messages");  // 基于messages.properties
    source.setDefaultEncoding("UTF-8");
    return source;
}

// 2. 使用国际化
String message = context.getMessage(
    "welcome.message",      // 消息键
    new Object[]{"John"},   // 参数
    Locale.CHINA            // 区域
);

2. 资源加载(ResourceLoader)

复制代码
// 加载各种资源
Resource fileResource = context.getResource("file://D:/app/config.properties");
Resource classpathResource = context.getResource("classpath:application.yml");
Resource urlResource = context.getResource("https://example.com/config.json");
Resource patternResource = context.getResources("classpath:com/service/*.class");

// 获取资源信息
System.out.println(resource.exists());
System.out.println(resource.contentLength());
System.out.println(resource.getFilename());

3. 环境变量访问(Environment)

复制代码
// 获取系统环境变量和JVM属性
Map<String, Object> envVars = context.getEnvironment().getSystemEnvironment();
Map<String, Object> sysProps = context.getEnvironment().getSystemProperties();

// 获取自定义属性
String appName = context.getEnvironment().getProperty("app.name");

// 添加自定义属性源
@PropertySource("classpath:application.properties")
public class AppConfig {
    // 会自动加载到Environment中
}

4. 事件发布机制(ApplicationEventPublisher)

复制代码
// 1. 定义自定义事件
public class CustomEvent extends ApplicationEvent {
    private String message;
    
    public CustomEvent(Object source, String message) {
        super(source);
        this.message = message;
    }
    // getter...
}

// 2. 监听事件
@Component
public class CustomEventListener implements ApplicationListener<CustomEvent> {
    @Override
    public void onApplicationEvent(CustomEvent event) {
        System.out.println("收到事件: " + event.getMessage());
    }
}

// 3. 发布事件
context.publishEvent(new CustomEvent(this, "Hello Event!"));

八、总结:Spring容器的核心设计思想

1. 统一抽象:BeanDefinition

无论何种配置方式,最终都抽象为BeanDefinition,实现创建流程的统一。

2. 职责分离:BeanFactory与ApplicationContext

  • BeanFactory:基础容器,负责Bean的创建和管理

  • ApplicationContext:高级容器,集成企业级功能

3. 扩展性:Processor机制

通过BeanPostProcessorBeanFactoryPostProcessor,提供强大的扩展点。

4. 灵活性:多种配置方式

支持XML、注解、Java配置等多种方式,适应不同项目需求。

5. 企业级支持:国际化、事件、资源等

超越单纯的依赖注入容器,提供完整的企业级应用支持。


九、学习建议与资源

学习路径建议:

  1. 理解基本概念:BeanDefinition、BeanFactory、ApplicationContext

  2. 掌握生命周期:Bean创建、初始化、销毁的全过程

  3. 熟悉扩展机制:各种Processor的工作原理

  4. 实践高级特性:事件、国际化、资源加载等

相关推荐
+VX:Fegn089530 分钟前
计算机毕业设计|基于springboot + vue律师咨询系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·课程设计
daidaidaiyu40 分钟前
一文学习和实践 当下互联网安全的基石 - TLS 和 SSL
java·netty
hssfscv1 小时前
Javaweb学习笔记——后端实战2_部门管理
java·笔记·学习
NE_STOP1 小时前
认识shiro
java
kong79069281 小时前
Java基础-Lambda表达式、Java链式编程
java·开发语言·lambda表达式
liangsheng_g1 小时前
泛型新认知
java·序列化·泛型
液态不合群1 小时前
【面试题】MySQL 三层 B+ 树能存多少数据?
java·数据库·mysql
李坤林2 小时前
Android Binder 详解(4) Binder 线程池
android·java·binder
代码方舟2 小时前
Java后端实战:构建基于天远手机号码归属地核验的金融级风控模块
java·大数据·开发语言·金融
困知勉行19852 小时前
springboot整合redis
java·spring boot·redis