1.getBean(beanName) 整体概述

1.transformedBeanName(name)

  • name可能是别名,将别名(alias)解析成真正的beanName
  • 截取&beanName中&字符,获得beanName

2.getSingleton(beanName) 从缓存中获取bean,有三个缓存集合,循环依赖会有单章讲解。

  • singletonObjects :缓存已经初始化完成的bean对象
  • earlySingletonObjects : 循环引用中,提前暴露的bean对象
  • singletonFactories :会调用getObject() 方法,返回一个earlyBean,放到earlySingletonObjects中,主要为了解决循环依赖时动态代理的问题

3.如果缓存中有bean对象,调用getObjectForBeanInstance 方法

  • 当前bean不是FactoryBean,直接返回对象
  • 当前bean是FactoryBean,且beanName中包换‘&’符号,直接放回对象。
  • 当前bean是FactoryBean,且beanName中不包含‘&’符号,调用当前bean的getObject()方法,返回getObject()方法的返回值。

4.如果bean中没有缓存对象

  • 检查是否有父工厂,有就要尝试从父工厂中拿,这里就实现了springmvc中的父子容器
  • 检查是否存在依赖的bean,有则优先实例化依赖的bean
  • 如果父工厂为空,或没有该bean,调用createBean(beanName, mbd, args)方法,创建对象,这里会判断scope类型,分别创建。

5.检查指定类型(requiredType)是否与获得Bean实例的类型匹配,不匹配就要使用转换器进行转换,转换失败就抛出异常。

