Spring源码之bean的加载(三)从bean中获取对象
在上一章节中,我们知道了Spring是如何去获取单例bean,而这一章节我们将要去了解Spring是如何从bean获取对象。(相关资源可到这里下载:http://pan.baidu.com/s/1sjSo9a9)
在最开始前面我们知道了,Spring的获取bean的方法的入口函数是getObjectForBeanInstance。那么我们就跟着时序图一步一步赶往代码查看。
1) 首先,我们要看在是getObjectForInstance的函数,这个函数主要做的事情是:
a) 对FactoryBean正确的验证
b) 对非FactoryBean不做任何处理
c) 对bean进行转换
d) 将从Factory中解析bean的工作委托给getObjectFromFactoryBean
protected Object getObjectForBeanInstance(Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {// Don't let calling code try to dereference the factory if the bean isn't a factory.//如果指定的name是工厂相
关(以&为前缀)且beanInstance又不是FactoryBean类型则验证不通过if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());}// 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的实例,这个实例可能会是正常的bean或者是FactoryBean//如果是FactoryBean我们使用它创建实例,但是如果是用户想要获取工厂实例而不是工厂的//getObject方法对应 的实例,那么传入的name应该加入前缀if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {return beanInstance;}//加载FactoryBeanObject object = null;if (mbd == null) {//尝试从缴存中加载beanobject = getCachedObjectForFactoryBean(beanName);}if (object == null) {// Return bean instance from factory.//到这里已经明确知道beanInstance一定是FactoryBean类型FactoryBean<?> factory = (FactoryBean<?>) beanInstance;// Caches object obtained from FactoryBean if it is a singleton.//containsBeanDefinition检测beanDefinitionMap中也就是在所有已经加载的类中检测是否定义beanNameif (mbd == null && containsBeanDefinition(beanName)) {//将存储XML配置文件的GenericBeanDfinition转换为RootBeanDefinition,如果指定BeanName是子Bean的话同时会合并父类的相关属性mbd = getMergedLocalBeanDefinition(beanName);}//是否是用户定义的而不是应用程序本身定义的boolean synthetic = (mbd != null && mbd.isSynthetic());object = getObjectFromFactoryBean(factory, beanName, !synthetic);}return object;}
2) 我们继续跟踪代码到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 (object != null && shouldPostProcess) {try {object = postProcessObjectFromFactoryBean(object, beanName);}catch (Throwable ex) {throw new BeanCreationException(beanName,"Post-processing of FactoryBean's singleton object failed", ex);}}this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));}}return (object != NULL_OBJECT ? object : null);}}else {Object object = doGetObjectFromFactoryBean(factory, beanName);if (object != null && shouldPostProcess) {try {object = postProcessObjectFromFactoryBean(object, beanName);}catch (Throwable ex) {throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);}}return object;}}
3) 在上面的方法中,我们比较关心的是doGetObjectFromFactoryBean ()的方法,这个方法中有一行代码是:object = factory.getObject(),这似乎是我们想要看到的。
private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)throws BeanCreationException {Object object;try {//需要权限验证if (System.getSecurityManager() != null) {AccessControlContext acc = getAccessControlContext();try {object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {@Overridepublic Object run() throws Exception {return factory.getObject();}}, acc);}catch (PrivilegedActionException pae) {throw pae.getException();}}else {//直接调用getObject方法object = factory.getObject();}}catch (FactoryBeanNotInitializedException ex) {throw new BeanCurrentlyInCreationException(beanName, ex.toString());}catch (Throwable ex) {throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);}// Do not accept a null value for a FactoryBean that's not fully// initialized yet: Many FactoryBeans just return null then.if (object == null && isSingletonCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName, "FactoryBean which is currently in creation returned null from getObject");}return object;}
4) 方法中的object = factory.getObject()得到了我们想要的结果,但是并没有直接返回,我们继续到getObjectFromFactoryBean方法的postProcessObjectFromFactoryBean方法下,再进入applyBeanPostprocessorsAfterInitiallization()的方法,就可以得到结果了。
@Overrideprotected Object postProcessObjectFromFactoryBean(Object object, String beanName) {return applyBeanPostProcessorsAfterInitialization(object, beanName);}
@Overridepublic Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {result = beanProcessor.postProcessAfterInitialization(result, beanName);if (result == null) {return result;}}return result;}
Spring源码之bean的加载(三)从bean中获取对象相关推荐
- Spring源码解析-applicationContext.xml加载和bean的注册
applicationContext文件加载和bean注册流程 Spring对于从事Java开发的boy来说,再熟悉不过了,对于我们这个牛逼的框架的介绍就不在这里复述了,Spring这个大杂烩,怎 ...
- 【框架源码】Spring源码解析之BeanDefinition加载流程解析
观看本文之前,我们先思考一个问题,Spring是如何描述Bean对象的? Spring是根据BeanDefinition来创建Bean对象,BeanDefinition就是Spring中表示Bean定 ...
- Spring源码之BeanDifinition(加几行代码,可以产出让队友几天也找不出的Bug)
前言 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/bin392328206/six-finger 种一棵树最好的时间是十年前,其次是现在 我知道很多人不玩qq ...
- Android 11.0 Settings源码分析 - 主界面加载
Android 11.0 Settings源码分析 - 主界面加载 本篇主要记录AndroidR Settings源码主界面加载流程,方便后续工作调试其流程. Settings代码路径: packag ...
- android资源加载流程6,FrameWork源码解析(6)-AssetManager加载资源过程
之前一段时间项目比较忙所以一直没有更新,接下来准备把插件化系列的文章写完,今天我们就先跳过ContentProvider源码解析来讲资源加载相关的知识,资源加载可以说是插件化非常重要的一环,我们很有必 ...
- 有没有code能改xml内容_Spring源码解析-applicationContext.xml加载和bean的注册
applicationContext文件加载和bean注册流程 Spring对于从事Java开发的boy来说,再熟悉不过了,对于我们这个牛逼的框架的介绍就不在这里复述了,Spring这个大杂烩,怎 ...
- JVM源码阅读-本地库加载流程和原理
前言 本文主要研究OpenJDK中JVM源码中涉及到native本地库的加载流程和原理的部分.主要目的是为了了解本地库是如何被加载到虚拟机,以及是如何找到并执行本地库里的本地方法,以及JNI的 JNI ...
- 从源码解析-结合Activity加载流程深入理解ActivityThrad的工作逻辑
ActivityThread源码解析 前言 类简称 类简介 一 二 三 四 五 代理和桩的理解 ActivityThread ActivityThread.main AT.attach AMN.get ...
- 【Android源码】Activity如何加载布局
我们都知道在Activity中通过setContentView(layoutId)来加载布局文件,使我们的布局文件能够显示在手机上,那么系统是如何将我们的布局文件加载到界面上的呢? setConten ...
- LoadingCache源码剖析之缓存加载实现
其他文章:https://blog.csdn.net/define_us/article/details/111656019 随着互联网的发展,数据量不断增长,用户对性能要求的不断提升,在开发项目中使 ...
最新文章
- 18,rand('state',sum(100*clock))
- 十问十答 Apache 许可证
- dump分析工具_Java应用CPU过高,如何排查?参考解决思路和常用工具总结
- 快速上手,使用 Kotlin 把支付宝小程序装进自己的 App
- HTML5响应式品牌服装设计类织梦模板
- 什么是ITSS认证,需要多长时间
- linux :Tar 命令参数详解
- HC蓝牙模块测试AT指令搭建外部电路遇到的问题
- 发力多人在线游戏!PS5有望2020年E3展会亮相!
- tiledmap 图块属性_TiledMap地图使用
- JS地图经纬度正则表达式校验
- 2022程序员必备网站
- C语言标准ANSI C、C语言的特点、C语言的关键字(32个)
- 人工智能机器人标准化建设的意义
- Zigbee Zstack2.5.1a使用rfx2401+cc2530
- Android程序员在大厂工作是什么体验?
- 图中的搜索——dij
- android 放大镜 Magnifier 简单实现
- PN532和控制器之间的交互
- 基于QT的多媒体播放器