ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

SpringBoot 源码解析6:Bean的创建① AbstractBeanFactory#doGetBean

SpringBoot 源码解析6:Bean的创建① AbstractBeanFactory#doGetBean

SpringBoot 源码解析6:Bean的创建① AbstractBeanFactory#doGetBean

    • 1.概述
    • 2. AbstractBeanFactory#doGetBean源码分析
      • 2.1 转换bean的名称 transformedBeanName
      • 2.2. FactoryBean兼容
        • 2.2.1 getObjectForBeanInstance
        • 2.2.2 FactoryBeanRegistrySupport#getObjectFromFactoryBean
        • 2.2.3 Demo
      • 2.3 三级缓存
        • 2.3.1 属性
        • 2.3.2 从缓存中获取
        • 2.3.3 添加缓存
      • 2.4 @DependsOn原理
        • 2.4.1 @DependsOn注解解析
        • 2.4.2 depends属性应用
        • 2.4.3 依赖关系管理 DefaultSingletonBeanRegistry#registerDependentBean

1.概述

  1. AbstractBeanFactory#doGetBean方法是Spring创建Bean的核心方法。在此之前Spring已经将BeanDefinition注册到了DefaultListableBeanFactory#beanDefinitionMap。而doGetBean方法会根据BeanDefinition实例化Bean,并且初始化Bean的属性。
  2. AbstractBeanFactory#doGetBean方法是获取Bean的核心入口方法。如果单例池中存在,则返回Bean;不存在,则创建Bean。

2. AbstractBeanFactory#doGetBean源码分析

/*** Return an instance, which may be shared or independent, of the specified bean.* @param name the name of the bean to retrieve* @param requiredType the required type of the bean to retrieve* @param args arguments to use when creating a bean instance using explicit arguments* (only applied when creating a new instance as opposed to retrieving an existing one)* @param typeCheckOnly whether the instance is obtained for a type check,* not for actual use* @return an instance of the bean* @throws BeansException if the bean could not be created*/
@SuppressWarnings("unchecked")
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {// 1.转换Bean的名称final String beanName = transformedBeanName(name);Object bean;// Eagerly check singleton cache for manually registered singletons.// 2.先校验单例Bean是否已存在,或者手动创建了单例。存在的bean会放在singletonObjects(单例池)中Object sharedInstance = getSingleton(beanName);if (sharedInstance != null && args == null) {if (logger.isTraceEnabled()) {if (isSingletonCurrentlyInCreation(beanName)) {logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +"' that is not fully initialized yet - a consequence of a circular reference");}else {logger.trace("Returning cached instance of singleton bean '" + beanName + "'");}}// 2.1. 从Bean的实例里面获取对象,这里体现了对FactoryBean的兼容性bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);}else {// Fail if we're already creating this bean instance:// We're assumably within a circular reference.// 如果当前的Bean没有被实例化,假设在循环依赖里面// 3. 循环依赖是不循序原型模式的if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}// Check if bean definition exists in this factory.BeanFactory parentBeanFactory = getParentBeanFactory();// 4.如果当前的Bean工厂中没有注册BeanDefinition,就委派父Bean工厂去实例化if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {// Not found -> check parent.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 if (requiredType != null) {// No args -> delegate to standard getBean method.return parentBeanFactory.getBean(nameToLookup, requiredType);}else {return (T) parentBeanFactory.getBean(nameToLookup);}}if (!typeCheckOnly) {// 5.标记当前Bean已创建markBeanAsCreated(beanName);}try {// 6.合并BeanDefinition,将当前的BeanDefinition与当前BeanDefinition中的parentName所指向的BeanDefinition的属性合并。当前的属性覆盖父BeanDefinition的属性final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);// 7.校验BeanDefinitioncheckMergedBeanDefinition(mbd, beanName, args);// Guarantee initialization of beans that the current bean depends on.// 8.处理依赖关系,@DependsOn注解String[] dependsOn = mbd.getDependsOn();if (dependsOn != null) {// 8.1.存在依赖的Bean,就先去加载需要依赖的Beanfor (String dep : dependsOn) {// 8.2.判断是否存在循环依赖if (isDependent(beanName, dep)) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");}// 8.3.保存Bean的依赖关系registerDependentBean(dep, beanName);try {//8.4.创建所依赖的BeangetBean(dep);}catch (NoSuchBeanDefinitionException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"'" + beanName + "' depends on missing bean '" + dep + "'", ex);}}}// Create bean instance.// 9.创建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 = 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(beanName);throw ex;}}// Check if required type matches the type of the actual bean instance.// 10.校验从Spring中获取的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.isTraceEnabled()) {logger.trace("Failed to convert bean '" + name + "' to required type '" +ClassUtils.getQualifiedName(requiredType) + "'", ex);}throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}}return (T) bean;
}
  1. 转换Bean的名称,先去掉beanName前缀&,再使用别名获取bean。如果是FactoryBean,那么bean的名称是以"&"开头的。
  2. getObjectForBeanInstance:兼容FactoryBean
    2.1. 跟普通的bean一样,FactoryBean类型的单例创建完毕之后都会保存到单例池。
    2.2. 校验单例Bean是否已存在,存在有两种情况:
    情况1:第一种情况是手动注册到单例池,比如调用DefaultSingletonBeanRegistry#registerSingleton。
    情况2:通过BeanDefinition创建单例。
    但是,不管是哪种情况,创建成功之后都可以通过DefaultSingletonBeanRegistry#getSingleton从Spring的三级缓存中获取。
    2.3. getObjectForBeanInstance方法,通过bean的名称获取bean。
  3. 在Spring中原型模式是不允许循环依赖的。因为ClassA 和 ClassB循环依赖,创建对象的过程为 A1 -> B1 -> A2 -> B2 -> A3 -> B3 -> B4…这样就无法完成Bean的属性的初始化。
  4. 如果当前的Bean工厂中没有注册BeanDefinition,就委派父Bean工厂去实例化。递归。
  5. 标记当前Bean已创建,后面对属性的初始化、代理、三级缓存获取等很多地方都用到了这个标识。
  6. 合并BeanDefinition,将当前的BeanDefinition与当前BeanDefinition中的parentName所指向的BeanDefinition的属性合并。当前的属性覆盖父BeanDefinition的属性。
  7. 校验BeanDefinition,校验了是否为Abstract。
  8. 处理dependsOn。
    8.1 @DependsOn属性解析在AnnotationConfigUtils#processCommonDefinitionAnnotations中完成的。SpringBoot 源码解析5:ConfigurationClassPostProcessor整体流程和@ComponentScan源码分析
    8.2 如果有DependsOn,那么就先实例化DependsOn,两个Bean是不能相互DependsOn。调用getBean方法将所有依赖的Bean创建完毕之后,才创建当前的Bean。注册和校验Bean的依赖关系是通过两个缓存dependentBeanMap和dependenciesForBeanMap完成的。
  9. 支持单例、原型、scope三种方式创建Bean。
  10. 校验通过beanName创建的Bean与限定的类型是否一致,不一致就会抛出异常。因为Spring提供了同时支持beanName和beanType获取Bean。

