您的位置:首页 > 编程语言 > Java开发

Spring源码解析之Bean的加载

2017-01-02 20:25 309 查看
本文基于Spring4.2.7版本,由于Bean的处理是Spring的核心模块,所以版本之间也没有太大的差异

从源码中看端倪

相信大家多少有些基本的概念了,我们就从源码中来看看Spring是如何加载Bean的。

java
// 从IOC容器中获取bean的基本方法
// 了解Spring的同学应该知道,getXXX往往是预处理,doGetXXX才是真正的获取
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {

// 如果是bean的别名或者bean的工厂名都会在这里处理掉
// bean的工厂名(bean名称前加&符号)也是Spring用于防止循环依赖和松耦合的创新方法
final String beanName = transformedBeanName(name);
Object bean;

// 首先在单例集合中取,大多数情况下,交给IOC管理的Bean都是单例的
// 而且也只有单例模式会存在循环依赖的问题
Object sharedInstance = getSingleton(beanName);
// 如果指定了参数的
if (sharedInstance != null && args == null) {
// 这里有个小技巧,先判断能否输出日志,再进行组装字符串,避免费劲组装了一大堆字符串却又不需要输出的情况,在工作中可以借鉴
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
////根据给定的实例是否为工厂Bean,返回它自己或工厂Bean创建的实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

else {
if (isPrototypeCurrentlyInCreation(beanName)) {//如果正在被创建,就抛出异常
throw new BeanCurrentlyInCreationException(beanName);
}

BeanFactory parentBeanFactory = getParentBeanFactory();//取本容器的父容器
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {//若存在父容器,且本容器不存在对应的Bean定义
String nameToLookup = originalBeanName(name);//取原始的Bean名
if (args != null) {//若参数列表存在
// 那么用父容器根据原始Bean名和参数列表返回
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// 参数列表不要求,那就直接根据原始名称和要求的类型返回
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}

//如果不需要类型检查,标记其已经被创建
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}

//根据beanName取其根Bean定义
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);

String[] dependsOn = mbd.getDependsOn();//得到这个根定义的所有依赖
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
getBean(dependsOnBean);//注册这个Bean
//注册一个Bean和依赖于它的Bean(后参数依赖前参数)
registerDependentBean(dependsOnBean, beanName);
}
}

// 如果Bean定义是单例,就在返回单例
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
}
});
//根据给定的实例是否为工厂Bean,返回它自己或工厂Bean创建的实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
//如果是原型
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);//原型创建前,与当前线程绑定
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);//原型创建后,与当前线程解除绑定
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}

else {//既不是单例又不是原型的情况
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);//得到范围
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
}
try {//根据范围创建实例
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);//原型创建前,与当前线程绑定
}
finally {
////原型创建后,与当前线程解除绑定
afterPrototypeCreation(beanName);
}
}
});
//根据给定的实例是否为工厂Bean,返回它自己或工厂Bean创建的实例
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' 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",
ex);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: