Spring 5 源码解析- BeanFactory#getBean(String):获取Bean对象实例分析

发布时间:2022-06-27 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了Spring 5 源码解析- BeanFactory#getBean(String):获取Bean对象实例分析脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

         业务系统通过直接或间接调用  BeanFactory#getBean(String) 获取bean 实例化后的对象。先从 BeanDefinITion 配置中获取类类型信息,然后通过反射创建对象。创建对象后,填充属性信息,执行 Aware 接口对应的方法,执行 BeanPostPRocessor#postProcessBeforeinitialization 方法,调用配置的 init-method 方法,执行 BeanPostProcessor#postProcessAfterInitialization 方法,得到最终的封装过的 Bean 对象实例。业务系统停机时,调用 destroy-method 销毁对象相关信息。

 

一.  ApplicationContext 中 获取  Bean 实例 

         AbstractApplicationContext#getBean(java.lang.String)        1. 检查 上下文环境 (ApplicationContext)活动标记是否正常

        2. 通过 BeanFactory 实例获取 bean 对象。

Spring 5 源码解析- BeanFactory#getBean(String):获取Bean对象实例分析

Spring 5 源码解析- BeanFactory#getBean(String):获取Bean对象实例分析

1     @override
2     public Object getBean(String name) throws BeansException {
3         assertBeanFactoryActive();
4         return getBeanFactory().getBean(name);
5     }
View Code

 

二. BeanFactory  获取 Bean 实例

     AbstractBeanFactory#getBean(java.lang.String)

           --> AbstractBeanFactory#doGetBean(String name, @Nullable Class<T> requiredTyPE, @Nullable Object[] args, boolean typeCheckOnly)

      1.将 name 名称转换成 原始的BeanName 名称。例如:如果 name 有 FACTORY_BEAN_PREFIX 标志,则循环处理去掉。如果是别名,则转换成实际的 BeanName。

      2.从单例缓存中获取 创建好的共享单例对象。

      3.如果获取的 共享单例对象不为 null。则 通过  getObjectForBeanInstance 方法处理 共享单例对象。

        getObjectForBeanInstance():检查  Bean 实例是否是 FactoryBean 实现类,如果是,则进行相关处理。FactoryBean  是一个返回特殊Bean实例的接口。当运行程序需要简单生成 Bean 实例时,可以继承这个接口,实现简单的三个方法就行。由 FactoryBean  生成的 Bean 实例是没有复杂的生命周期管理。

      4.不满足 3 条件,则常规逻辑创建 bean 实例。

             a. 检查 beanName 是否是 原型模式 的循环依赖创建。 如果是,则直接抛出异常。Spring 只能解决 单例模式的循环依赖,不能解决原型模式的循环依赖。

             b. 当 BeanFactory 有 parentBeanFactory,并且 beanName 不在当前 beanDefinition 中 。 则通过 parentBeanFactory.getBean() 获取 beanName 实例。

             c. 标记正在创建 Bean 实例。

             d.  获取 合并后的 beanDefinition  定义信息,并检查 beanDefinition  信息。

             e. 从 beanDefinition  中获取所有依赖 bean 信息。先创建依赖 Bean 的实例。

             f.  如果是单例模式,则使用单例逻辑创建 Bean 实例。创建好后再通过 getObjectForBeanInstance  处理。

             j.  如果是原型模式,则使用原型逻辑创建 Bean 实例。创建好后再通过 getObjectForBeanInstance  处理。

             h. 如果其他自定义作用域模式,则使用对应的逻辑创建 Bean 实例。创建好后再通过 getObjectForBeanInstance  处理。

      5.如果创建的 bean 实例 和 指定的类型不匹配,则转换成指定的类型。

Spring 5 源码解析- BeanFactory#getBean(String):获取Bean对象实例分析

