# Ioc源码剖析


<!--more-->

# Spring IOC源码剖析



## 一、容器继承体系

BeanFactory是顶层容器

![BeanFactory](https://img.zhaojq.top/20260727092038578.png "BeanFactory")

## 二、Bean生命周期关键节点

### 1.数据准备

创建测试bean，实现几个特殊接口

```java
//实现 InitializingBean 接口
public class TestBean implements InitializingBean {

    public TestBean() {
        System.out.println("------------------TestBean 构造器执行------------------------");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("------------------TestBean afterPropertiesSet执行------------------------");
    }


}
```

```java
//实现 BeanPostProcessor 接口
public class TestBeanPostProcessor implements BeanPostProcessor {

    public TestBeanPostProcessor() {
        System.out.println("------------------BeanPostProcessor 实现类 构造器------------------------");
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("------------------BeanPostProcessor 实现类 postProcessBeforeInitialization 执行------------------------");

        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("------------------BeanPostProcessor 实现类 postProcessAfterInitialization 执行------------------------");

        return bean;
    }
}
```

```java
//实现 BeanFactoryPostProcessor 接口
public class TestBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    public TestBeanFactoryPostProcessor() {
        System.out.println("------------------BeanFactoryPostProcessor 实现类 构造器 执行------------------------");
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("------------------BeanFactoryPostProcessor 实现类 postProcessBeanFactory 执行------------------------");
    }
}
```

以xml配置形式示例

```xml
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx
        https://www.springframework.org/schema/tx/spring-tx.xsd
">
    <bean id="testBean" class="com.example.demo.entity.TestBean"/>
    <bean id="testBeanPostProcessor" class="com.example.demo.processor.TestBeanPostProcessor"/>
    <bean id="testBeanFactoryPostProcessor" class="com.example.demo.processor.TestBeanFactoryPostProcessor"/>

</beans>
```

```java
//测试类
public class TestDemo {

    @Test
    public void test1() {
        ClassPathXmlApplicationContext context = new    ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        TestBean testBean = (TestBean) context.getBean("testBean");
        System.out.println(testBean);
    }
}
```

### 2.分析bean创建是在容器初始化时，还是在`getBean()`时

![img_10](https://img.zhaojq.top/20260727092038760.png "img_10")

可以看到，在未设置延迟加载的前提下，Bean 的创建是在容器初始化过程中完成的。

### 3.分析构造函数调用情况

![img_11](https://img.zhaojq.top/20260727092038982.png "img_11")

通过如上观察，我们发现构造函数的调⽤时机在`AbstractApplicationContext`类`refresh()`⽅法的`finishBeanFactoryInitialization(beanFactor)`处;

### 4.分析 `InitializingBean` 之 `afterPropertiesSet() `(初始化⽅法调⽤情况

![img_11](https://img.zhaojq.top/20260727092038982.png "img_11")

通过如上观察，我们发现` InitializingBean`中`afterPropertiesSet `⽅法的调⽤时机也是在`AbstractApplicationContext`类`refresh()`⽅法的`finishBeanFactoryInitialization(beanFactory)`

### 5.分析`BeanFactoryPostProcessor` 初始化和调⽤情况

分别在构造函数、`postProcessBeanFactory` ⽅法处打断点，观察调⽤栈，发现:  

- `BeanFactoryPostProcessor` 初始化在`AbstractApplicationContext`类`refresh`⽅法的`invokeBeanFactoryPostProcessors(beanFactory)`;

- `postProcessBeanFactory` 调⽤在`AbstractApplicationContext`类`refresh`⽅法的`invokeBeanFactoryPostProcessors(beanFactory)`;

### 6.分析 `BeanPostProcessor` 初始化和调⽤情况

分别在构造函数、`postProcessBeanFactory` ⽅法处打断点，观察调⽤栈，发现：

- `BeanPostProcessor` 初始化在`AbstractApplicationContext`类`refresh`⽅法的`registerBeanPostProcessors(beanFactory)`;

- `postProcessBeforeInitialization` 调⽤在`AbstractApplicationContext`类`refresh`⽅法的`finishBeanFactoryInitialization(beanFactory)`;

- `postProcessAfterInitialization` 调⽤在`AbstractApplicationContext`类`refresh`⽅法的`finishBeanFactoryInitialization(beanFactory)`;

>```java
>------------------BeanFactoryPostProcessor 实现类 构造器 执行------------------------
>------------------BeanFactoryPostProcessor 实现类 postProcessBeanFactory 执行------------------------
>------------------BeanPostProcessor 实现类 构造器------------------------
>------------------TestBean 构造器执行------------------------
>------------------BeanPostProcessor 实现类 postProcessBeforeInitialization 执行------------------------
>------------------TestBean afterPropertiesSet执行------------------------
>------------------BeanPostProcessor 实现类 postProcessAfterInitialization 执行------------------------
>```

## 三、容器初始化流程

```java
public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// Prepare this context for refreshing.
      // 预处理
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			// 获取BeanFactory；默认实现是DefaultListableBeanFactory
			// 加载BeanDefition 并注册到 BeanDefitionRegistry
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// Prepare the bean factory for use in this context.
      // BeanFactory的预准备⼯作 BeanFactory进⾏⼀些设置，⽐如context的类加载器等
			prepareBeanFactory(beanFactory);

			try {
				// Allows post-processing of the bean factory in context subclasses.
        // BeanFactory准备⼯作完成后进⾏的后置处理⼯作
				postProcessBeanFactory(beanFactory);

				// Invoke factory processors registered as beans in the context.
        // 实例化并调⽤实现了BeanFactoryPostProcessor接⼝的Bean
				invokeBeanFactoryPostProcessors(beanFactory);

				// Register bean processors that intercept bean creation.
        // 注册BeanPostProcessor（Bean的后置处理器），在创建bean的前后等执行
				registerBeanPostProcessors(beanFactory);

				// Initialize message source for this context.
        // 初始化MessageSource组件（做国际化功能；消息绑定，消息解析）
				initMessageSource();

				// Initialize event multicaster for this context.
        // 初始化事件派发器
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
        // ⼦类重写这个⽅法，在容器刷新的时候可以⾃定义逻辑
				onRefresh();

				// Check for listener beans and register them.
        // 注册应⽤的监听器。就是注册实现了ApplicationListener接⼝的监听器bean
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
        // 初始化所有剩下的⾮懒加载的单例bean
        // 初始化创建⾮懒加载⽅式的单例Bean实例（未设置属性）
        // 填充属性
        // 初始化⽅法调⽤（⽐如调⽤afterPropertiesSet⽅法、init-method⽅法）
        // 调⽤BeanPostProcessor（后置处理器）对实例bean进⾏后置处
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
        // 完成context的刷新。主要是调⽤LifecycleProcessor的onRefresh()⽅法，并且发布事件（ContextRefreshedEvent）
				finishRefresh();
			}

			catch (BeansException ex) {
				if (logger.isWarnEnabled()) {
					logger.warn("Exception encountered during context initialization - " +
							"cancelling refresh attempt: " + ex);
				}

				// Destroy already created singletons to avoid dangling resources.
				destroyBeans();

				// Reset 'active' flag.
				cancelRefresh(ex);

				// Propagate exception to caller.
				throw ex;
			}

			finally {
				// Reset common introspection caches in Spring's core, since we
				// might not ever need metadata for singleton beans anymore...
				resetCommonCaches();
			}
		}
	}
```

## 四、BeanFactory创建流程

```java
ClassPathXmlApplicationContext#refresh obtainFreshBeanFactory()
   AbstractApplicationContext#obtainFreshBeanFactory refreshBeanFactory()
     AbstractRefreshableApplicationContext#refreshBeanFactory  createBeanFactory()
       protected DefaultListableBeanFactory createBeanFactory() {
					return new DefaultListableBeanFactory(getInternalParentBeanFactory());
			 }
```

## 五、BeanDefinition加载解析及注册⼦流程

### 1.步骤

- Resource定位：指对BeanDefinition的资源定位过程。通俗讲就是找到定义Javabean信息的XML⽂件，并将其封装成Resource对象。

- BeanDefinition载⼊ ：把⽤户定义好的Javabean表示为IoC容器内部的数据结构，这个容器内部的数据结构就是BeanDefinition。

### 2.过程分析

- Step1 

  流程入口在`AbstractRefreshableApplicationContext#refreshBeanFactory`方法中

  ![img_12](https://img.zhaojq.top/20260727092039363.png "img_12")  

- Step2 

  依次调⽤多个类的` loadBeanDefinitions`⽅法->`AbstractXmlApplicationContext` ->`AbstractBeanDefinitionReader` -> `XmlBeanDefinitionReader` ⼀直执⾏到`XmlBeanDefinitionReader `的 `doLoadBeanDefinitions` ⽅法

  ![img_13](https://img.zhaojq.top/20260727092039607.png "img_13")  

- step3

  我们重点观察`XmlBeanDefinitionReader` 类的 `registerBeanDefinitions` ⽅法，期间产⽣了多次重载调⽤，我们定位到最后⼀个

  ![img_14](https://img.zhaojq.top/20260727092039847.png "img_14")  

  先进⼊`createRederContext`,我们可以看到,此处 Spring ⾸先完成了`NamespaceHandlerResolver`的初始化

  ![img_15](https://img.zhaojq.top/20260727092040045.png "img_15")  

  我们再进⼊ `registerBeanDefinitions` ⽅法中追踪

  ![img_16](https://img.zhaojq.top/20260727092040350.png "img_16")  

  ![img_17](https://img.zhaojq.top/20260727092040536.png "img_17")  

  ![img_18](https://img.zhaojq.top/20260727092040786.png "img_18")  

  ![img_19](https://img.zhaojq.top/20260727092041017.png "img_19")  

  ![img_20](https://img.zhaojq.top/20260727092041208.png "img_20")  

  ![img_21](https://img.zhaojq.top/20260727092041444.png "img_21") 

  ![img_22](https://img.zhaojq.top/20260727092041671.png "img_22") 

  ⾄此，注册流程结束，我们发现，所谓的注册就是把封装的 XML 中定义的 Bean信息封装为BeanDefinition 对象之后放⼊⼀个Map中，BeanFactory 是以 Map 的结构组织这些 BeanDefinition的。

## 六、Bean创建流程

通过最开始的关键时机点分析，我们知道Bean创建⼦流程⼊⼝在`AbstractApplicationContext#refresh()`⽅法的`finishBeanFactoryInitialization(beanFactory) `处

![img_23](https://img.zhaojq.top/20260727092041863.png "img_23") 

![img_24](https://img.zhaojq.top/20260727092042055.png "img_24") 

继续进⼊`DefaultListableBeanFactory`类的`preInstantiateSingletons`⽅法，我们找到下⾯部分的代码，看到⼯⼚Bean或者普通Bean，最终都是通过getBean的⽅法获取实例

![img_25](https://img.zhaojq.top/20260727092042318.png "img_25") 

继续跟踪下去，我们进⼊到了`AbstractBeanFactory`类的`doGetBean`⽅法，这个⽅法中的代码很多，我们直接找到核⼼部分

![img_26](https://img.zhaojq.top/20260727092042580.png "img_26") 

接着进⼊到AbstractAutowireCapableBeanFactory类的⽅法，找到以下代码部分

![img_27](https://img.zhaojq.top/20260727092042794.png "img_27") 

进⼊doCreateBean⽅法看看，该⽅法我们关注两块重点区域

![img_28](https://img.zhaojq.top/20260727092042989.png "img_28") 

![img_29](https://img.zhaojq.top/20260727092043167.png "img_29") 

我们看到实现`InitializingBean#afterPropertiesSet`方法、`BeanPostProcessor#postProcessBeforeInitialization`方法、`BeanPostProcessor#postProcessAfterInitialization`方法调用位置如下

![img_30](https://img.zhaojq.top/20260727092043379.png "img_30") 

## 七、lazy-init 延迟加载机制原理

普通 Bean 的初始化是在容器启动初始化阶段执⾏的，⽽被lazy-init=true修饰的 bean 则是在从容器⾥第⼀次进⾏`context.getBean()` 时进⾏触发。Spring 启动的时候会把所有bean信息(包括XML和注解)解析转化成Spring能够识别的`BeanDefinition`并存到`Hashmap`⾥供下⾯的初始化时⽤，然后对每个`BeanDefinition` 进⾏处理，如果是懒加载的则在容器初始化阶段不处理，其他的则在容器初始化阶段进⾏初始化并依赖注⼊。

```java
public void preInstantiateSingletons() throws BeansException {
		if (logger.isTraceEnabled()) {
			logger.trace("Pre-instantiating singletons in " + this);
		}

		// Iterate over a copy to allow for init methods which in turn register new bean definitions.
		// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
      //此处初始化非抽象bean、单例bean、非lazy-init的bean
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				if (isFactoryBean(beanName)) {
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						final FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
											((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
							getBean(beanName);
						}
					}
				}
				else {
          //如果是普通bean则进⾏初始化并依赖注⼊，此 getBean(beanName)接下来触发的逻辑和
					//懒加载时 context.getBean("beanName") 所触发的逻辑是⼀样的
					getBean(beanName);
				}
			}
		}
```

- 总结

  - 对于被修饰为lazy-init的bean Spring 容器初始化阶段不会进⾏ init 并且依赖注⼊，当第⼀次进⾏getBean时候才进⾏初始化并依赖注⼊

  - 对于⾮懒加载的bean，getBean的时候会从缓存⾥头获取，因为容器初始化阶段 Bean 已经初始化完成并缓存了起来

## 八、IOC循环依赖问题

### 1.什么是循环依赖

循环依赖其实就是循环引⽤，也就是两个或者两个以上的 Bean 互相持有对⽅，最终形成闭环。⽐如A依赖于B，B依赖于C，C⼜依赖于A。

![img_31](https://img.zhaojq.top/20260727092043639.png "img_31")

> 注意，这⾥不是函数的循环调⽤，是对象的相互依赖关系。循环调⽤其实就是⼀个死循环，除⾮有终结条件

Spring中循环依赖场景有：

- 构造器的循环依赖（构造器注⼊）

- Field 属性的循环依赖（set注⼊）

> 其中，构造器的循环依赖问题⽆法解决，只能拋出 `BeanCurrentlyInCreationException` 异常，在解决属性循环依赖时，spring采⽤的是提前暴露对象的⽅法。

### 2.循环依赖处理机制

- 单例 bean 构造器参数循环依赖（⽆法解决）

- prototype 原型 bean循环依赖（⽆法解决）

  对于原型bean的初始化过程中不论是通过构造器参数循环依赖还是通过`setXxx`⽅法产⽣循环依赖，Spring都 会直接报错处理。

  `AbstractBeanFactory.doGetBean()`⽅法：

  ```java
  // Fail if we're already creating this bean instance:
  // We're assumably within a circular reference.
  if (isPrototypeCurrentlyInCreation(beanName)) {
    throw new BeanCurrentlyInCreationException(beanName);
  }
  
  /**
   * Return whether the specified prototype bean is currently in creation
   * (within the current thread).
   * @param beanName the name of the bean
   */
  protected boolean isPrototypeCurrentlyInCreation(String beanName) {
    Object curVal = this.prototypesCurrentlyInCreation.get();
    return (curVal != null &&
            (curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
  }
  ```

  在获取bean之前如果这个原型bean正在被创建则直接抛出异常。原型bean在创建之前会进⾏标记这个beanName正在被创建，等创建结束之后会删除标记

  ```java
  else if (mbd.isPrototype()) {
    // It's a prototype -> create a new instance.
    Object prototypeInstance = null;
    try {
      //添加标记
      beforePrototypeCreation(beanName);
      //创建原型bean
      prototypeInstance = createBean(beanName, mbd, args);
    }
    finally {
      //删除标记
      afterPrototypeCreation(beanName);
    }
    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
  }
  ```

  **总结：Spring 不⽀持原型 bean 的循环依赖。**

- 单例bean通过setXxx或者@Autowired进⾏循环依赖

  Spring 的循环依赖的理论依据基于 Java 的引⽤传递，当获得对象的引⽤时，对象的属性是可以延后设置的，但是构造器必须是在获取引⽤之前。Spring通过setXxx或者@Autowired⽅法解决循环依赖其实是通过提前暴露⼀个ObjectFactory对象来完成的，简单来说ClassA在调⽤构造器完成对象初始化之后，在调⽤ClassA的setClassB⽅法之前就把ClassA实例化的对象通过ObjectFactory提前暴露到Spring容器中。

  - Spring容器初始化ClassA通过构造器初始化对象后提前暴露到Spring容器。

    ```java
    		//从官方注解可以看出，此处就是为了解决循环依赖问题
        // Eagerly cache singletons to be able to resolve circular references
    		// even when triggered by lifecycle interfaces like BeanFactoryAware.
    		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
    				isSingletonCurrentlyInCreation(beanName));
    		if (earlySingletonExposure) {
    			if (logger.isTraceEnabled()) {
    				logger.trace("Eagerly caching bean '" + beanName +
    						"' to allow for resolving potential circular references");
    			}
    			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    		}
    ```

  - ClassA调⽤setClassB⽅法，Spring⾸先尝试从容器中获取ClassB，此时ClassB不存在Spring容器中

  - Spring容器初始化ClassB，同时也会将ClassB提前暴露到Spring容器中

  - ClassB调⽤setClassA⽅法，Spring从容器中获取ClassA ，因为第⼀步中已经提前暴露了ClassA，因此可以获取到ClassA实例

  - ClassA通过spring容器获取到ClassB，完成了对象初始化操作

  - 这样ClassA和ClassB都完成了对象初始化操作，解决了循环依赖问题














































