• Spring源码构建
    • 下载源码(github)
    • 安装gradle 5.6.3
    • 导⼊(耗费⼀定时间)
    • 编译⼯程(顺序:core-oxm-context-beans-aspects-aop)
      • ⼯程—>tasks—>compileTestJava

5.1 IOC容器初始化主体流程

5.1.1 Spring IOC的容器体系

  • Spring提供了很多的容器,其中BeanFactory是顶层容器(根容器),它规范了/定义了容器的基本行为。
  • 具体的容器实现可以增加额外的功能,⽐如我们常⽤到的ApplicationContext,其下更具体的实现如 ClassPathXmlApplicationContext 包含了解析 xml 等⼀系列的内容,AnnotationConfigApplicationContext 则是包含了注解解析等⼀系列的内容。
  • ApplicationContext是容器的高级接口,Spring应用上下文,官方称之为IOC容器(错误的认识:容器就是map而已;准确的说,map是IOC容器的一个成员,叫做单例池(singletonObjects),容器是一组组件和过程的集合,包括BeanFactory、单例池、BeanPostProcessor等等)。
  • Spring IoC 容器继承体系⾮常聪明,需要使⽤哪个层次⽤哪个层次即可,不必使⽤功能⼤⽽全的。也就是把功能都打散,想实现哪个功能就去实现哪个接口,不用一股脑全部实现。
  • 我们⼀贯使⽤的 ApplicationContext 除了继承BeanFactory的⼦接⼝,还继承了ResourceLoaderMessageSource等接⼝,因此其提供的功能也就更丰富了。

    5.1.2 Bean生命周期的关键时机点

  1. 以ClassPathXmlApplicationContext为例启动容器,创建一个类MyBean,让其实现几个特殊的接口,方法中断点,观察线程调⽤栈,分析出 Bean 对象创建和管理关键点的触发时机。

    1. public class LagouBean implements InitializingBean{
    2. /**
    3. * 构造函数
    4. */
    5. public LagouBean(){
    6. System.out.println("LagouBean 构造器...");
    7. }
    8. /**
    9. * InitializingBean 接⼝实现
    10. */
    11. public void afterPropertiesSet() throws Exception {
    12. System.out.println("LagouBean afterPropertiesSet...");
    13. }
    14. }
  2. BeanPostProcessor接口实现类

    1. public class MyBeanPostProcessor implements BeanPostProcessor {
    2. public MyBeanPostProcessor() {
    3. System.out.println("BeanPostProcessor 实现类构造函数...");
    4. }
    5. @Override
    6. public Object postProcessBeforeInitialization(Object bean, String beanName)
    7. throws BeansException {
    8. if("MyBean".equals(beanName)) {
    9. System.out.println("BeanPostProcessor 实现类postProcessBeforeInitialization ⽅法被调⽤中......");
    10. }
    11. return bean;
    12. }
    13. @Override
    14. public Object postProcessAfterInitialization(Object bean, String beanName)
    15. throws BeansException {
    16. if("MyBean".equals(beanName)) {
    17. System.out.println("BeanPostProcessor 实现类postProcessAfterInitialization ⽅法被调⽤中......");
    18. }
    19. return bean;
    20. }
    21. }
  3. BeanFactoryPostProcessor 接⼝实现类

    1. public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
    2. public MyBeanFactoryPostProcessor() {
    3. System.out.println("BeanFactoryPostProcessor的实现类构造函数...");
    4. }
    5. @Override
    6. public void postProcessBeanFactory(ConfigurableListableBeanFactory
    7. beanFactory) throws BeansException {
    8. System.out.println("BeanFactoryPostProcessor的实现⽅法调⽤中......");
    9. }
    10. }
  4. 分析结论

  • 在getBean()方法打断点发现,在未设置延迟加载的前提下,Bean 的创建是在容器初始化过程中完成的。在调用getBean()方法前已经存在于容器中。
  • Bean的无参构造器调用时机:在IOC容器中,Bean的创建是通过反射调用无参构造器来完成的,所以在构造器中设置断点,发现构造函数的调⽤时机在AbstractApplicationContext类refresh⽅法的finishBeanFactoryInitialization(beanFactory)处。
  • Bean的初始化时机:在MyBean这个类中继承InitializingBean接口,这个接口是用来实现Bean的初始化的,然后实现它的方法afterPropertiesSet(),在方法中断点发现InitializingBean中afterPropertiesSet ⽅法的调⽤时机也是在AbstractApplicationContext类refresh⽅法的finishBeanFactoryInitialization(beanFactory)。
  • BeanPostProcessor 初始化和调⽤情况:初始化在AbstractApplicationContext类refresh⽅法的registerBeanPostProcessors(beanFactory);方法调用都在AbstractApplicationContext类refresh⽅法的finishBeanFactoryInitialization(beanFactory);
  • BeanFactoryPostProcessor 初始化和调⽤情况:初始化在AbstractApplicationContext类refresh⽅法的invokeBeanFactoryPostProcessors(beanFactory);方法调用在调⽤在AbstractApplicationContext类refresh⽅法的invokeBeanFactoryPostProcessors(beanFactory);
  • 总结:Bean对象创建的几个关键时机点都在AbstractApplicationContex类的refresh方法中,具体位置如下: | 关键点 | 触发代码 | | —- | —- | | 构造器 | finishBeanFactoryInitialization(beanFactory) | | BeanFactoryPostProcessor 初始化 | invokeBeanFactoryPostProcessors(beanFactory); | | BeanFactoryPostProcessor ⽅法调⽤ | invokeBeanFactoryPostProcessors(beanFactory); | | BeanPostProcessor 初始化 | registerBeanPostProcessors(beanFactory) | | BeanPostProcessor ⽅法调⽤ | finishBeanFactoryInitialization(beanFactory) |