Spring 5 源码解析- BeanFactory#getBean(String):获取Bean对象实例分析

  1     /**
  2      * Return an instance, which may be shared or independent, of the specified bean.
  3      * @param name the name of the bean to retrieve
  4      * @param requiredType the required type of the bean to retrieve
  5      * @param args arguments to use when creating a bean instance using explicit arguments
  6      * (only applied when creating a new instance as opposed to retrieving an existing one)
  7      * @param typeCheckOnly whether the instance is oBTained for a type check,
  8      * not for actual use
  9      * @return an instance of the bean
 10      * @throws BeansException if the bean could not be created
 11      */
 12     @SupPressWarnings("unchecked")
 13     protected <T> T doGetBean(
 14             String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
 15             throws BeansException {
 16 
 17         // 将 name 转换成 BeanDefinition 中定义的信息。
 18         // 1. 如果name 名称前面有 &,则循环去掉。 & 表示FactoryBean
 19         // 2. 如果name 是别名的话,则循环转换成 BeanDefinition 中定义的 id 名称。
 20         String beanName = transformedBeanName(name);
 21         Object beanInstance;
 22 
 23         //  singletonFactories  earlySingletonObjects singletonObjects
 24         //  1.检查 singletonObjects 或 earlySingletonObjects 中是否有在创建的 对象实例信息。
 25         //  2. 添加同步锁, 重新校验(双重校验 ) singletonObjects 或 earlySingletonObjects 是否有 对象实例信息。
 26         //  3. 获取 singletonFactories 中对象实例信息。如果获取到,放到  earlySingletonObjects 中。
 27         //  4. 否在返回 null 对象。
 28 
 29         // Eagerly check singleton cache for manually registered singletons.
 30         Object sharedInstance = getSingleton(beanName);
 31         if (sharedInstance != null && args == null) {
 32             if (LOGger.isTraceEnabled()) {
 33                 if (isSingletoncurrentlyInCreation(beanName)) {
 34                     logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
 35                             "' that is not fully initialized yet - a consequence of a circular reference");
 36                 }
 37                 else {
 38                     logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
 39                 }
 40             }
 41             beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
 42         }
 43 
 44         else {
 45             // Fail if we're already creating this bean instance:
 46             // We're assumably within a circular reference.
 47             if (isPrototypeCurrentlyInCreation(beanName)) {
 48                 throw new BeanCurrentlyInCreationException(beanName);
 49             }
 50 
 51             // Check if bean definition exists in this factory.
 52             BeanFactory parentBeanFactory = getParentBeanFactory();
 53             if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
 54                 // Not found -> check parent.
 55                 String nameToLookup = originalBeanName(name);
 56                 if (parentBeanFactory instanceof AbstractBeanFactory) {
 57                     return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
 58                             nameToLookup, requiredType, args, typeCheckOnly);
 59                 }
 60                 else if (args != null) {
 61                     // Delegation to parent with explicit args.
 62                     return (T) parentBeanFactory.getBean(nameToLookup, args);
 63                 }
 64                 else if (requiredType != null) {
 65                     // No args -> delegate to standard getBean method.
 66                     return parentBeanFactory.getBean(nameToLookup, requiredType);
 67                 }
 68                 else {
 69                     return (T) parentBeanFactory.getBean(nameToLookup);
 70                 }
 71             }
 72 
 73             if (!typeCheckOnly) {
 74                 markBeanAsCreated(beanName);
 75             }
 76 
 77             StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
 78                     .tag("beanName", name);
 79             try {
 80                 if (requiredType != null) {
 81                     beanCreation.tag("beanType", requiredType::toString);
 82                 }
 83                 RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
 84                 checkMergedBeanDefinition(mbd, beanName, args);
 85 
 86                 // Guarantee initialization of beans that the current bean depends on.
 87                 String[] dependsOn = mbd.getDependsOn();
 88                 if (dependsOn != null) {
 89                     for (String dep : dependsOn) {
 90                         if (isDependent(beanName, dep)) {
 91                             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 92                                     "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
 93                         }
 94                         registerDependentBean(dep, beanName);
 95                         try {
 96                             getBean(dep);
 97                         }
 98                         catch (NoSuchBeanDefinitionException ex) {
 99                             throw new BeanCreationException(mbd.getResourceDescription(), beanName,
100                                     "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
101                         }
102                     }
103                 }
104 
105                 // Create bean instance.
106                 if (mbd.isSingleton()) {
107                     sharedInstance = getSingleton(beanName, () -> {
108                         try {
109                             return createBean(beanName, mbd, args);
110                         }
111                         catch (BeansException ex) {
112                             // Explicitly remove instance From singleton cache: It might have been put there
113                             // eagerly by the creation process, to allow for circular reference resolution.
114                             // Also remove any beans that received a temporary reference to the bean.
115                             destroySingleton(beanName);
116                             throw ex;
117                         }
118                     });
119                     beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
120                 }
121 
122                 else if (mbd.isPrototype()) {
123                     // It's a prototype -> create a new instance.
124                     Object prototypeInstance = null;
125                     try {
126                         beforePrototypeCreation(beanName);
127                         prototypeInstance = createBean(beanName, mbd, args);
128                     }
129                     finally {
130                         afterPrototypeCreation(beanName);
131                     }
132                     beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
133                 }
134 
135                 else {
136                     String scopeName = mbd.getScope();
137                     if (!StringUtils.hasLength(scopeName)) {
138                         throw new IllegalstateException("No scope name defined for bean ´" + beanName + "'");
139                     }
140                     Scope scope = this.scopes.get(scopeName);
141                     if (scope == null) {
142                         throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
143                     }
144                     try {
145                         Object scopedInstance = scope.get(beanName, () -> {
146                             beforePrototypeCreation(beanName);
147                             try {
148                                 return createBean(beanName, mbd, args);
149                             }
150                             finally {
151                                 afterPrototypeCreation(beanName);
152                             }
153                         });
154                         beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
155                     }
156                     catch (IllegalStateException ex) {
157                         throw new ScopeNotActiveException(beanName, scopeName, ex);
158                     }
159                 }
160             }
161             catch (BeansException ex) {
162                 beanCreation.tag("exception", ex.getClass().toString());
163                 beanCreation.tag("message", String.valueOf(ex.getMessage()));
164                 cleanupAfterBeanCreationFailure(beanName);
165                 throw ex;
166             }
167             finally {
168                 beanCreation.end();
169             }
170         }
171 
172         return adaptBeanInstance(name, beanInstance, requiredType);
173     }
View Code

 

 三. BeanFactory  创建 Bean 实例

     AbstractBeanFactory#getBean(java.lang.String)

           --> AbstractBeanFactory#doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)

               -->  AbstractAutowireCapableBeanFactory#createBean(String,  RootBeanDefinition,  Object[])

     1. 解析 BeanClass 得到 对应的Class 实例,并设置到 BeanDefinition 上。

     2. 准备覆盖方法。

     3. 通过 InstantiationAwareBeanPostProcessor 实现类创建 Bean 对象的实例。如果创建成功,则直接返回。

               例如: org.springframework.aop.framework.autoProxy.DefaultAdvisorAutoProxyCreator 实现类实现动态代理。

     4. 在 3步骤没有创建,则使用 AbstractAutowireCapableBeanFactory#doCreateBean() 创建对象实例 ,并返回。

