spring中如何实现参数隐式传递_「死磕 Spring」—– IOC 之开启 bean 的加载

本文探讨Spring IOC容器的两个阶段:初始化和加载bean。在初始化阶段,配置元数据被加载并解析成BeanDefinition,注册到BeanDefinitionRegistry。在加载bean阶段,getBean()方法触发bean实例化和依赖注入。doGetBean()方法是核心,接收bean名称、类型、创建参数和类型检查标志作为参数。
摘要由CSDN通过智能技术生成

原文出自:http://cmsblogs.com

作者:作者:chenssy

18153ef36c09d5516628322e702197c4.png

(此图来自《Spring 揭秘》) Spring IOC 容器所起的作用如上图所示,它会以某种方式加载 Configuration Metadata,将其解析注册到容器内部,然后回根据这些信息绑定整个系统的对象,最终组装成一个可用的基于轻量级容器的应用系统。 Spring 在实现上述功能中,将整个流程分为两个阶段:容器初始化阶段和加载bean 阶段。

  • 容器初始化阶段:首先通过某种方式加载 Configuration Metadata (主要是依据 Resource、ResourceLoader 两个体系),然后容器会对加载的 Configuration MetaData 进行解析和分析,并将分析的信息组装成 BeanDefinition,并将其保存注册到相应的 BeanDefinitionRegistry 中。至此,Spring IOC 的初始化工作完成。
  • 加载 bean 阶段:经过容器初始化阶段后,应用程序中定义的 bean 信息已经全部加载到系统中了,当我们显示或者隐式地调用 getBean() 时,则会触发加载 bean 阶段。在这阶段,容器会首先检查所请求的对象是否已经初始化完成了,如果没有,则会根据注册的 bean 信息实例化请求的对象,并为其注册依赖,然后将其返回给请求方。至此第二个阶段也已经完成。

第一个阶段前面已经用了 10 多篇博客深入分析了(总结参考【死磕 Spring】----- IOC 之 IOC 初始化总结)。所以从这篇开始分析第二个阶段:加载 bean 阶段。当我们显示或者隐式地调用 getBean() 时,则会触发加载 bean 阶段。如下:

 public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); }

内部调用 doGetBean() 方法,其接受四个参数:

  • name:要获取 bean 的名字
  • requiredType:要获取 bean 的类型
  • args:创建 bean 时传递的参数。这个参数仅限于创建 bean 时使用
  • typeCheckOnly:是否为类型检查

这个方法的代码比较长,各位耐心看下:

 protected  T doGetBean(final String name, @Nullable final Class requiredType, @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException { // 获取 beanName,这里是一个转换动作,将 name 转换Wie beanName final String beanName = transformedBeanName(name); Object bean; // 从缓存中或者实例工厂中获取 bean // *** 这里会涉及到解决循环依赖 bean 的问题 Object sharedInstance = getSingleton(beanName); if (sharedInstance != null && args == null) { if (logger.isDebugEnabled()) { if (isSingletonCurrentlyInCreation(beanName)) { logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference"); } else { logger.debug("Returning cached instance of singleton bean '" + beanName + "'"); } } bean = getObjectForBeanInstance(sharedInstance, name, beanName, null); } else { // 因为 Spring 只解决单例模式下得循环依赖,在原型模式下如果存在循环依赖则会抛出异常 // **关于循环依赖后续会单独出文详细说明** if (isPrototypeCurrentlyInCreation(beanName)) { throw new BeanCurrentlyInCreationException(beanName); } // 如果容器中没有找到,则从父类容器中加载 BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { String nameToLookup = originalBeanName(name); if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) parentBeanFactory).doGetBean( nameToLookup, requiredType, args, typeCheckOnly); } else if (args != null) { return (T) parentBeanFactory.getBean(nameToLookup, args); } else { return parentBeanFactory.getBean(nameToLookup, requiredType); } } // 如果不是仅仅做类型检查则是创建bean,这里需要记录 if (!typeCheckOnly) { markBeanAsCreated(beanName); } try { // 从容器中获取 beanName 相应的 GenericBeanDefinition,并将其转换为 RootBeanDefinition final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); // 检查给定的合并的 BeanDefinition checkMergedBeanDefinition(mbd, beanName, args); // 处理所依赖的 bean String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { // 若给定的依赖 bean 已经注册为依赖给定的b ean // 循环依赖的情况 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 + "'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值