5.1.3 IOC容器初始化主流程

由上分析可知,Spring IoC 容器初始化的关键环节就在 AbstractApplicationContext#refresh() ⽅法中
,我们查看 refresh ⽅法来俯瞰容器创建的主体流程。

  1. @Override
  2. public void refresh() throws BeansException, IllegalStateException {
  3. synchronized (this.startupShutdownMonitor) {
  4. // 第⼀步:刷新前的预处理
  5. prepareRefresh();
  6. /*
  7. 第⼆步:
  8. 获取BeanFactory;默认实现是DefaultListableBeanFactory
  9. 加载BeanDefition 并注册到 BeanDefitionRegistry
  10. */
  11. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
  12. // 第三步:BeanFactory的预准备⼯作(BeanFactory进⾏⼀些设置,⽐如context的类加载器等等)
  13. prepareBeanFactory(beanFactory);
  14. try {
  15. // 第四步:BeanFactory准备⼯作完成后进⾏的后置处理⼯作
  16. postProcessBeanFactory(beanFactory);
  17. // 第五步:实例化并调⽤实现了BeanFactoryPostProcessor接⼝的Bean
  18. invokeBeanFactoryPostProcessors(beanFactory);
  19. // 第六步:注册BeanPostProcessor(Bean的后置处理器),在创建bean的前后等执⾏
  20. registerBeanPostProcessors(beanFactory);
  21. // 第七步:初始化MessageSource组件(做国际化功能;消息绑定,消息解析);
  22. initMessageSource();
  23. // 第⼋步:初始化事件派发器
  24. initApplicationEventMulticaster();
  25. // 第九步:⼦类重写这个⽅法,在容器刷新的时候可以⾃定义逻辑
  26. onRefresh();
  27. // 第⼗步:注册应⽤的监听器。就是注册实现了ApplicationListener接⼝的监听器bean
  28. registerListeners();
  29. /*
  30. 第十一步:初始化所有剩下的⾮懒加载的单例bean
  31. 初始化创建⾮懒加载⽅式的单例Bean实例(未设置属性)
  32. 填充属性
  33. 初始化⽅法调⽤(⽐如调⽤afterPropertiesSet⽅法、init-method⽅法)
  34. 调⽤BeanPostProcessor(后置处理器)对实例bean进⾏后置处理
  35. */
  36. finishBeanFactoryInitialization(beanFactory);
  37. // 第⼗⼆步:完成context的刷新。主要是调⽤LifecycleProcessor的onRefresh()⽅法,
  38. // 并且发布事件(ContextRefreshedEvent)
  39. finishRefresh();
  40. }
  41. }
  42. }

5.2 BeanFactory的创建流程

5.2.1 获取BeanFactory子流程

  1. 时序图