Spring 5 源码解析- BeanFactory#getBean(String):获取Bean对象实例分析

Spring 5 源码解析- BeanFactory#getBean(String):获取Bean对象实例分析

 1     /**
 2      * Central method of this class: creates a bean instance,
 3      * populates the bean instance, applies post-processors, etc.
 4      * @see #doCreateBean
 5      */
 6     @Override
 7     protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
 8             throws BeanCreationException {
 9 
10         if (logger.isTraceEnabled()) {
11             logger.trace("Creating instance of bean '" + beanName + "'");
12         }
13         RootBeanDefinition mbdToUse = mbd;
14 
15         // Make sure bean class is actually resolved at this point, and
16         // clone the bean definition in case of a dynamically resolved Class
17         // which cannot be Stored in the shared merged bean definition.
18         Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
19         if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanclassname() != null) {
20             mbdToUse = new RootBeanDefinition(mbd);
21             mbdToUse.setBeanClass(resolvedClass);
22         }
23 
24         // Prepare method overrides.
25         try {
26             mbdToUse.prepareMethodOverrides();
27         }
28         catch (BeanDefinitionValidationException ex) {
29             throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
30                     beanName, "Validation of method overrides failed", ex);
31         }
32 
33         try {
34             // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
35             Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
36             if (bean != null) {
37                 return bean;
38             }
39         }
40         catch (Throwable ex) {
41             throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
42                     "BeanPostProcessor before instantiation of bean failed", ex);
43         }
44 
45         try {
46             Object beanInstance = doCreateBean(beanName, mbdToUse, args);
47             if (logger.isTraceEnabled()) {
48                 logger.trace("Finished creating instance of bean '" + beanName + "'");
49             }
50             return beanInstance;
51         }
52         catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
53             // A previously detected exception with proper bean creation context already,
54             // or illegal singleton state to be communicated up to defaultsingletonBeanRegistry.
55             throw ex;
56         }
57         catch (Throwable ex) {
58             throw new BeanCreationException(
59                     mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
60         }
61     }
View Code

 

 四. BeanFactory  创建 Bean 实例

     AbstractBeanFactory#getBean(java.lang.String)

           --> AbstractBeanFactory#doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)

               -->  AbstractAutowireCapableBeanFactory#createBean(String,  RootBeanDefinition,  Object[])

                  --> AbstractAutowireCapableBeanFactory#doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)

    1.  创建 BeanWrapper 实例。

    2.  通过 ;mergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition() 实现类合并处理 BeanDefinition 配置。

    3.  检查 正在创建的 Bean 实例是否是 循环依赖 创建的单例。如果是循环依赖创建的单例,则添加 循环依赖的缓存信息。

               即:将 ObjectFactory 实例保存到   singletonFactories 中。

    4. 填充Bean 属性信息。例如  Autowired注解属性注入。

             InstantiationAwareBeanPostProcessor#postProcessProperties 和 InstantiationAwareBeanPostProcessor#postProcessPropertyValues 相关处理。

    5. 初始化 Bean 实例 。

              a. 执行 实现Aware接口的相关方法。

              b. 循环调用 BeanPostProcessor#postProcessBeforeInitialization() 方法。

              c. 执行 init-method() 方法。

              d. 循环调用 BeanPostProcessor#postProcessAfterInitialization() 方法。

      6.  如果是单例创建,进行相关的特殊处理。

      7. 注册 Bean 的 销毁相关逻辑处理方法。

      8. 返回最终的 Bean 实例。可能是动态代理实例。

