Spring启动过程
1、通过ContextLoaderListener启动初始化程序
2、开始创建web上下文容器
3、初始化BeanFactory
4、获取ContextLoaderListener对应的配置文件
5、查找内部root标签,转换为Element,获取相关Nodes
6、经过一系列解析注册,循环Nodes,区别import、bean、alias,import则为文件导入,bean则注册,bean注册时将ID和Class对应信息加入底层的ConcurrentHashMap中
7、中间操作(刷新,注册监听等)
8、初始化bean,通过getBean形式注入,区分Single、Scope、Prototype,其中只是区分了isSingleton或isPrototype,两者的区别在于,单例的(Singleton)被缓存起来,而Prototype是不用缓存的。
9、创建Bean,通过CreateBean-》doCreateBean->instantiateBean->instantiate方法
10、通过populateBean将Bean属性注入到Bean中,是调用InstantiationAwareBeanPostProcessor
的具体子类的ibp.postProcessPropertyValues
方法注入属性。当我们使用@Resource
注解的时候,具体的子类是CommonAnnotationBeanPostProcessor
;
如果使用的是@Autowired
注解,则具体的子类是AutowiredAnnotationBeanPostProcessor
。此方法内是委托InjectionMetadata
对象来完成属性注入。
11、反射生成Bean,注入
注:findAutowiringMetadata
方法能拿到使用了特定注解的属性(Field)、方法(Method)及依赖的关系保存到checkedElements
集合<Set>
里,然后再执行自己的inject
方法。
注入代码:
ReflectionUtils.makeAccessible(field); field.set(bean, value);
最终是通过JDK反射特性,直接set值的。
Spring是如何确定singleton还是prototype?
spring在默认情况上是Singleton,如果需要设置为Prototype,则需要显示配置
if (!StringUtils.hasLength(mbd.getScope())) { mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON); }