1648201056(1).jpg

  1. 代码如下
  • AbstractApplicationContext

    1. protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    2. // 创建BeanFactory,加载BeanDefinitions,
    3. refreshBeanFactory();
    4. return getBeanFactory();
    5. }
  • AbstractRefreshableApplicationContext ```java @Override protected final void refreshBeanFactory() throws BeansException { // 判断是否存在BeanFactory,存在则销毁关闭 if (hasBeanFactory()) {

    1. destroyBeans();
    2. closeBeanFactory();

    } try {

    1. // 创建BeanFactory
    2. DefaultListableBeanFactory beanFactory = createBeanFactory();
    3. // 初始化BeanFactory
    4. beanFactory.setSerializationId(getId());
    5. customizeBeanFactory(beanFactory);
    6. // BeanDefinition的加载解析及注册入口
    7. loadBeanDefinitions(beanFactory);
    8. synchronized (this.beanFactoryMonitor) {
    9. this.beanFactory = beanFactory;
    10. }

    } catch (IOException ex) {

    1. throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);

    } }

// 创建新的BeanFactory protected DefaultListableBeanFactory createBeanFactory() { return new DefaultListableBeanFactory(getInternalParentBeanFactory()); }

  1. <a name="Y7G3N"></a>
  2. ## 5.2.2 BeanDefinition加载解析及注册⼦流程
  3. 1. 时序图
  4. ![1648202413(1).jpg](https://cdn.nlark.com/yuque/0/2022/jpeg/13010374/1648202429131-57551158-58b6-4183-892a-443b4a3ab732.jpeg#clientId=u1114194b-b4a9-4&crop=0&crop=0&crop=1&crop=1&from=ui&id=ucb0e8af1&margin=%5Bobject%20Object%5D&name=1648202413%281%29.jpg&originHeight=721&originWidth=1410&originalType=binary&ratio=1&rotation=0&showTitle=false&size=269291&status=done&style=none&taskId=ud96e208c-7190-481d-a198-d0577839368&title=)
  5. 2. 代码流程
  6. - 5.2.1中刷新BeanFactory时方法中的loadBeanDefinitions(beanFactory)就是入口。
  7. - AbstractXmlApplicationContext
  8. ```java
  9. @Override
  10. protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
  11. // 给BeanFactory创建一个新的XmlBeanDefinitionReader对象用来读取解析xml对象
  12. XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
  13. // XmlBeanDefinitionReader设置一些上下文中的环境属性
  14. beanDefinitionReader.setEnvironment(this.getEnvironment());
  15. beanDefinitionReader.setResourceLoader(this);
  16. beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
  17. // 提供给子类的一些自定义的初始化策略
  18. initBeanDefinitionReader(beanDefinitionReader);
  19. // 真正去加载BeanDefinitions
  20. loadBeanDefinitions(beanDefinitionReader);
  21. }
  22. protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
  23. // 从resource资源对象中加载BeanDefinitions
  24. Resource[] configResources = getConfigResources();
  25. if (configResources != null) {
  26. reader.loadBeanDefinitions(configResources);
  27. }
  28. // 从xml配置文件加载BeanDefinitions
  29. String[] configLocations = getConfigLocations();
  30. if (configLocations != null) {
  31. reader.loadBeanDefinitions(configLocations);
  32. }
  33. }
  • AbstractBeanDefinitionReader ```java @Override public int loadBeanDefinitions(String… locations) throws BeanDefinitionStoreException { Assert.notNull(locations, “Location array must not be null”); int count = 0; // 如果有多个配置文件,循环读取加载,并统计总共加载了多少个BeanDefinition for (String location : locations) {
    1. count += loadBeanDefinitions(location);
    } return count; }

public int loadBeanDefinitions(String location, @Nullable Set actualResources) throws BeanDefinitionStoreException { // 获取上下文的资源加载器 ResourceLoader resourceLoader = getResourceLoader(); if (resourceLoader == null) { throw new BeanDefinitionStoreException( “Cannot load bean definitions from location [“ + location + “]: no ResourceLoader available”); }

  1. if (resourceLoader instanceof ResourcePatternResolver) {
  2. // Resource pattern matching available.
  3. try {
  4. // 统一加载转换为Resource资源对象
  5. Resource[] resources = ((ResourcePatternResolver) resourceLoader).getResources(location);
  6. // 加载资源配置中的BeanDefinition对象并返回数量
  7. int count = loadBeanDefinitions(resources);
  8. ......
  9. }
  10. catch (IOException ex) {
  11. ......
  12. }
  13. }
  14. ......
  15. return;

}

@Override public int loadBeanDefinitions(Resource… resources) throws BeanDefinitionStoreException { Assert.notNull(resources, “Resource array must not be null”); int count = 0; for (Resource resource : resources) { count += loadBeanDefinitions(resource); } return count; }

  1. - XmlBeanDefinitionReader
  2. ```java
  3. public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
  4. ......
  5. try {
  6. InputStream inputStream = encodedResource.getResource().getInputStream();
  7. try {
  8. // 把xml流加载为InputSource对象
  9. InputSource inputSource = new InputSource(inputStream);
  10. if (encodedResource.getEncoding() != null) {
  11. inputSource.setEncoding(encodedResource.getEncoding());
  12. }
  13. // 开始执行加载逻辑
  14. return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
  15. }
  16. finally {
  17. inputStream.close();
  18. }
  19. }
  20. ......
  21. }
  22. // 读取xml解析完成
  23. protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
  24. throws BeanDefinitionStoreException {
  25. try {
  26. // 读取xml信息,将xml信息保存到document对象
  27. Document doc = doLoadDocument(inputSource, resource);
  28. // 解析document对象,封装成BeanDefinition对象并进行注册
  29. int count = registerBeanDefinitions(doc, resource);
  30. }
  31. ......
  32. }
  33. // 注册开始
  34. public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
  35. BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
  36. // 获取已有definition数量
  37. int countBefore = getRegistry().getBeanDefinitionCount();
  38. // 注册Definition
  39. documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
  40. // 返回新注册的Definition数量
  41. return getRegistry().getBeanDefinitionCount() - countBefore;
  42. }
  • DefaultBeanDefinitionDocumentReader ```java @Override public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) { this.readerContext = readerContext; doRegisterBean Definitions(doc.getDocumentElement()); }

protected void doRegisterBeanDefinitions(Element root) { …… preProcessXml(root); parseBeanDefinitions(root, this.delegate); postProcessXml(root); }

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { if (delegate.isDefaultNamespace(root)) { NodeList nl = root.getChildNodes(); for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); if (node instanceof Element) { Element ele = (Element) node; if (delegate.isDefaultNamespace(ele)) { // 解析默认标签(bean等等) parseDefaultElement(ele, delegate); } else { // 解析自定义标签 delegate.parseCustomElement(ele); } } } } else { delegate.parseCustomElement(root); } }

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { // import元素处理 if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { importBeanDefinitionResource(ele); } // alias元素处理 else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { processAliasRegistration(ele); } // bean元素处理 else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { processBeanDefinition(ele, delegate); } // beans嵌套处理 else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { // recurse doRegisterBeanDefinitions(ele); } }

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { // 包装bean元素为BeanDefinitionHolder对象 BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { // 完成BeanDefinition的注册 BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); } catch (BeanDefinitionStoreException ex) { getReaderContext().error(“Failed to register bean definition with name ‘“ + bdHolder.getBeanName() + “‘“, ele, ex); } getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } }

  1. - org.springframework.beans.factory.support.BeanDefinitionReaderUtils
  2. ```java
  3. public static void registerBeanDefinition(
  4. BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
  5. throws BeanDefinitionStoreException {
  6. // Register bean definition under primary name.
  7. String beanName = definitionHolder.getBeanName();
  8. // 注册bean的名字和bean本身信息
  9. registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
  10. // Register aliases for bean name, if any.
  11. String[] aliases = definitionHolder.getAliases();
  12. if (aliases != null) {
  13. for (String alias : aliases) {
  14. registry.registerAlias(beanName, alias);
  15. }
  16. }
  17. }
  • org.springframework.beans.factory.support.DefaultListableBeanFactory
    1. public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition){
    2. ......
    3. // 把BeanDefinition作为值,beanName作为key存入BeanFaory也就是容器的单例池则算注册成功
    4. this.beanDefinitionMap.put(beanName, beanDefinition);
    5. ......
    6. }

    5.3 Bean的创建流程

  1. 从5.1.2的分析中得知,Bean的创建,也就是构造器调用在AbstractApplicationContex类的refresh方法中,调用了finishBeanFactoryInitialization(beanFactory)
  2. 代码流程如下。
  • org.springframework.context.support.AbstractApplicationContext

    1. protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    2. // 实例化所有的立即加载的单例Bean
    3. beanFactory.preInstantiateSingletons();
    4. }
  • org.springframework.beans.factory.support.DefaultListableBeanFactory

    1. @Override
    2. public void preInstantiateSingletons() throws BeansException {
    3. ......
    4. // 所有bean的名字beanDefinitionNames
    5. List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
    6. // 触发所有非延迟加载的单例bean的初始化,主要步骤为getBean
    7. for (String beanName : beanNames) {
    8. // 合并父BeanDefinition对象 map.get(beanName)
    9. RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
    10. if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
    11. // 如果是factoryBean则加&
    12. if (isFactoryBean(beanName)) {
    13. Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
    14. if (bean instanceof FactoryBean) {
    15. final FactoryBean<?> factory = (FactoryBean<?>) bean;
    16. boolean isEagerInit;
    17. if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
    18. isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
    19. ((SmartFactoryBean<?>) factory)::isEagerInit,
    20. getAccessControlContext());
    21. }
    22. else {
    23. isEagerInit = (factory instanceof SmartFactoryBean &&
    24. ((SmartFactoryBean<?>) factory).isEagerInit());
    25. }
    26. if (isEagerInit) {
    27. // 实例化当前bean
    28. getBean(beanName);
    29. }
    30. }
    31. }
    32. else {
    33. getBean(beanName);
    34. }
    35. }
    36. }
  • org.springframework.beans.factory.support.AbstractBeanFactory ```java protected T doGetBean(final String name, @Nullable final Class requiredType,

    1. @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

    // 解析beanName,如果以&开头则去掉&,如果是别名则获取真正名字 final String beanName = transformedBeanName(name); Object bean;

    // Eagerly check singleton cache for manually registered singletons. // 尝试从缓存中获取bean Object sharedInstance = getSingleton(beanName); // 如果存在则返回 if (sharedInstance != null && args == null) {

    1. ......
    2. // 针对beanFactory的处理
    3. bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);

    } else {

    1. // 判断如果是prototype的类型且允许开启循环依赖,则抛出异常
    2. if (isPrototypeCurrentlyInCreation(beanName)) {
    3. throw new BeanCurrentlyInCreationException(beanName);
    4. }
    5. // 检查父工厂中是否存在该对象
    6. BeanFactory parentBeanFactory = getParentBeanFactory();
    7. ......
    8. // 合并父子bean的属性
    9. final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    10. ......
    11. // 创建单例bean
    12. if (mbd.isSingleton()) {
    13. sharedInstance = getSingleton(beanName, () -> {
    14. try {
    15. // 创建bean
    16. return createBean(beanName, mbd, args);
    17. }
    18. catch (BeansException ex) {
    19. destroySingleton(beanName);
    20. throw ex;
    21. }
    22. });
    23. bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    24. }

    }

}

  1. - org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory
  2. ```java
  3. @Override
  4. protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args){
  5. // 获取到BeanDefinition
  6. RootBeanDefinition mbdToUse = mbd;
  7. // BeanDefinition从获得类的信息
  8. Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
  9. if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
  10. mbdToUse = new RootBeanDefinition(mbd);
  11. mbdToUse.setBeanClass(resolvedClass);
  12. }
  13. ......
  14. // 真正创建Bean
  15. Object beanInstance = doCreateBean(beanName, mbdToUse, args);
  16. }
  17. protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
  18. throws BeanCreationException {
  19. BeanWrapper instanceWrapper = null;
  20. if (mbd.isSingleton()) {
  21. instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
  22. }
  23. if (instanceWrapper == null) {
  24. // 仅仅调用构造函数,没有设置属性
  25. instanceWrapper = createBeanInstance(beanName, mbd, args);
  26. }
  27. // 利用反射实例化bean
  28. final Object bean = instanceWrapper.getWrappedInstance();
  29. Class<?> beanType = instanceWrapper.getWrappedClass();
  30. if (beanType != NullBean.class) {
  31. mbd.resolvedTargetType = beanType;
  32. }
  33. ......
  34. try {
  35. // bean属性填充
  36. populateBean(beanName, mbd, instanceWrapper);
  37. // 调用初始化方法,应用BeanPostProcessor后置处理器
  38. exposedObject = initializeBean(beanName, exposedObject, mbd);
  39. }
  40. catch (Throwable ex) {
  41. ......
  42. }
  43. }

