8-spring源码3.2.18解读+spring技术内幕(IOC容器的依赖注入(反射+递归调用))
来源:互联网 发布:淘宝客cms源码 编辑:程序博客网 时间:2024/05/18 03:02
1、导读
以上对IOC容器的初始化过程做了详细的分析,这个初始化过程完成的主要工作是在IOC容器中建立BeanDefinition数据映射。再次过程中并没有对Bean依赖关系进行注入,接下来将分析一下IOC容器是怎么样对Bean的依赖关系进行注入的。
假设当前IOC容器已经载入了用户定义的Bean信息,开始分析依赖注入的原理。首先,注意到依赖注入的过程是用户第一次向IOC容器索要Bean时触发的,当然也有例外,也就是我们可以在BeanDefinition信息中通过控制lazy-init属性来让容器完成对Bean的预实例化。这个预实例化实际上也是一个完成依赖注入的过程,但它在初始化的过程中完成的。当用户想IOC容器索要Bean时,如BeanFactory中,有一个getBean接口的定义,这个接口的实现就是触发依赖注入发生的地方,下面我们将从DefaultListableBeanFactory的基类AbstractBeanFactory入手getBean的实现。
2、AbstractBeanFactory类
//这里是对BeanFactory接口的实现,比如getBean接口方法
//这些getBean接口方法最终是通过调用doGetBean来实现的
public Object getBean(String name) throws BeansException {
return this.doGetBean(name, (Class)null, (Object[])null, false);
}
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return this.doGetBean(name, requiredType, (Object[])null, false);
}
public Object getBean(String name, Object... args) throws BeansException {
return this.doGetBean(name, (Class)null, args, false);
}
public <T> T getBean(String name, Class<T> requiredType, Object... args) throws BeansException {
return this.doGetBean(name, requiredType, args, false);
}
//这里是实际取得Bean的地方,也是触发依赖注入的地方
protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = this.transformedBeanName(name);
//先从缓存中取得Bean,处理那些已经被创建过的单例模式的Bean,对这种Bean的请求不需要重复的创建,直接返回即可
Object sharedInstance = this.getSingleton(beanName);
Object bean;
if(sharedInstance != null && args == null) {
if(this.logger.isDebugEnabled()) {
if(this.isSingletonCurrentlyInCreation(beanName)) {
this.logger.debug("Returning eagerly cached instance of singleton bean \'" + beanName + "\' that is not fully initialized yet - a consequence of a circular reference");
} else {
this.logger.debug("Returning cached instance of singleton bean \'" + beanName + "\'");
}
}
//这里的getObjectForBeanInstance完成的是FactoryBean的相关处理,以取得FactoryBean的生产结果。
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
} else {
if(this.isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
//这里对IOC容器中的BeanDefinition是否存在进行检查,检查是否能在当前BeanFactory中取得需要的Bean,如果在当前的工厂中取不到,则到双亲BeanFactory中去取,如果双亲工厂取不到,那就顺着双亲BeanFactory链一直往上查找
BeanFactory ex = this.getParentBeanFactory();
if(ex != null && !this.containsBeanDefinition(beanName)) {
String var24 = this.originalBeanName(name);
if(args != null) {
return ex.getBean(var24, args);
}
return ex.getBean(var24, requiredType);
}
if(!typeCheckOnly) {
this.markBeanAsCreated(beanName);
}
try {
//这里根据Bean的名字取得BeanDefinition
final RootBeanDefinition ex1 = this.getMergedLocalBeanDefinition(beanName);
this.checkMergedBeanDefinition(ex1, beanName, args);
//获取当前Bean的所有依赖Bean,这样会触发getBean的递归调用,直到取到一个没有任何的依赖Bean为止
String[] dependsOn = ex1.getDependsOn();
String[] scopeName;
if(dependsOn != null) {
scopeName = dependsOn;
int scope = dependsOn.length;
for(int ex2 = 0; ex2 < scope; ++ex2) {
String dependsOnBean = scopeName[ex2];
this.getBean(dependsOnBean);
this.registerDependentBean(dependsOnBean, beanName);
}
}
//这里通过调用createBean方法创建Singleton bean的实例,这里有一个回调函数getObject,会在getSingleton中调用ObjectFactory的createBean
if(ex1.isSingleton()) {
sharedInstance = this.getSingleton(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
try {
return AbstractBeanFactory.this.createBean(beanName, ex1, args);
} catch (BeansException var2) {
AbstractBeanFactory.this.destroySingleton(beanName);
throw var2;
}
}
});
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, ex1);
} else if(ex1.isPrototype()) {//这里是创建prototype bean的地方
scopeName = null;
Object var25;
try {
this.beforePrototypeCreation(beanName);
var25 = this.createBean(beanName, ex1, args);
} finally {
this.afterPrototypeCreation(beanName);
}
bean = this.getObjectForBeanInstance(var25, name, beanName, ex1);
} else {
String var26 = ex1.getScope();
Scope var27 = (Scope)this.scopes.get(var26);
if(var27 == null) {
throw new IllegalStateException("No Scope registered for scope \'" + var26 + "\'");
}
try {
Object var28 = var27.get(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
AbstractBeanFactory.this.beforePrototypeCreation(beanName);
Object var1;
try {
var1 = AbstractBeanFactory.this.createBean(beanName, ex1, args);
} finally {
AbstractBeanFactory.this.afterPrototypeCreation(beanName);
}
return var1;
}
});
bean = this.getObjectForBeanInstance(var28, name, beanName, ex1);
} catch (IllegalStateException var21) {
throw new BeanCreationException(beanName, "Scope \'" + var26 + "\' is not active for the current thread; " + "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", var21);
}
}
} catch (BeansException var23) {
this.cleanupAfterBeanCreationFailure(beanName);
throw var23;
}
}
//这里包含了对Bean类型检查,如果没有问题,则返回这个新创建的bean,这个bean已经包含了依赖关系的bean
if(requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
try {
return this.getTypeConverter().convertIfNecessary(bean, requiredType);
} catch (TypeMismatchException var22) {
if(this.logger.isDebugEnabled()) {
this.logger.debug("Failed to convert bean \'" + name + "\' to required type [" + ClassUtils.getQualifiedName(requiredType) + "]", var22);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
} else {
return bean;
}
}
- 8-spring源码3.2.18解读+spring技术内幕(IOC容器的依赖注入(反射+递归调用))
- Spring:源码解读(IOC容器的依赖注入)
- spring技术内幕5-IoC容器的依赖注入
- spring技术内幕笔记:IoC容器的依赖注入
- 《Spring技术内幕》学习笔记5——IoC容器的依赖注入
- 《Spring技术内幕》学习笔记5——IoC容器的依赖注入
- 《Spring技术内幕》学习笔记5——IoC容器的依赖注入
- 《Spring技术内幕》学习笔记5——IoC容器的依赖注入
- Ioc容器依赖注入-Spring 源码(2)
- Spring源码阅读(三)—IOC容器依赖注入
- Spring源码学习IOC(5):IOC容器的依赖注入
- 深入解读Spring Framework IoC容器(第二弹:依赖注入的方式)
- Spring技术内幕(一):IOC容器
- 【Spring源码--IOC容器的实现】(六)Bean的依赖注入
- Spring IOC容器的依赖注入(源码角度)
- 5-spring源码3.2.18解读+spring技术内幕(关于BeanDefinition的定位)
- 6-spring源码3.2.18解读+spring技术内幕(关于BeanDefinition的载入和解析)
- 7-spring源码3.2.18解读+spring技术内幕(关于BeanDefinition的注册)
- yuv420数据格式
- Web 安全 PHP 代码审查之常规漏洞
- HTTP
- 基于word2vec的短文本分析---开玩笑,分析什么,只是刚入门的自己的一些感受
- 查看进程死锁的命令
- 8-spring源码3.2.18解读+spring技术内幕(IOC容器的依赖注入(反射+递归调用))
- 线程池ThreadPool详解
- PHP正则匹配数字中英文及下划线
- 如何更加便捷地在Eclipse上开发GO语言
- [并行计算] 2. OpenMP简介
- B样曲线的绘制代码
- LeetCode
- Nginx安装及配置文件nginx.conf详解
- POJ 2395 Out of Hay