文章目录
前言
在Spring容器启动的时候会把所有的单例bean都给加载到容器中,但是在这些单例bean是如何被创建出来的呢?在Spring容器中,会使用推断构造方法将单例bean的构造方法找出来,找到最合适的构造方法进行对象的创建,具体找到构造方法,继续往下看?
一、什么是构造方法?
构造方法是一种特殊的方法,他是一个与类名相同的方法。对象创建就是通过构造方法来完成,其主要功能就是完成对象的初始化。
二、在Spring中如何找到最合适的构造方法
1、找出所有的构造方法
//先从缓存中有,则说明已经有创建过bean,最合适的构造方法在缓存中
Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
//如果缓存中没有,通过反射获取该类的所有构造方法,则需要推断最合适的构造方法
rawCandidates = beanClass.getDeclaredConstructors();
2、遍历所有的构造方法获取到的构造方法
// 用来记录添加了@Autowired且required为true的构造方法,一个类中只能有一个required为true的构造方法
Constructor<?> requiredConstructor = null;
// 用来记录默认无参的构造方法
Constructor<?> defaultConstructor = null;
// kotlin相关,不用管
Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
下面流程图对应的就是循环遍历每一个构造方法的过程;
3、找到构造方法之后,需要找出合适的构造方法
4、整个推断构造方法的总结
- 找到Bean的所有构造方法;
- 循环每一个构造方法,如果使用了@Autowired注解就加入到候选candidates集合中;
- 如果找到了两个@Autowired的构造方法,就会抛出异常;
- 如果构造方法中有@Autowired的,但是也找到了一个默认的无参构造,那么也会加入到候选集合中,但是这个时候只有@Autowired中的required=false才会加入,也就是说,如果找到了一个默认无参构造方法,一个@Autowired属性required=true会被舍弃,只有找到@Autowired属性required=false,那么又找到一个无参构造方法,才会加入到candidates中,也就是说如果找到了@Autowired同时其属性required=false和一般无参构造方法一样,都会加入到后续列表中,Spring把它当做一个不确定的因素,需要后续继续推导;
- 如果找到的构造方法只有一个,并且这个构造方法的参数大于0,那么就放回这个构造方法;
- 如果前三个否不满足,也就是说bean中存在2个以上的构造方法,但是没有加@Autowired注解的构造,那么直接返回null;
5、在获取所有构造方法之前还使用了DCL来保证线程安全问题。
- 先从缓存中获取是否有构造方法;
- 如果没有则使用synchronized来锁住缓存;
- 目的是为了在当前线程获取锁对象之前,另一个线程能够操作完成;
- 获取所对象成功之后,再次查询缓存,如果获取成功,则直接返回;
- 如果获取失败,则开始推断构造方法;
- 最后还会将推断出的结果放入到缓存当中;
总结
以上就是我对Spring中的推断构造方法的总结,有疑问或其他问题,欢迎评论区见;