5.4 lazy-init延迟加载机制原理

  1. 机制分析

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

  1. 总结
  • 对于被修饰为lazy-init的bean Spring 容器初始化阶段不会进⾏ init 并且依赖注⼊,当第⼀次进⾏getBean时候才进⾏初始化并依赖注⼊
  • 对于⾮懒加载的bean,getBean的时候会从缓存⾥头获取,因为容器初始化阶段 Bean 已经初始化完成并缓存了起来

    5.5 循环依赖问题

    5.5.1 什么是循环依赖

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

5. SpringIOC的源码 - 图2

  • 注意,这⾥不是函数的循环调⽤,是对象的相互依赖关系。循环调⽤其实就是⼀个死循环,除⾮有终结条件
  • Spring中循环依赖场景有:
    • 构造器的循环依赖(构造器注⼊)
    • Field 属性的循环依赖(set注⼊)
  • 其中,构造器的循环依赖问题⽆法解决,只能拋出 BeanCurrentlyInCreationException 异常,在解决属性循环依赖时,spring采⽤的是提前暴露对象的⽅法。

    5.5.2 循环依赖处理机制(三级缓存)

    循环依赖问题.png
  1. 单例Bean的构造器注入循环依赖无法解决。
  2. 多例bean的循环依赖无法解决。对于原型bean的初始化过程中不论是通过构造器参数循环依赖还是通过setXxx⽅法产⽣循环依赖,Spring都 会直接报错处理。
  3. 通过set方法注入或者@Autowired注入的单例Bean的循环依赖是可以解决的(如图):
  • Spring的循环依赖解决基于java的引用传递,实例化Bean的时候属性还没注入,此时把Bean放入三级缓存当中,提前暴露没有完全创建的Bean;比如BeanA实例化完成放入三级缓存,然后注入属性的时候发现需要BeanB,此时就会去创建BeanB,创建完发现依赖于BeanA,此时就可以在三级缓存中取到BeanA,完成BeanB的创建。虽然BeanB在三级缓存中拿到的BeanA只是个刚刚实例化完没有属性的,但是因为获取的是对象的引用,所以BeanA后续创建完成时BeanB中的BeanA属性也是个完全的Bean。具体的流程如图所示。
  • 为什么构造器注入不能解决:因为实例化Bean需要调用构造器,构造器注入则说明在实例化的时候就需要注入循环依赖的Bean,但是该Bean没有创建所以无法实例化,也就无法放入三级缓存中提前暴露了。

