依赖注入的方式
  • 属性注入
1
2
@Autowired
private DemoService demoService;

注:注入对象不能通过final修饰,无法发现空指针

  • setter注入
1
2
3
4
5
6
private DemoService demoService; 

@Autowired
public void setDemoService(DemoService demoService) {
this.demoService = demoService;
}
  • 构造器注入
1
2
3
4
5
6
7
8
public class DemoController {

private final DemoService demoService;

public SysUserController(DemoService demoService) {
this.demoService = demoService;
}
}

注:存在循环依赖问题

  • Lombox 的 @RequiredArgsConstructor

生成带final修饰的私有构造方法

三级缓存
  • 存放正在创建bean的名称
1
private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
  • 存放完全初始化好的Bean(一级缓存)
1
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
  • 存放实例化但是未初始化的Bean(早期引用)(二级缓存)
1
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
  • 存放Bean工厂对象(三级缓存)
1
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
依赖创建流程
非循环依赖A依赖了B
  • 在 singletonsCurrentlyInCreation 中存入A,表示A正在创建中

  • 判断A是否在一级缓存中,存在就直接从一级缓存中拿

  • 一级缓存不存在,判断二级缓存中是否存在

    • 二级缓存中存在,初始化A,并将A剪切至一级缓存
    • 二级缓存中不存在,从三级缓存中拿到创建A的工厂,创建A后剪切至一级缓存
  • 三级缓存创建A

    • 若A依赖了B,则需要先将B创建完成,从一级缓冲中拿到B,初始化A后剪切至一级缓存
循环依赖 A依赖了B B依赖了A
  • 在 singletonsCurrentlyInCreation 中存入A,表示A正在创建中

  • 判断A是否在一级缓存中,存在就直接从一级缓存中拿

  • 一级缓存不存在,判断二级缓存中是否存在

    • 二级缓存中存在,初始化A,并将A剪切至一级缓存
    • 二级缓冲中不存在,从三级缓存中拿到创建A的工厂创建A
  • 三级缓存创建A

    • 若A依赖B,则先创建B,再创建A

    • 创建B

      • 在 singletonsCurrentlyInCreation 中存入B,表示B正在创建中
      • 一二级缓存中都不存在B情况下,三级缓存创建B
        • B依赖了A,判断 singletonsCurrentlyInCreation 是否在创建中,若A在创建中,则先实例化A(先不初始化,即A中不填入属性),将A从三级缓存剪切到二级缓存
        • 创建B,将二级缓存中的A放入B,初始化完成后将B剪切至一级缓存,将B从 singletonsCurrentlyInCreation 移除,表示B创建完成
    • 从二级缓存中拿到A,从一级缓存中拿到B,将B填入A,初始化完成A以后将A剪切至一级缓存

    • 将A从 singletonsCurrentlyInCreation 中移除,表示A创建完成