IoC容器加载流程
流程主要分为两个阶段:
- Bean的配置解析阶段:将Bean的配置信息转换成BeanDefinition
- Bean的创建阶段:根据BeanDefinition进行Bean创建
1. 加载流程
1.1 配置解析
加载流程:
- 资源文件定位:一般是在ApplicationContext的实现类里完成的,ResourceLoader接口的getResource()方法,可以将外部的资源,读取为Resource类
- 加载配置文件:通过BeanDefinitionReader读取配置文件或配置类
- 注解扫描:根据ComonentScan注解的路径进行扫描,未指明时会从声明这个注解的配置类所在包以及其子包进行扫描,读取@Bean、@Component、@Service等Bean声明注解
- 解析注册BeanDefinition:针对扫描出来的bean信息进行解析,生成的对象注册到BeanDefinitionRegistry中(BeanDefinitionRegistry是一个接口,提供了向IoC容器中注册BeanDefinition的方法)
1.2 Bean创建
IoC容器中的bean默认为延迟加载只有在需要使用时才会被实例化。这个过程是通过Bean的getBean方法实现的。
创建流程:
- 配置读取:根据Bean的名称或类型查找BeanDefinition;
- Bean实例化:容器根据BeanDefinition中的定义,调用Bean工厂实例化Bean对象。可以通过构造函数实例化、工厂方法实例化、静态工厂方法实例化等方式来创建Bean对象;
- Bean属性注入:通过BeanPostProcessor接口中的postProcessPropertyValues方法来对Bean的属性进行填充。这个过程是通过PropertyValues封装Bean的属性,然后使用依赖注入技术自动填充。这过程可以为构造注入或者设值注入;
- 处理依赖关系:容器会处理Bean之间的依赖关系,将依赖的Bean注入到需要的地方 ;
- 执行初始化方法:容器会调用Bean的初始化方法,可以通过实现InitializingBean接口或在配置文件中指定初始化方法来定义Bean的初始化逻辑。
- 注册Bean:容器会将实例化、属性设置和初始化完成的Bean对象注册到容器中,以便后续的使用和管理。
2. BeanDefinition
BeanDefinition 描述和定义Spring容器中Bean的元数据对象。
其中包含了许多属性,如 Bean 的名称、类型、作用域、构造函数参数、属性等等。
BeanDefinition 还可以设置生命周期回调方法,用于在 Bean 的生命周期中执行一些初始化或销毁操作。
这些可以通过 XML 配置、注解、Java 配置等方式进行配置:
XML定义
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 定义一个bean,其中class属性指定了类的全限定名,id属性是该bean的唯一标识 --><bean id="myBean" class="com.bean.DemoBean" ><!-- 这里可以配置构造函数参数、属性setter方法参数等 --></bean></beans>
注解定义
import lombok.Getter;
import lombok.Setter;
import org.springframework.stereotype.Component;@Getter
@Setter
@Component
public class DemoBeanA {private String name;}
@Configuration + @Bean
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class DemoBean {@Bean("demoBeanA1")public DemoBeanA demoBeanA() {// 自定义装配 一般用于将第三方类库装配为bean 或者 需要自行设定一些参数的beanDemoBeanA demoBeanA = new DemoBeanA();demoBeanA.setName("demoBeanA");return demoBeanA;}}
代码注册
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;@Slf4j
public class DemoBeanRegister {static AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(DemoBean.class);public static void main(String[] args) {beanRegister(DemoBeanA.class);DemoBeanA demoBeanA = applicationContext.getBean(DemoBeanA.class);log.debug(demoBeanA.getName());}public static void beanRegister(Class<?> beanClass) {applicationContext.register(beanClass);applicationContext.refresh();}}