为什么不能使用二级缓存解决:
结论:如果没有AOP,是可以使用二级缓存解决循环依赖的,但是有AOP就不行。
分析:
在创建bean对象的时候,有三个步骤:实例化、填充属性、初始化。比如BeanA实例化首先通过ObjectFactory暴露在三级缓存中,然后填充属性时发现依赖BeanB,依次从1,2,3三级缓存中找,没找到,然后创建BeanB,BeanB实例化也通过ObjectFactory暴露在三级缓存中,填充属性的时候发现依赖BeanA,也一次从1,2,3级缓存中找,在三级缓存中拿到BeanA的ObjectFactory对象后,调用ObjectFactory.getObject()方法最终会调用getEarlyBeanReference()方法,getEarlyBeanReference()方法主要执行的是:如果BeanA被AOP代理,那么返回的则是代理对象,没有被代理则返回原对象。获得BeanA后升级到二级缓存,此时BeanA的代理对象也存放到二级缓存,最后BeanB初始化完全放入一级缓存,接着BeanA也初始化完成放入一级缓存。
二级缓存的作用就是存放是半成品的代理对象或者是半成品的原始对象,因为存在AOP代理的时候,ObjectFactory.getObject()方法每次产生的都是一个新的代理对象,如果不把执行了ObjectFactory.getObject()方法的对象放入二级缓存中,那么每次都从三级缓存获取都会调用ObjectFactory.getObject()方法都会产生新代理对象不符合单例模式。