Spring IoC源码解析之getBean,血与泪的总结

本文详细解析了Spring IoC容器在getBean过程中的核心逻辑,包括从缓存获取对象、处理循环依赖、父工厂委托、单例与原型实例化等步骤。通过源码分析,揭示了Spring如何解决setter注入的循环依赖,以及在创建Bean过程中的各种处理策略。

getAccessControlContext());

}

else {

isEagerInit = (factory instanceof SmartFactoryBean &&

((SmartFactoryBean<?>) factory).isEagerInit());

}

//调用真正的getBean

if (isEagerInit) {

getBean(beanName);

}

}

}

else {//非工厂Bean就是普通的bean

getBean(beanName);

}

}

}

//获取所有的bean的名称 至此所有的单实例的bean已经加入到单实例Bean的缓存池中,所谓的单实例缓存池实际上就是一个ConcurrentHashMap

for (String beanName : beanNames) {

//从单例缓存池中获取所有的对象

Object singletonInstance = getSingleton(beanName);

//判断当前的bean是否实现了SmartInitializingSingleton接口

if (singletonInstance instanceof SmartInitializingSingleton) {

final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;

if (System.getSecurityManager() != null) {

AccessController.doPrivileged((PrivilegedAction) () -> {

smartSingleton.afterSingletonsInstantiated();

return null;

}, getAccessControlContext());

}

else {

//触发实例化之后的方法afterSingletonsInstantiated

smartSingleton.afterSingletonsInstantiated();

}

}

}

}

复制代码

前面多个地方涉及到getBean,接下来就分析下getBean(很重要

二、getBean流程


进入getBean(beanName)的方法:

@Override

public Object getBean(String name) throws BeansException {

//真正的获取Bean的逻辑

return doGetBean(name, null, null, false);

}

该方法啥没干,又交给了干活的doGetBean(name, null, null, false)方法:

复制代码

protected T doGetBean(final String name, @Nullable final Class requiredType,

@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

//在这里传入进来的name可能是别名、也有可能是工厂beanName,所以在这里需要转换

final String beanName = transformedBeanName(name);

Object 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 + “’”);

}

}

/**

* 如果sharedInstance是普通的单例bean,下面的方法会直接返回。但如果

* sharedInstance是FactoryBean类型的,则需调用getObject工厂方法获取真正的

* bean实例。如果用户想获取 FactoryBean 本身,这里也不会做特别的处理,直接返回

* 即可。毕竟 FactoryBean 的实现类本身也是一种 bean,只不过具有一点特殊的功能而已。

*/

bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);

}

else {

//Spring只能解决单例对象的setter注入的循环依赖,不能解决构造器注入,也不能解决多实例的循环依赖

if (isPrototypeCurrentlyInCreation(beanName)) {

throw new BeanCurrentlyInCreationException(beanName);

}

//判断是否有父工厂

BeanFactory parentBeanFactory = getParentBeanFactory();

//若存在父工厂,切当前的bean工厂不存在当前的bean定义,那么bean定义是存在于父beanFactory中

if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {

//获取bean的原始名称

String nameToLookup = originalBeanName(name);

//若为AbstractBeanFactory类型,委托父类处理

if (parentBeanFactory instanceof AbstractBeanFactory) {

return ((AbstractBeanFactory) parentBeanFactory).doGetBean(

nameToLookup, requiredType, args, typeCheckOnly);

}

else if (args != null) {

// 委托给构造函数getBean()处理

return (T) parentBeanFactory.getBean(nameToLookup, args);

}

else {

// 没有args,委托给标准的getBean()处理

return parentBeanFactory.getBean(nameToLookup, requiredType);

}

}

/**

* 方法参数typeCheckOnly ,是用来判断调用getBean(…) 方法时,表示是否为仅仅进行类型检查获取Bean对象

* 如果不是仅仅做类型检查,而是创建Bean对象,则需要调用markBeanAsCreated(String beanName) 方法,进行记录

*/

if (!typeCheckOnly) {

markBeanAsCreated(beanName);

}

try {

//从容器中获取beanName相应的GenericBeanDefinition对象,并将其转换为RootBeanDefinition对象

final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);

//检查当前创建的bean定义是不是抽象的bean定义

checkMergedBeanDefinition(mbd, beanName, args);

//处理dependsOn的依赖(这个不是我们所谓的循环依赖 而是bean创建前后的依赖)

//依赖bean的名称

String[] dependsOn = mbd.getDependsOn();

if (dependsOn != null) {

for (String dep : dependsOn) {

//beanName是当前正在创建的bean,dep是正在创建的bean的依赖的bean的名称

if (isDependent(beanName, dep)) {

throw new BeanCreationException(mbd.getResourceDescription(), beanName,

“Circular depends-on relationship between '” + beanName + “’ and '” + dep + “’”);

}

//保存的是依赖beanName之间的映射关系:依赖beanName -> beanName的集合

registerDependentBean(dep, beanName);

try {

//获取dependsOn的bean

getBean(dep);

}

catch (NoSuchBeanDefinitionException ex) {

throw new BeanCreationException(mbd.getResourceDescription(), beanName,

“’” + beanName + “’ depends on missing bean '” + dep + “’”, ex);

}

}

}

//是单例则创建单例Bean

if (mbd.isSingleton()) {

//把beanName和一个singletonFactory匿名内部类传入用于回调

sharedInstance = getSingleton(beanName, () -> {

try {

//创建bean的逻辑

return createBean(beanName, mbd, args);

}

catch (BeansException ex) {

//创建bean的过程中发生异常,需要销毁关于当前bean的所有信息

destroySingleton(beanName);

throw ex;

}

});

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 name '” + scopeName + “’”);

}

try {

Object scopedInstance = scope.get(beanName, () -> {

beforePrototypeCreation(beanName);

try {

return createBean(beanName, mbd, args);

}

finally {

afterPrototypeCreation(beanName);

}

});

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);

}

}

}

catch (BeansException ex) {

cleanupAfterBeanCreationFailure(b

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值