spring源码解析(四)

系列文章目录

第一篇 spring源码解析之扩展原理BeanFactoryPostProcessor和BeanDefinitionPostProcessor和ApplicationListener
第二篇 spring bean的实例化过程
第三篇 spring容器创建准备的前期工作源码分析
第四篇 spring ioc源码解析之解决循环依赖
第五篇 spring aop源码分析之代理对象的创建


案例

package com.yemuxia.ioc15;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;


@Configuration
@Import(value = {TestService.class})
@ComponentScan(basePackages = "com.yemuxia.ioc15")
public class AppConfig {


    @Bean
    public TestDataSource testDataSource() {
        return new TestDataSource();
    }



}

package com.yemuxia.ioc15;



public class TestDataSource {

    public TestDataSource() {
        System.out.println("TestDataSource");
    }
}

package com.yemuxia.ioc15;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;


@Repository
//@Scope(value = "prototype")
public class TestDao {

    private TestDataSource testDataSource;


    public TestDao(TestDataSource testDataSource) {
        this.testDataSource = testDataSource;
        System.out.println("本类的DataSource"+this.testDataSource);
    }

}

package com.yemuxia.ioc15;

import org.springframework.stereotype.Controller;


@Controller
public class TestController {
}

package com.yemuxia.ioc15;


public class TestService {

    public TestService() {
        System.out.println("我是testService的构造方法");
    }
}

package com.yemuxia.ioc15;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;


public class MainClass {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
        System.out.println(ctx.getBean(TestDao.class));
        System.out.println(ctx.getBean(TestDao.class));
        TestDao testDao = (TestDao) ctx.getBean("testDao");
        System.out.println(testDao);
    }
}


在这里插入图片描述

总结getBean的完整流程

在这里插入图片描述

Spring循环依赖的案例

基于属性的循环依赖

package com.yemuxia.ioc17;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class InstanceA {

    @Autowired
    private InstanceB instanceB;


//    @Autowired
    public InstanceA(InstanceB instanceB) {
        this.instanceB = instanceB;
    }

    public InstanceA() {
        System.out.println("InstanceA实例化");
    }
}

package com.yemuxia.ioc17;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class InstanceB {

    @Autowired
    private InstanceA instanceA;


//    @Autowired
    public InstanceB(InstanceA instanceA) {
        this.instanceA = instanceA;
    }

    public InstanceB() {
        System.out.println("InstanceB实例化");
    }
}

package com.yemuxia.ioc17;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;


@Configuration
@ComponentScan(basePackages = {"com.yemuxia.ioc17"})
public class MainConfig {

}

package com.yemuxia.ioc17;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;


public class MainClass {

    public static void main(String[] args) {
        //创建IOC容器
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(MainConfig.class);
    }
}

在这里插入图片描述

构造器参数循环依赖

将实例A和实例B两个类修改成如下

package com.yemuxia.ioc17;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class InstanceA {

//    @Autowired
    private InstanceB instanceB;


    @Autowired
    public InstanceA(InstanceB instanceB) {
        this.instanceB = instanceB;
    }

    public InstanceA() {
        System.out.println("InstanceA实例化");
    }
}

package com.yemuxia.ioc17;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class InstanceB {

//    @Autowired
    private InstanceA instanceA;


    @Autowired
    public InstanceB(InstanceA instanceA) {
        this.instanceA = instanceA;
    }

    public InstanceB() {
        System.out.println("InstanceB实例化");
    }
}

在这里插入图片描述

总结

上述案例可知, Spring解决的循环依赖就是指属性的循环依赖
通过构造器注入构成的循环依赖,此依赖是无法解决的,只能抛出BeanCurrentlyInCreationException异常表示循环依赖。

Spring的三级缓存

  • 一级缓存:singletonObjects里面存放的是初始化之后的单例对象;
  • 二级缓存:earlySingletonObjects中存放的是一个已完成实例化未完成初始化的早期单例对象;
  • 三级缓存:singletonFactories中存放的是ObjectFactory对象,此对象的getObject方法返回值即刚完成实例化还未开始初始化的单例对象。
  • 所以先后顺序是,单例对象先存在于singletonFactories中,后存在于earlySingletonObjects中,最后初始化完成后放入singletonObjects中。

Spring是如何解决循环依赖的

Spring通过将实例化后的对象提前暴露给Spring容器中的singletonFactories,解决了循环依赖的问题。

Spring循环依赖流程图

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yemuxiaweiliang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值