6.返回最终bean对象。

    public Object getBean(String name) throws BeansException {return doGetBean(name, null, null, false);}protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)throws BeansException {//name可能是别名,将别名(alias)解析成真正的beanName//截取&beanName中&字符,获得beanNameString beanName = transformedBeanName(name);Object bean;// Eagerly check singleton cache for manually registered singletons.// 检查单例缓存中是否有单例对象Object sharedInstance = getSingleton(beanName);// 如果有bean的单例对象,且没有创建bean实例时要使用的参数if (sharedInstance != null && args == null) {// 当前bean不是FactoryBean,直接返回对象// 当前bean是FactoryBean,且beanName中包换‘&’符号,直接放回对象。// 当前bean是FactoryBean,且beanName中不包含‘&’符号,调用当前bean的getObject()        //         方法,返回getObject()方法的返回值。bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);}else {// 原型模式下如果存在循环依赖的情况,那么直接抛出异常if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}// 当前bean不存在,就检查是否有父工厂BeanFactory parentBeanFactory = getParentBeanFactory();// 如果当前工厂中不包含beanName,那么就尝试从父容器中获取if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {//如果name前面有'&',则会返回'&'+规范名称String nameToLookup = originalBeanName(name);// 如果父工厂是AbstractBeanFactoryif (parentBeanFactory instanceof AbstractBeanFactory) {// 调用父工厂的doGetBean方法return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);}//有参数else if (args != null) {return (T) parentBeanFactory.getBean(nameToLookup, args);}//有类型else if (requiredType != null) {// No args -> delegate to standard getBean method.// 没有创建bean实例时要使用的参数 -> 委托给标准的getBean方法。// 使用父工厂获取该bean对象,通bean全类名和所需的bean类型return parentBeanFactory.getBean(nameToLookup, requiredType);}else {return (T) parentBeanFactory.getBean(nameToLookup);}}if (!typeCheckOnly) {// 将beanName标记为已经创建markBeanAsCreated(beanName);}try {// 当前bean的BeanDefinition是否有parentBeanDefinition,如果有就需要合并RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);// 检查mbd是否时抽象的checkMergedBeanDefinition(mbd, beanName, args);// 如果是否存在依赖的bean,有则优先实例化依赖的beanString[] dependsOn = mbd.getDependsOn();if (dependsOn != null) {for (String dep : dependsOn) {// dep所指定的bean,和当前bean不能相互依赖if (isDependent(beanName, dep)) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");}// 注册依赖关系registerDependentBean(dep, beanName);try {// 实例化被依赖的BeangetBean(dep);}catch (NoSuchBeanDefinitionException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"'" + beanName + "' depends on missing bean '" + dep + "'", ex);}}}// Create bean instance.// 创建单例beanif (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, () -> {try {// 真正创建bean实例return createBean(beanName, mbd, args);}catch (BeansException ex) {destroySingleton(beanName);throw ex;}});// 当前bean不是FactoryBean,直接返回对象// 当前bean是FactoryBean,且beanName中包换‘&’符号,直接放回对象。// 当前bean是FactoryBean,且beanName中不包含‘&’符号,调用当前bean的        //            getObject()方法,返回getObject()方法的返回值。bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}// 原型模式的bean对象创建else if (mbd.isPrototype()) {Object prototypeInstance = null;try {// beanName添加到prototypesCurrentlyInCreation,标记为正在创建beforePrototypeCreation(beanName);// 创建一个bean实例prototypeInstance = createBean(beanName, mbd, args);}finally {// 将beanName从prototypesCurrentlyInCreation移除,表示创建完成afterPrototypeCreation(beanName);}// 当前bean不是FactoryBean,直接返回对象// 当前bean是FactoryBean,且beanName中包换‘&’符号,直接放回对象。// 当前bean是FactoryBean,且beanName中不包含‘&’符号,调用当前bean的        //            getObject()方法,返回getObject()方法的返回值。bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}else {String scopeName = mbd.getScope();if (!StringUtils.hasLength(scopeName)) {throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");}// springmvc中,有session 或 request作用域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, () -> {// 类似与ProtoType,不能循环依赖beforePrototypeCreation(beanName);try {//创建一个bean实例return createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}});// 当前bean不是FactoryBean,直接返回对象// 当前bean是FactoryBean,且beanName中包换‘&’符号,直接放回对象。// 当前bean是FactoryBean,且beanName中不包含‘&’符号,调用当前bean的        //            getObject()方法,返回getObject()方法的返回值。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) {// 在Bean创建失败后,对缓存的元数据执行适当的清理cleanupAfterBeanCreationFailure(beanName);throw ex;}}// 如果requiredType不为null&&bean不是requiredType的实例if (requiredType != null && !requiredType.isInstance(bean)) {try {// 获取类型转换器,将bean转换为requiredTypeT convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);// 如果convertedBean为null,转换失败if (convertedBean == null) {throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}return convertedBean;}catch (TypeMismatchException ex) {throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}}// 将bean返回return (T) bean;}

2.createBean()方法概述

1.resolveBeanClass(mbd, beanName) :获取当前bean的class对象,因为mbd中beanClassName属性值可能是字符串类型,需要反射加载。

2.mbdToUse.prepareMethodOverrides() :对lookup-method  replace-method 修饰的方法,设置为未覆盖(意味着需要后面进行覆盖)。后面bean实例化时会有方法和这里对应。

3.resolveBeforeInstantiation(beanName, mbdToUse) : 调用InstantiationAwareBeanPostProcessor后置处理器的postProcessBeforeInstantiation(),如果有对象返回,则后续实例化工作不再继续。bean的后置处理的分类在这里https://blog.csdn.net/weixin_41009314/article/details/117293706 有说明。

4.doCreateBean(beanName, mbdToUse, args) :创建bean对象。

    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {if (logger.isTraceEnabled()) {logger.trace("Creating instance of bean '" + beanName + "'");}RootBeanDefinition mbdToUse = mbd;// 锁定class,mbd中存储的可能是bean的Class对象,也可能是类的全限定类名的字符串。Class<?> resolvedClass = resolveBeanClass(mbd, beanName);// 全限定类名的字符串解析成Class对象,需要设置BeanClass属性,再次创建时可复用if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {// 重新创建一个RootBeanDefinition对象mbdToUse = new RootBeanDefinition(mbd);// 设置BeanClass属性值mbdToUse.setBeanClass(resolvedClass);}// 验证及准备覆盖的方法,lookup-method  replace-method,// 当需要创建的bean对象中包含了lookup-method和replace-method标签的时候,会产生覆盖操作try {mbdToUse.prepareMethodOverrides();}catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),beanName, "Validation of method overrides failed", ex);}try {//调用InstantiationAwareBeanPostProcessor后置处理器的postProcessBeforeInstantiation(),// 如果有对象返回,则后续实例化工作不再继续Object bean = resolveBeforeInstantiation(beanName, mbdToUse);if (bean != null) {return bean;}}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,"BeanPostProcessor before instantiation of bean failed", ex);}try {// 实际创建bean的调用Object beanInstance = doCreateBean(beanName, mbdToUse, args);if (logger.isTraceEnabled()) {logger.trace("Finished creating instance of bean '" + beanName + "'");}return beanInstance;}catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {// A previously detected exception with proper bean creation context already,// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.throw ex;}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);}}

3.doCreateBean()整体概述

1.创建bean对象,用BeanWrapper 类包装放回。

2.调用MergedBeanDefinitionPostProcessor 的postProcessMergedBeanDefinition()方法,主要用于@Autowire, @Resource 标记的属性注入(找到需要注入的属性并缓存)。

3.在三级缓存singletonFactories中添加getEarlyBeanReference()方法,用以解决循环依赖问题。

4.调用populateBean()方法,对bean的属性进行填充。

5.调用initializeBean()方法,对bean进行初始化。

6.假设exposedObject对象应该被代理,由于循环依赖提前生成了代理对象(earlySingletonObjects中),initializeBean()中返回的对象可能是未被代理,因此需要将提前生成的代理对象赋值给exposedObject,并返回。

    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {// 持有创建出来的bean对象BeanWrapper instanceWrapper = null;// 从缓存中获取if (mbd.isSingleton()) {// 如果是单例对象,从factorybean实例缓存中移除当前bean定义信息instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}// 没有就创建实例if (instanceWrapper == null) {instanceWrapper = createBeanInstance(beanName, mbd, args);}// 从包装类中获取beanObject bean = instanceWrapper.getWrappedInstance();// 获取具体的bean对象的Class属性Class<?> beanType = instanceWrapper.getWrappedClass();// 如果不等于NullBean类型,那么修改目标类型if (beanType != NullBean.class) {mbd.resolvedTargetType = beanType;}// Allow post-processors to modify the merged bean definition.// 允许beanPostProcessor去修改合并的beanDefinitionsynchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {try {// MergedBeanDefinitionPostProcessor后置处理器修改合并bean的定义applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Post-processing of merged bean definition failed", ex);}mbd.postProcessed = true;}}// Eagerly cache singletons to be able to resolve circular references// even when triggered by lifecycle interfaces like BeanFactoryAware.// 判断当前bean是否需要提前曝光:单例&允许循环依赖&当前bean正在创建中(检测循环依赖)boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));if (earlySingletonExposure) {// 为避免后期循环依赖,可以在bean初始化完成前将创建实例的ObjectFactory加入工厂addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));}// Initialize the bean instance.// 初始化bean实例Object exposedObject = bean;try {// 对bean的属性进行填充,将各个属性值注入,populateBean(beanName, mbd, instanceWrapper);// 执行初始化逻辑,动态代理也在这里实现exposedObject = initializeBean(beanName, exposedObject, mbd);}catch (Throwable ex) {if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {throw (BeanCreationException) ex;}else {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);}}if (earlySingletonExposure) {// 从缓存中获取具体的对象Object earlySingletonReference = getSingleton(beanName, false);// 检测到有循环依赖if (earlySingletonReference != null) {// 如果bean在循环依赖情况下,提前被代理,这里的exposedObject并不会被代理,因此需要赋值操作。if (exposedObject == bean) {exposedObject = earlySingletonReference;}else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {String[] dependentBeans = getDependentBeans(beanName);Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);for (String dependentBean : dependentBeans) {// 返回false说明依赖还没实例化好if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {actualDependentBeans.add(dependentBean);}}// 因为bean创建后所依赖的bean一定是已经创建的// actualDependentBeans不为空则表示当前bean创建后其依赖的bean却没有全部创建完,也就是说存在循环依赖if (!actualDependentBeans.isEmpty()) {throw new BeanCurrentlyInCreationException(beanName,"Bean with name '" + beanName + "' has been injected into other beans [" +StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +"] in its raw version as part of a circular reference, but has eventually been " +"wrapped. This means that said other beans do not use the final version of the " +"bean. This is often the result of over-eager type matching - consider using " +"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");}}}}// Register bean as disposable.try {// 注册bean对象,方便后续在容器销毁的时候销毁对象registerDisposableBeanIfNecessary(beanName, bean, mbd);}catch (BeanDefinitionValidationException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);}return exposedObject;}

4.createBeanInstance() 方法解析

1.判断beanDefinition 中是否设置Supplier,可提前实例化,不需要走后面推断构造器,再实例化的过程。

2.判断beanDefinition 中是否有工厂方法(FactoryMethod),可提前实例化,不需要走后面推断构造器,再实例化的过程。

3.判断构造方法是否已经解析过来,如果已经解析过,直接实例化, 没有解析过需要根据【注解@Autowire, 参数(propertyValues)】等推断构造方法,再实例化

​protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {// 获取bean的class对象Class<?> beanClass = resolveBeanClass(mbd, beanName);// class不为空,并且访问权限是publicif (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());}// 判断beanDefinition中是否设置InstanceSupplier,可通过种方式实例化对象。Supplier<?> instanceSupplier = mbd.getInstanceSupplier();if (instanceSupplier != null) {return obtainFromSupplier(instanceSupplier, beanName);}// 判断当前bean是否使用FactoryMethod实例化beanif (mbd.getFactoryMethodName() != null) {return instantiateUsingFactoryMethod(beanName, mbd, args);}// 标记当前bean的构造函数是否已经被解析boolean resolved = false;// 当前bean是否开启自动注入模式boolean autowireNecessary = false;if (args == null) {synchronized (mbd.constructorArgumentLock) {// resolvedConstructorOrFactoryMethod 保存已经被解析的构造方法if (mbd.resolvedConstructorOrFactoryMethod != null) {resolved = true;//constructorArgumentsResolved 表示进入过autowireConstructor()方法,也就是进行过自动注入autowireNecessary = mbd.constructorArgumentsResolved;}}}// 构造函数是否已经被解析if (resolved) {// 进行过自动注入if (autowireNecessary) {// 进行过自动注入,即使构造函数已经被解析过,还是需要进入自动注入的方法// 原因:在自动注入的情况下,构造函数可能不是无参构造,也就是会有参数//       下面的instantiateBean(beanName, mbd) 只能实例化无参构造,                //       autowireConstructor()即可以实例化无参构造,也可以实例化有参构造return autowireConstructor(beanName, mbd, null, null);}else {// 使用默认构造函数构造return instantiateBean(beanName, mbd);}}// 调用SmartInstantiationAwareBeanPostProcessor 的determineCandidateConstructors()方法 // 主要用与解析@Autowire标注的构造方法Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);// 以下情况符合其一即可进入// 1、存在可选构造方法(@Autowire修饰)// 2、自动装配模型为构造函数自动装配// 3、给BeanDefinition中设置了构造参数值// 4、有参与构造函数参数列表的参数if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {return autowireConstructor(beanName, mbd, ctors, args);}// Preferred constructors for default construction?// 找出最合适的默认构造方法,一般返回nullctors = mbd.getPreferredConstructors();if (ctors != null) {return autowireConstructor(beanName, mbd, ctors, null);}// 使用默认无参构造函数创建对象return instantiateBean(beanName, mbd);}​

注:getBean流程中有很多细节,需要新的章节说明,这里无法展开。本文为个人理解和参考他人,如有问题请指出。

spring getBean()方法解析概述相关推荐

  1. spring getbean 方法分析

    spring 缺省: 1.spring用DefaultListableBeanFactory.preInstantiateSingletons()建立bean实例 2.缺省采用单例模式 在最近的项目中 ...

  2. spring getbean 方法

    在网上找到一篇比较好的spring gebean的方法文章 创建一个工具类SpringContextsUtil ,通过实现Spring中的ApplicationContextAware接口,在appl ...

  3. Spring 核心方法 refresh 刷新流程简要概述及相关源码扩展实现(二)

    前言 registerBeanPostProcessors initMessageSource 如何实际应用国际化处理 initApplicationEventMulticaster onRefres ...

  4. Spring 核心方法 refresh 刷新流程简要概述及相关源码扩展实现(一)

    前言 Spring 启动流程解析 Refresh 内部方法全解析 prepareRefresh obtainFreshBeanFactory AbstractApplicationContext 类以 ...

  5. Spring源码解析之getBean(beanName)

    获取Spring Bean大体步骤: 调用BeanDefinitionReader的loadBeanDefinitions()方法解析并加载bean配置信息,转换位BeanDefinition对象 讲 ...

  6. 详解Spring中getBean()方法

    我们日常会经常使用getBean()方法从spring容器中获取我们需要的bean.那么,getBean()方法是怎么一步步完成从spring容器中获取bean的呢? 下面我们就通过源码分析一下. 一 ...

  7. Spring源码讲解之 getBean 方法

    getBean 方法是用来进行获取 bean 实例对象的,是我们进行 spring 程序开发从 bean 工厂获取结果的.那这个方法的执行过程是什么样的,下面我们就去揭开它的面纱. 样例代码 Appl ...

  8. (转)spring源码解析,spring工作原理

    转自:https://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/ Spring 的骨骼架构 Spring 总共有十几个组件,但是 ...

  9. Spring 容器IOC解析及简单实现

    这篇文章来自极客学院 : Spring 容器IOC解析及简单实现 最近一段时间,"容器"两个字一直萦绕在我的耳边,甚至是吃饭.睡觉的时候都在我脑子里蹦来蹦去的.随着这些天一次次的交 ...

最新文章

  1. linux挂载home分区,Linux(CentOS6) 调整 /home 挂载 分区大小
  2. 但是如果你按照官网的说明进行输入:比如 [{0: 1, 1: 1}, {0: 1, 1: 5}, {0: 1, 1: 1}, {0: 1, 1: 1}]就会报错,经过实践,多分类希望给各个label不
  3. Python学习之路1 - 基础入门
  4. 编程方法学21:监听器和迭代器回顾
  5. Delphi读取文本内容
  6. Chrome调试模拟iPhone6时body显示980*1742
  7. 手机知识:手机快充取决于充电头还是数据线,看完你就懂了!
  8. 几款经典好用的Android,经典实用 Android十款生活必备软件推荐
  9. opencv 智能答卷识别系统(一)
  10. 通讯超时什么意思_威伦触摸屏通讯报错了怎么办?
  11. Excel函数 (使用 「index + match」代替 vlookup进行查询)
  12. 【数据资产】数据资产目录建设方法与案例
  13. 怎么实现微信公众号生成专属二维码推广来源统计
  14. 谁不想拥有自己的代码仓库?
  15. C语言编程>第一周 ⑧ 输入两个正整数m和n,求其最大公约数和最小公倍数。
  16. java嫦娥_嫦娥回来了,还有哪些浪漫传说已经实现?
  17. 装虚拟机装Oracle数据库
  18. 图形化编程语言的设计
  19. 大数据产业驱动智慧家庭发展
  20. python从业人员工资_会Python的人,毕业后工资到底有多高?

热门文章

  1. 张子阳:谈谈离职和跳槽
  2. 【电子秤方案】人体秤方案开发
  3. 直流无刷电机霍尔线序自学习
  4. Oracle函数:row_number() over() 的使用
  5. 如何屏蔽百度热搜榜?(关闭百度搜索热点、关闭百度风云榜实时热点)(Adblock Plus插件)
  6. Python学习总结----基础篇3
  7. FFT信号处理知识总结
  8. detachd entity passed to persist:数据库表名
  9. 如何制作苹果的推送证书
  10. 计算机表格增加,职称计算机Dreamwaver2017教程:插入并编辑表格