如下是几个主要的方法,对应 Bean 创建的几个生命周期。

-->> AbstractAutowireCapableBeanFactory#createBeanInstance()

-->> AbstractAutowireCapableBeanFactory#populateBean()

-->> AbstractAutowireCapableBeanFactory#invokeAwareMethods

-->> AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization

-->> AbstractAutowireCapableBeanFactory#invokeInitMethods

             org.springframework.beans.factory.InitializingBean#afterPropertiesSet()

-->> AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization()

Spring 5 源码解析- BeanFactory#getBean(String):获取Bean对象实例分析

Spring 5 源码解析- BeanFactory#getBean(String):获取Bean对象实例分析

  1     /**
  2      * Actually create the specified bean. Pre-creation processing has already happened
  3      * at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.
  4      * <p>Differentiates between default bean instantiation, use of a
  5      * factory method, and autowiring a constructor.
  6      * @param beanName the name of the bean
  7      * @param mbd the merged bean definition for the bean
  8      * @param args explicit arguments to use for constructor or factory method invocation
  9      * @return a new instance of the bean
 10      * @throws BeanCreationException if the bean could not be created
 11      * @see #instantiateBean
 12      * @see #instantiateUsingFactoryMethod
 13      * @see #autowireConstructor
 14      */
 15     protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
 16             throws BeanCreationException {
 17 
 18         // Instantiate the bean.
 19         BeanWrapper instanceWrapper = null;
 20         if (mbd.isSingleton()) {
 21             instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
 22         }
 23         if (instanceWrapper == null) {
 24             instanceWrapper = createBeanInstance(beanName, mbd, args);
 25         }
 26         Object bean = instanceWrapper.getWrappedInstance();
 27         Class<?> beanType = instanceWrapper.getWrappedClass();
 28         if (beanType != NullBean.class) {
 29             mbd.resolvedTargetType = beanType;
 30         }
 31 
 32         // Allow post-processors to modify the merged bean definition.
 33         synchronized (mbd.postProcessingLock) {
 34             if (!mbd.postProcessed) {
 35                 try {
 36                     applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
 37                 }
 38                 catch (Throwable ex) {
 39                     throw new BeanCreationException(mbd.getResourceDescription(), beanName,
 40                             "Post-processing of merged bean definition failed", ex);
 41                 }
 42                 mbd.postProcessed = true;
 43             }
 44         }
 45 
 46         // Eagerly cache singletons to be able to resolve circular references
 47         // even when triggered by lifecycle interfaces like BeanFactoryAware.
 48         boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
 49                 isSingletonCurrentlyInCreation(beanName));
 50         if (earlySingletonExposure) {
 51             if (logger.isTraceEnabled()) {
 52                 logger.trace("Eagerly caching bean '" + beanName +
 53                         "' to allow for resolving potential circular references");
 54             }
 55             addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
 56         }
 57 
 58         // Initialize the bean instance.
 59         Object exposedObject = bean;
 60         try {
 61             populateBean(beanName, mbd, instanceWrapper);
 62             exposedObject = initializeBean(beanName, exposedObject, mbd);
 63         }
 64         catch (Throwable ex) {
 65             if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
 66                 throw (BeanCreationException) ex;
 67             }
 68             else {
 69                 throw new BeanCreationException(
 70                         mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
 71             }
 72         }
 73 
 74         if (earlySingletonExposure) {
 75             Object earlySingletonReference = getSingleton(beanName, false);
 76             if (earlySingletonReference != null) {
 77                 if (exposedObject == bean) {
 78                     exposedObject = earlySingletonReference;
 79                 }
 80                 else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
 81                     String[] dependentBeans = getDependentBeans(beanName);
 82                     Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
 83                     for (String dependentBean : dependentBeans) {
 84                         if (!removeSingletonIfcreateDForTypeCheckOnly(dependentBean)) {
 85                             actualDependentBeans.add(dependentBean);
 86                         }
 87                     }
 88                     if (!actualDependentBeans.iSEMpty()) {
 89                         throw new BeanCurrentlyInCreationException(beanName,
 90                                 "Bean with name '" + beanName + "' has been injected into other beans [" +
 91                                 StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
 92                                 "] in its raw version as part of a circular reference, but has eventually been " +
 93                                 "wrapped. This means that said other beans do not use the final version of the " +
 94                                 "bean. This is often the result of over-eager type matching - consider using " +
 95                                 "'getBeannamesForType' with the 'allowEagerInit' flag turned off, for example.");
 96                     }
 97                 }
 98             }
 99         }
100 
101         // Register bean as disposable.
102         try {
103             registerDisposableBeanIfNecessary(beanName, bean, mbd);
104         }
105         catch (BeanDefinitionValidationException ex) {
106             throw new BeanCreationException(
107                     mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
108         }
109 
110         return exposedObject;
111     }
View Code

 

脚本宝典总结

以上是脚本宝典为你收集整理的Spring 5 源码解析- BeanFactory#getBean(String):获取Bean对象实例分析全部内容,希望文章能够帮你解决Spring 5 源码解析- BeanFactory#getBean(String):获取Bean对象实例分析所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。