2.1 转换bean的名称 transformedBeanName

protected String transformedBeanName(String name) {return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}//BeanFactoryUtils.transformedBeanName
public static String transformedBeanName(String name) {Assert.notNull(name, "'name' must not be null");if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {return name;}return transformedBeanNameCache.computeIfAbsent(name, beanName -> {do {beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());}while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));return beanName;});
}public String canonicalName(String name) {String canonicalName = name;// Handle aliasing...String resolvedName;do {resolvedName = this.aliasMap.get(canonicalName);if (resolvedName != null) {canonicalName = resolvedName;}}while (resolvedName != null);return canonicalName;
}
  1. 在循环里面将beanName去除所有以"&"开头的字符,添加了缓存transformedBeanNameCache。
  2. 通过去除"&"之后的名称,获取别名。

2.2. FactoryBean兼容

2.2.1 getObjectForBeanInstance
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {// Don't let calling code try to dereference the factory if the bean isn't a factory.//如果是以&开头,那么需要获取的bean就是factoryBean。if (BeanFactoryUtils.isFactoryDereference(name)) {if (beanInstance instanceof NullBean) {return beanInstance;}if (!(beanInstance instanceof FactoryBean)) {throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());}if (mbd != null) {mbd.isFactoryBean = true;}return beanInstance;}// Now we have the bean instance, which may be a normal bean or a FactoryBean.// If it's a FactoryBean, we use it to create a bean instance, unless the// caller actually wants a reference to the factory.// 如果不是普通的bean,就直接返回if (!(beanInstance instanceof FactoryBean)) {return beanInstance;}Object object = null;if (mbd != null) {mbd.isFactoryBean = true;}else {//对factoryBean进行缓存,体现了单例factoryBean的特性object = getCachedObjectForFactoryBean(beanName);}if (object == null) {// Return bean instance from factory.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());//回调factoryBean#getObject获取Beanobject = getObjectFromFactoryBean(factory, beanName, !synthetic);}return object;
}
  1. 参数说明
    beanInstance:从单例池中获取的bean,这个bean可能是factoryBean
    name:通过getBean方法想要获取bean的名称
    beanName: name去除所有&前缀之后的名称
    mbd: bean的定义信息
  2. 获取factoryBean:用户可以获取factoryBean这个对象,也可以获取factoryBean#getObject方法的返回值的对象。
    2.1. 如果传入的bean的name是普通的,即不以&开头,获取的对象就是回调factoryBean#getObject方法的返回值,这也是FactoryBean的特性。
    2.2. 当然,如果用户一定要获取FactoryBean的对象,Spring也是支持的。如果beanName是以&开头,那么Spring就认为用户要获取的对象一定是FactoryBean,即不会回调factoryBean#getObject。并且Spring还校验了这个bean的类型一定是FactoryBean,否则会抛出BeanIsNotAFactoryException。
  3. 如何支持单例:因为每一次调用factoryBean#getObject返回的对象地址是不一样的,为了保证获取的对象是单例,添加了缓存FactoryBeanRegistrySupport#factoryBeanObjectCache。
