spring getBean()方法解析概述
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()方法解析概述相关推荐
- spring getbean 方法分析
spring 缺省: 1.spring用DefaultListableBeanFactory.preInstantiateSingletons()建立bean实例 2.缺省采用单例模式 在最近的项目中 ...
- spring getbean 方法
在网上找到一篇比较好的spring gebean的方法文章 创建一个工具类SpringContextsUtil ,通过实现Spring中的ApplicationContextAware接口,在appl ...
- Spring 核心方法 refresh 刷新流程简要概述及相关源码扩展实现(二)
前言 registerBeanPostProcessors initMessageSource 如何实际应用国际化处理 initApplicationEventMulticaster onRefres ...
- Spring 核心方法 refresh 刷新流程简要概述及相关源码扩展实现(一)
前言 Spring 启动流程解析 Refresh 内部方法全解析 prepareRefresh obtainFreshBeanFactory AbstractApplicationContext 类以 ...
- Spring源码解析之getBean(beanName)
获取Spring Bean大体步骤: 调用BeanDefinitionReader的loadBeanDefinitions()方法解析并加载bean配置信息,转换位BeanDefinition对象 讲 ...
- 详解Spring中getBean()方法
我们日常会经常使用getBean()方法从spring容器中获取我们需要的bean.那么,getBean()方法是怎么一步步完成从spring容器中获取bean的呢? 下面我们就通过源码分析一下. 一 ...
- Spring源码讲解之 getBean 方法
getBean 方法是用来进行获取 bean 实例对象的,是我们进行 spring 程序开发从 bean 工厂获取结果的.那这个方法的执行过程是什么样的,下面我们就去揭开它的面纱. 样例代码 Appl ...
- (转)spring源码解析,spring工作原理
转自:https://www.ibm.com/developerworks/cn/java/j-lo-spring-principle/ Spring 的骨骼架构 Spring 总共有十几个组件,但是 ...
- Spring 容器IOC解析及简单实现
这篇文章来自极客学院 : Spring 容器IOC解析及简单实现 最近一段时间,"容器"两个字一直萦绕在我的耳边,甚至是吃饭.睡觉的时候都在我脑子里蹦来蹦去的.随着这些天一次次的交 ...
最新文章
- linux挂载home分区,Linux(CentOS6) 调整 /home 挂载 分区大小
- 但是如果你按照官网的说明进行输入:比如 [{0: 1, 1: 1}, {0: 1, 1: 5}, {0: 1, 1: 1}, {0: 1, 1: 1}]就会报错,经过实践,多分类希望给各个label不
- Python学习之路1 - 基础入门
- 编程方法学21:监听器和迭代器回顾
- Delphi读取文本内容
- Chrome调试模拟iPhone6时body显示980*1742
- 手机知识:手机快充取决于充电头还是数据线,看完你就懂了!
- 几款经典好用的Android,经典实用 Android十款生活必备软件推荐
- opencv 智能答卷识别系统(一)
- 通讯超时什么意思_威伦触摸屏通讯报错了怎么办?
- Excel函数 (使用 「index + match」代替 vlookup进行查询)
- 【数据资产】数据资产目录建设方法与案例
- 怎么实现微信公众号生成专属二维码推广来源统计
- 谁不想拥有自己的代码仓库?
- C语言编程>第一周 ⑧ 输入两个正整数m和n,求其最大公约数和最小公倍数。
- java嫦娥_嫦娥回来了,还有哪些浪漫传说已经实现?
- 装虚拟机装Oracle数据库
- 图形化编程语言的设计
- 大数据产业驱动智慧家庭发展
- python从业人员工资_会Python的人,毕业后工资到底有多高?