软件编程
位置:首页>> 软件编程>> java编程>> spring获取bean的源码解析

spring获取bean的源码解析

作者:not back  发布时间:2023-10-11 22:15:43 

标签:spring,bean,源码

介绍

前面一章说了AbstractApplicationContext中的refresh方法中的invokeBeanFactoryPostProcessors。主要是调用BeanFactoryPostProcessor。其中也有获取bean的过程,就是beanFactory.getBean的方法。这一章就说下getBean这个方法。由于spring中获取bean的方法比较复杂,涉及到的流程也非常多,这一章就先说下整个大体的流程。其中的细节会在后面也会慢慢说。

源码

直接看源码吧


@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}

@Override
public <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}

@Override
public Object getBean(String name, Object... args) throws BeansException {
return doGetBean(name, null, args, false);
}

public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args)
throws BeansException {

return doGetBean(name, requiredType, args, false);
}

@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

// 把name转化成beanName,也就是把FactoryBean的名称转化成beanName如果有别名则用别名
final String beanName = transformedBeanName(name);
Object bean;

// 从缓存中获取实例
       // 可能是需要的Bean实例,也可能是FactoryBean
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或者FactoryBean
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

else {
// 判断prototype类型的bean是否存在循环引用
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}

// 校验父类BeanFactory
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 父类去获取bean
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
}
else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}

// 标记成已创建
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}

try {
               // 把原来BeanDefinition转换成RootBeanDefinition
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);

// 获取依赖的bean,也就是通过@DependsOn注入进来的bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
                       // 校验dependsOn的bean是否存在循环应用
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
                       // 加入到引用的缓存中,由于校验dependsOn循环引用
registerDependentBean(dep, beanName);
                       // 获取@dependsOn的bean
getBean(dep);
}
}

// 创建单例的bean
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
                   // 获取需要的bean或者FactoryBean
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
               // 创建prototype的bean
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);
}
               // 创建其他的bean,比如session,request等
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(beanName);
throw ex;
}
}

// 如果要求的类型不是这个bean的实例类型,则进行转换
if (requiredType != null && !requiredType.isInstance(bean)) {
try {
T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
if (convertedBean == null) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return convertedBean;
}
catch (TypeMismatchException ex) {
if (logger.isDebugEnabled()) {
logger.debug("Failed to convert bean '" + name + "' to required type '" +
ClassUtils.getQualifiedName(requiredType) + "'", ex);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
}
return (T) bean;
}

获取bean的整体流程就像上面源码所示,这里再梳理下spring获取bean的整个流程

1.先转换bean的名称,转换成beanName。这里意思就是,我们在获取bean的时候,可能是FactoryBean的名称(&开头),这里转成不带&开头的名称,如果有别名,再获取别名。

2.从缓存中获取bean,这里的缓存分为一二 * 缓存,也就是我们常常被问到了spring * 缓存,具体逻辑下面再说。

3.根据获取的到对象再去获取我们想要的bean,因为这里获取到的对象可能是我们需要的bean,也可能是FactoryBean。

4.如果缓存中没有,那么我们就要自己去创建bean了。

5.查看有没有父类的BeanFactory,如果有,那么就父类去创建bean。

6.获取要创建的bean对象的@DependsOn注解上的名称,先去创建DependsOn的bean,并且校验是否存在循环引用

7.创建bean,根据类型创建不同的bean,比如singleton,prototype,request,session等。

8.如果需要转换类型,则进行类型转换。

整体的获取bean的流程就是这样了,其中有些具体流程接着分析。

从缓存中获取bean对象


public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}

@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
       // 从一级缓存中获取
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
               // 从二级缓存中获取
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
                   // 从 * 缓存中获取
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}

spring通过 * 缓存来解决循环依赖的问题。简单来介绍下 * 缓存。

1. singletonObjects为一级缓存,我们实例化的bean都在这个map里,侠义的说singletonObjects才是我们真正的spring容器,存放bean的地方。

2. earlySingletonObjects为二级缓存,是存放未完成的bean的缓存,如果有代理的话,存放的是代理对象。

3. singletonFactories为 * 缓存,存放的是一个ObjectFactory,数据通过getObject方法获得。

从BeanInstance中获取对象

接下来看getObjectForBeanInstance方法。


protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

// name是不是factoryBean的name(&开头的)
if (BeanFactoryUtils.isFactoryDereference(name)) {
if (beanInstance instanceof NullBean) {
return beanInstance;
}
           // 如果是FactoryBeanName,但是获取到的bean不是FactoryBean,则抛异常
if (!(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
}
}

// 如果bean不是FactoryBean,或者名称是FactoryBeanName,直接返回BeanInstace
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
}

Object object = null;
if (mbd == null) {
           // 从缓存中获取
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// 这里可以确定beanInstance是FactoryBean了
FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
           // 通过FactoryFBean中获取需要的beanInstance
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}

这里是通过BeanInstance获取我们想要的bean,这里也简单说下流程

1. 首先判断name是不是FactoryBean的name,也就是&开头的name,如果是去判断beanInstance是不是FactoryBean,如果beanInstance不是FactoryBean则抛异常。

2. 由于上面已经判断过,如果name是FactoryBeanName,但是BeanInstance不是FactoryBean的话,就会抛出异常。所以如果BeanInstance如果不是FactoryBean的话,那么name一定不是FactoryBeanName。那么就直接返回BeanInstance就是我们需要的了。

如果name是FactoryBeanName,那么我们需要获取的就是FactoryBean,也直接返回就可以了。

3. 如果都没有返回,那么已经可以确定我们此时的已经可以确定BeanInstance是FactoryBean了,因为如果不是FactoryBean的话,在!(beanInstance instanceof FactoryBean)就已经返回了。

4. 通过FactoryBean的getObject方法获取我们需要的bean实例。

创建bean

根据@dependsOn查找依赖的bean并且加到依赖里面去没有什么好说的,代码逻辑也很简单,接下来看创建单例bean。其他类型的bean的创建也都差别不大。看源码


public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
synchronized (this.singletonObjects) {
           // 直接从一级缓存中取
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
               // 在没创建bean之前的处理
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
                   // 获取创建的bean
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
catch (IllegalStateException ex) {
// Has the singleton object implicitly appeared in the meantime ->
// if yes, proceed with it since the exception indicates that state.
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
throw ex;
}
}
catch (BeanCreationException ex) {
if (recordSuppressedExceptions) {
for (Exception suppressedException : this.suppressedExceptions) {
ex.addRelatedCause(suppressedException);
}
}
throw ex;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
                   // 创建结束之后的工作
afterSingletonCreation(beanName);
}
if (newSingleton) {
                   // 加到一级缓存中,其实也就是真正的容器中了
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}

对于创建单例bean的主要流程就是如此,传入一个beanName,和一个ObjectFactory。ObjectFactory中具体实现了创建bean的逻辑。在看具体创建bean的逻辑之前,我们还需要去看下getSingleton中的创建bean之前的工作和创建bean之后的工作。这里面就是查找bean的循环依赖的方法(和dependsOn不同)。主要是查找根据filed,set,构造器方法的循环依赖。


protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}

protected void afterSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
}
}

可以看到代码非常的简单,就是创建bean之前,如果没有排除依赖检查,那么就加入到正在创建的Set中,如果加入不进去,说明之前已经加过,这就产生了循环依赖,从而抛出异常。

如果在创建bean之后,没有排除检查依赖,并且移除失败,说明已经不在Set中,也会抛出异常。

来源:https://blog.csdn.net/xby7437/article/details/116059853

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com