Spring bean的加载过程
来源:互联网 发布:cdlinux安装软件 编辑:程序博客网 时间:2024/05/23 21:06
一、问题引入:
ctx.getBean方法是如何运作的 ?
二、doGetBean加载概述:
AbstractBeanFactory.doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
doGetBean()
1. 首先这里会将传入的beanName进行转化。代码如下所示:
转化有两个步骤,首先处理beanName为&XXX的格式,这里表示要取指定name的factoryBean。在这里先把&符号取消,先获取bean再处理。然后,针对bean的alias机制,这里传入的参数可能是一个bean别名,那么我们先获取这个bean的主要id,只需要根据id值取bean就可以了。
2.判断这个beanName的bean是否已经创建了【缓存获取】,代码如下:
3.尝试从父容器中寻找,这一点和classLoader的父子加载机制相同。代码如下所示
4.获取bean定义信息
这里会对bean信息进行一个封装,主要是处理parent信息和scope信息。将这些信息进行一次定义融合,同时接下来对bean进行检查。
5. 处理依赖信息,这里会针对xml定义中的depends-on进行处理。如下面代码所示:
6.调用getSingleton(String beanName, ObjectFactory singletonFactory),最终会触发objectFactory的getObject方法,即调用createBean(beanName, mbd, args)方法进行bean创建。代码如下所示:
三、循环依赖
循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比如CircleA引用CircleB,CircleB引用CircleC,CircleC引用CircleA,则它们最终反映为一个环。此处不是循环调用,循环调用是方法之间的环调用。
Spring容器循环依赖包括构造器循环依赖和setter循环依赖,那Spring容器如何解决循环依赖呢?
- 构造器循环依赖:表示通过构造器注入构成的循环依赖,此依赖是无法解决的,只能抛出BeanCurrentlyInCreationException异常表示循环依赖。
如在创建CircleA类时,构造器需要CircleB类,那将去创建CircleB,在创建CircleB类时又发现需要CircleC类,则又去创建CircleC,最终在创建CircleC时发现又需要CircleA;从而形成一个环,没办法创建。
Spring容器将每一个正在创建的Bean 标识符放在一个“当前创建Bean池”中,Bean标识符在创建过程中将一直保持在这个池中,因此如果在创建Bean过程中发现自己已经在“当前创建Bean池”里时将抛出BeanCurrentlyInCreationException异常表示循环依赖;而对于创建完毕的Bean将从“当前创建Bean池”中清除掉。
- setter循环依赖:表示通过setter注入方式构成的循环依赖。
对于setter注入造成的依赖是通过Spring容器提前暴露刚完成构造器注入但未完成其他步骤(如setter注入)的Bean来完成的,而且只能解决单例作用域的Bean循环依赖。
四、doCreateBean()-bean生命周期
AbstractAutowireCapableBeanFactory.createBean(String, RootBeanDefinition, Object[])
在进入doCreateBean()之前,执行一次如下的操作:
我的理解:主要是处理实现了InstantiationAwareBeanPostProcessor的后置处理器,相当于给我们开发者一个在bean真正创建的的机会进行代理逃逸或者对配置做一些修改。
bean真正执行的函数:doCreateBean:
1:Bean的建立:
容器寻找Bean的定义信息并将其实例化。
(1)基于FactoryBean实例化
(2)基于构造器的实例化。
- 默认构造器或者是不带lookup或者replace配置方法时实例化使用java反射直接实现
- 否则使用动态代理将配置特性加入bean中
插一个过程,处理循环依赖的提前曝光策略:
2:属性注入:
使用依赖注入,Spring按照Bean定义信息配置Bean所有属性。
插一个过程:initializeBean():
后面的3-8的步骤均在此方法中调用:
3:BeanNameAware的setBeanName():
如果Bean类有实现org.springframework.beans.BeanNameAware接口,工厂调用Bean的setBeanName()方法传递Bean的ID。
4:BeanFactoryAware的setBeanFactory():
如果Bean类有实现org.springframework.beans.factory.BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身。
5:BeanPostProcessors的ProcessBeforeInitialization()
如果有org.springframework.beans.factory.config.BeanPostProcessors和Bean关联,那么其postProcessBeforeInitialization()方法将被将被调用。
6:initializingBean的afterPropertiesSet():
如果Bean类已实现org.springframework.beans.factory.InitializingBean接口,则执行他的afterProPertiesSet()方法
7:Bean定义文件中定义init-method:
可以在Bean定义文件中使用"init-method"属性设定方法名称例如:
如果有以上设置的话,则执行到这个阶段,就会执行initBean()方法
8:BeanPostProcessors的ProcessaAfterInitialization()
如果有任何的BeanPostProcessors实例与Bean实例关联,则执行BeanPostProcessors实例的ProcessaAfterInitialization()方法
五、Bean生命周期应用
自定义注解实现Logger
- spring bean的加载过程
- Spring bean的加载过程
- spring加载bean的过程
- spring bean加载过程
- Spring Bean加载过程
- SPRING 启动加载BEAN 的代码过程
- Spring中bean的加载过程
- spring bean的加载
- spring的bean加载
- 看看Spring的源码(一)——Bean加载过程
- 看看Spring的源码(一)——Bean加载过程
- 看看Spring的源码——Bean加载过程
- 工厂模式模拟Spring的bean加载过程
- Spring Bean加载过程(二)
- spring源码分析 加载bean过程
- Spring bean 标签加载、解析过程分析
- Spring bean 标签加载、解析过程分析
- XmlBeanFactory加载bean的过程
- Webrtc穿透转发通讯2-windows
- spoj 1812 LCS2(SAM+DP)
- 【SDK使用】sdk print方式
- 第三周项目一(2)
- 45.Scala中Context Bounds代码实战及其在Spark中的应用源码解析
- Spring bean的加载过程
- 汽车结构
- 前端之微信小程序总结
- new与malloc的不同
- 直接插入排序-->希尔排序
- C语言10个经典小程序--致新手
- libsvm用法
- Poj3660 Cow Contest 【传递闭包】
- SimpleAudioEngine音效的使用导致游戏出现卡顿记录