2.2.2 FactoryBeanRegistrySupport#getObjectFromFactoryBean
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {if (factory.isSingleton() && containsSingleton(beanName)) {synchronized (getSingletonMutex()) {Object object = this.factoryBeanObjectCache.get(beanName);if (object == null) {object = doGetObjectFromFactoryBean(factory, beanName);// Only post-process and store if not put there already during getObject() call above// (e.g. because of circular reference processing triggered by custom getBean calls)Object alreadyThere = this.factoryBeanObjectCache.get(beanName);if (alreadyThere != null) {object = alreadyThere;}else {if (shouldPostProcess) {if (isSingletonCurrentlyInCreation(beanName)) {// Temporarily return non-post-processed object, not storing it yet..return object;}beforeSingletonCreation(beanName);try {object = postProcessObjectFromFactoryBean(object, beanName);}catch (Throwable ex) {throw new BeanCreationException(beanName,"Post-processing of FactoryBean's singleton object failed", ex);}finally {afterSingletonCreation(beanName);}}if (containsSingleton(beanName)) {this.factoryBeanObjectCache.put(beanName, object);}}}return object;}}else {Object object = doGetObjectFromFactoryBean(factory, beanName);if (shouldPostProcess) {try {object = postProcessObjectFromFactoryBean(object, beanName);}catch (Throwable ex) {throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);}}return object;}
}
  1. 这是从FactoryBean获取Bean具体方法。
  2. 分为单例和非单例。如果是单例,使用了缓存。非单例,就没有放入缓存,直接创建bean。FactoryBean#getObject具体回调是在FactoryBeanRegistrySupport#doGetObjectFromFactoryBean中完成的。
2.2.3 Demo

虽然本系列只是做源码分析,还是写一个demo吧!!!

FactoryBean

@Component
public class FactoryBeanTest implements FactoryBean<Object> {@Overridepublic Object getObject() throws Exception {return new Object();}@Overridepublic Class<?> getObjectType() {return Object.class;}
}

启动类

public static void main(String[] args) {ConfigurableApplicationContext run = SpringApplication.run(MyApplication.class, args);Object obj = run.getBean("factoryBeanTest");System.out.println(obj.getClass());Object factoryBean = run.getBean("&factoryBeanTest");System.out.println(factoryBean.getClass());}

可以看到,factoryBeanTest打印的是回调getObject之后的bean,而&factoryBeanTest打印的就是FactoryBean的本身。

在这里插入图片描述

2.3 三级缓存

2.3.1 属性
/** Cache of singleton objects: bean name to bean instance. */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);/** Cache of singleton factories: bean name to ObjectFactory. */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);/** Cache of early singleton objects: bean name to bean instance. */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

这三个Map的key都为beanName

  1. singletonObjects :一级缓存,存放的值为Bean。并且bean中的属性已初始化完毕。@Autowired、@Resource注解处理完毕。
  2. earlySingletonObjects : 二级缓存,存放的为Bean。但是Bean中的属性可能没有初始化,也有可能初始化了一部分。
  3. singletonFactories :三级缓存,存放的为ObjectFactory。通过源码看ObjectFactory是FunctionalInterface。回调该函数式接口才能返回Bean。

面试题:为什么需要三级缓存singletonFactories?代理。三级缓存里面判断是否有代理对象,有代理对象就返回单例对象(没有就返回当前对象),放入到二级缓存。AbstractAutoProxyCreator#earlyProxyReferences中缓存了代理的对象。

2.3.2 从缓存中获取
protected Object getSingleton(String beanName, boolean allowEarlyReference) {//1.从一级缓存中获取BeanObject singletonObject = this.singletonObjects.get(beanName);//一级缓存中不存在,并且当前的Bean是单例并且正在创建中if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {synchronized (this.singletonObjects) {//2.从二级缓存中获取singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null && allowEarlyReference) {//3.获取三级缓存ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);if (singletonFactory != null) {//回调三级缓存singletonObject = singletonFactory.getObject();//放入三级缓存this.earlySingletonObjects.put(beanName, singletonObject);//移除二级缓存this.singletonFactories.remove(beanName);}}}}return singletonObject;
}

源码解析如注释。逐级获取, 一级缓存 -> 二级缓存 -> 三级缓存。
三级缓存是FunctionalInterface,如下

@FunctionalInterface
public interface ObjectFactory<T> {/*** Return an instance (possibly shared or independent)* of the object managed by this factory.* @return the resulting instance* @throws BeansException in case of creation errors*/T getObject() throws BeansException;}
2.3.3 添加缓存
/*** Add the given singleton object to the singleton cache of this factory.* <p>To be called for eager registration of singletons.* @param beanName the name of the bean* @param singletonObject the singleton object*/
protected void addSingleton(String beanName, Object singletonObject) {synchronized (this.singletonObjects) {//添加一级缓存,移除二级、三级缓存this.singletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);this.earlySingletonObjects.remove(beanName);this.registeredSingletons.add(beanName);}
}/*** Add the given singleton factory for building the specified singleton* if necessary.* <p>To be called for eager registration of singletons, e.g. to be able to* resolve circular references.* @param beanName the name of the bean* @param singletonFactory the factory for the singleton object*/
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {Assert.notNull(singletonFactory, "Singleton factory must not be null");synchronized (this.singletonObjects) {if (!this.singletonObjects.containsKey(beanName)) {this.singletonFactories.put(beanName, singletonFactory);this.earlySingletonObjects.remove(beanName);this.registeredSingletons.add(beanName);}}
}
  1. addSingleton添加一级缓存,将二级、三级缓存清除。
  2. addSingletonFactory添加三级缓存,首先判断了一级缓存中是否存在,不存在则添加三级缓存,并且移除二级缓存。
  3. 可以简单的理解为同一时间只会保存在一个缓存。

2.4 @DependsOn原理

2.4.1 @DependsOn注解解析

扫描到一个Bean需要被Spring管理后,就会生成Bean的定义信息,也就是BeanDefinition。而DependsOn的属性也会封装到BeanDefinition中。

想要知道一个Bean是否要被Spring管理,请参考@ComponentScan原理。SpringBoot 源码解析5:ConfigurationClassPostProcessor整体流程和@ComponentScan源码分析

static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);if (lazy != null) {abd.setLazyInit(lazy.getBoolean("value"));}else if (abd.getMetadata() != metadata) {lazy = attributesFor(abd.getMetadata(), Lazy.class);if (lazy != null) {abd.setLazyInit(lazy.getBoolean("value"));}}if (metadata.isAnnotated(Primary.class.getName())) {abd.setPrimary(true);}AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);if (dependsOn != null) {abd.setDependsOn(dependsOn.getStringArray("value"));}AnnotationAttributes role = attributesFor(metadata, Role.class);if (role != null) {abd.setRole(role.getNumber("value").intValue());}AnnotationAttributes description = attributesFor(metadata, Description.class);if (description != null) {abd.setDescription(description.getString("value"));}
}

可以看到最终将DependsOn#value中的属性封装到AbstractBeanDefinition#dependsOn。而这些属性就是bean的名称。

2.4.2 depends属性应用
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {for (String dep : dependsOn) {if (isDependent(beanName, dep)) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");}registerDependentBean(dep, beanName);try {getBean(dep);}catch (NoSuchBeanDefinitionException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"'" + beanName + "' depends on missing bean '" + dep + "'", ex);}}
}
  1. 如果两个bean相互依赖,就会抛出异常。因为Spring的规则就是dependsOn的bean要先创建,如果相互依赖,Spring不知道优先创建哪一个bean。
  2. 在创建Bean的时候AbstractBeanFactory#doGetBean方法会优先加载AbstractBeanDefinition#dependsOn对应的bean,再创建当前的bean。
2.4.3 依赖关系管理 DefaultSingletonBeanRegistry#registerDependentBean
public void registerDependentBean(String beanName, String dependentBeanName) {String canonicalName = canonicalName(beanName);synchronized (this.dependentBeanMap) {Set<String> dependentBeans =this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));if (!dependentBeans.add(dependentBeanName)) {return;}}synchronized (this.dependenciesForBeanMap) {Set<String> dependenciesForBean =this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));dependenciesForBean.add(canonicalName);}
}
  1. 参数说明:
    beanName:依赖的bean名称
    dependentBeanName:当前正在创建的bean的名称
  2. Spring对一个Bean的依赖关系也进行了管理。其实不仅仅是对@DependsOn注解的关系,一个Bean的属性依赖另外一个bean也是通过这种方式进行管理的。
  3. 这种关系通过两个map进行管理。
    dependentBeanMap:如果A依赖B,那么key为B,value为A。
    dependenciesForBeanMap:如果A依赖B,那么key为A,value为B。
返回列表