当前位置: 首页 > news >正文

Spring-创建bean

preInstantiateSingletons

v1.0 preInstantiateSingletons

tips:最终调用getBean使用的是RootBeanDefinition进行构建的

public void preInstantiateSingletons() throws BeansException {if (logger.isTraceEnabled()) {logger.trace("Pre-instantiating singletons in " + this);}//获取所有beanDefinition的名字List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);//循环for (String beanName : beanNames) {// 获取合并后的BeanDefinition,看代码V1.1RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);//如果RootBeanDefinition不是抽象BeanDefinition,是单例bean,非懒加载,则创建bean对象if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {if (isFactoryBean(beanName)) {// 获取FactoryBean对象Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);if (bean instanceof FactoryBean) {FactoryBean<?> factory = (FactoryBean<?>) bean;boolean isEagerInit;if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,getAccessControlContext());}else {isEagerInit = (factory instanceof SmartFactoryBean &&((SmartFactoryBean<?>) factory).isEagerInit());}if (isEagerInit) {// 创建真正的Bean对象(getObject()返回的对象)getBean(beanName);}}}else {// 创建Bean对象getBean(beanName);}}}// 所有的非懒加载单例Bean都创建完了后//找出实现了SmartInitializingSingleton接口的单例bean,并执行afterSingletonsInstantiated()方法for (String beanName : beanNames) {Object singletonInstance = getSingleton(beanName);if (singletonInstance instanceof SmartInitializingSingleton) {StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize").tag("beanName", beanName);SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {smartSingleton.afterSingletonsInstantiated();return null;}, getAccessControlContext());}else {smartSingleton.afterSingletonsInstantiated();}smartInitialize.end();}}}

什么是抽象BeanDefinition?

V1.1 getMergedLocalBeanDefinition

合并BeanDefinition

protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {// 先从RootBeanDefinitionMap中获取当前beanName对应的RootBeanDefinition对象RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);//如果已经存在,则直接返回if (mbd != null && !mbd.stale) {return mbd;}//如果不存在,则继续向下判断return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));}
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)throws BeanDefinitionStoreException {synchronized (this.mergedBeanDefinitions) {RootBeanDefinition mbd = null;RootBeanDefinition previous = null;// Check with full lock now in order to enforce the same merged instance.if (containingBd == null) {mbd = this.mergedBeanDefinitions.get(beanName);}if (mbd == null || mbd.stale) {previous = mbd;//如果当前BeanDefinition没有父类if (bd.getParentName() == null) {//判断bd是否是RootBeanDefinition的实例,如果是,则克隆一个新的RootBeanDifinition对象if (bd instanceof RootBeanDefinition) {mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();}else {//直接创建一个RootBeanDefionition对象,并赋值mbd = new RootBeanDefinition(bd);}}else {//当bd存在父类的时候// pbd表示parentBeanDefinitionBeanDefinition pbd;try {//获取父BeanDefinition的名称String parentBeanName = transformedBeanName(bd.getParentName());//如果 当前bean的名称与父类名称不相同,表示父类还存在父类,则需要继续递归调用//最终的效果是每一个父类都已经合并完了,当前beanDefinition在和父类进行合并if (!beanName.equals(parentBeanName)) {pbd = getMergedBeanDefinition(parentBeanName);}else {BeanFactory parent = getParentBeanFactory();if (parent instanceof ConfigurableBeanFactory) {pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);}else {throw new NoSuchBeanDefinitionException(parentBeanName,"Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +"': cannot be resolved without a ConfigurableBeanFactory parent");}}}catch (NoSuchBeanDefinitionException ex) {throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,"Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);}// 子BeanDefinition的属性覆盖父BeanDefinition的属性,这就是合并//先用父类的BeanDefinition创建一个新的RootBeanDefinitionmbd = new RootBeanDefinition(pbd);//在使用子类 的BeanDefinition覆盖RootBeanDefinition的属性mbd.overrideFrom(bd);}// 如果未设置bean的作用域,则默认设置未单例if (!StringUtils.hasLength(mbd.getScope())) {mbd.setScope(SCOPE_SINGLETON);}// A bean contained in a non-singleton bean cannot be a singleton itself.// Let's correct this on the fly here, since this might be the result of// parent-child merging for the outer bean, in which case the original inner bean// definition will not have inherited the merged outer bean's singleton status.if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {mbd.setScope(containingBd.getScope());}if (containingBd == null && isCacheBeanMetadata()) {this.mergedBeanDefinitions.put(beanName, mbd);}}if (previous != null) {copyRelevantMergedBeanDefinitionCaches(previous, mbd);}return mbd;}

doGetBean

protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)throws BeansException {// name有可能是 &xxx 或者 xxx,如果name是&xxx,那么beanName就是xxx// name有可能传入进来的是别名,那么beanName就是id//具体看v1.1String beanName = transformedBeanName(name);Object beanInstance;// 优先从单例池中获取beanDefinitionObject sharedInstance = getSingleton(beanName);if (sharedInstance != null && args == null) {if (logger.isTraceEnabled()) {if (isSingletonCurrentlyInCreation(beanName)) {logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +"' that is not fully initialized yet - a consequence of a circular reference");}else {logger.trace("Returning cached instance of singleton bean '" + beanName + "'");}}// 如果sharedInstance是FactoryBean,那么就调用getObject()返回对象beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);}else {// Fail if we're already creating this bean instance:// We're assumably within a circular reference.if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}// Check if bean definition exists in this factory.BeanFactory parentBeanFactory = getParentBeanFactory();if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {//如果beanDefinitionMap的keys中不包含beanName,则调用父类的bean工厂创建创建对象String nameToLookup = originalBeanName(name);if (parentBeanFactory instanceof AbstractBeanFactory) {//此处是递归处理,直至找到beanDefginitionreturn ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);}else if (args != null) {// Delegation to parent with explicit args.return (T) parentBeanFactory.getBean(nameToLookup, args);}else if (requiredType != null) {// No args -> delegate to standard getBean method.return parentBeanFactory.getBean(nameToLookup, requiredType);}else {return (T) parentBeanFactory.getBean(nameToLookup);}}if (!typeCheckOnly) {markBeanAsCreated(beanName);}StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate").tag("beanName", name);try {if (requiredType != null) {beanCreation.tag("beanType", requiredType::toString);}//拿到beanName对应的RootBeanDefinitionRootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);// 检查BeanDefinition是不是Abstract的checkMergedBeanDefinition(mbd, beanName, args);// 找出这个对象所依赖的所有bean的集合,该字段于构建rootBeandefinition的时候赋值String[] dependsOn = mbd.getDependsOn();if (dependsOn != null) {// dependsOn表示当前beanName所依赖的,当前Bean创建之前dependsOn所依赖的Bean必须已经创建好了for (String dep : dependsOn) {// beanName是不是被dep依赖了,如果是则出现了循环依赖//看代码v1.3if (isDependent(beanName, dep)) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");}// dep被beanName依赖了,存入dependentBeanMap中,dep为key,beanName为valueregisterDependentBean(dep, beanName);// 创建所依赖的beantry {getBean(dep);}catch (NoSuchBeanDefinitionException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"'" + beanName + "' depends on missing bean '" + dep + "'", ex);}}}// bean是单例的情况if (mbd.isSingleton()) {//此处第二个参数lambda并不会马上执行,此处是相当于传入了一个对象,//该对象是getSingleton()方法中第二个参数接口的实例化,重写了该接口中唯一一个方法//具体看代码v1.2sharedInstance = getSingleton(beanName, () -> {try {//见代码四return createBean(beanName, mbd, args);}catch (BeansException ex) {// Explicitly remove instance from singleton cache: It might have been put there// eagerly by the creation process, to allow for circular reference resolution.// Also remove any beans that received a temporary reference to the bean.destroySingleton(beanName);throw ex;}});beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}else if (mbd.isPrototype()) {// It's a prototype -> create a new instance.Object prototypeInstance = null;try {beforePrototypeCreation(beanName);prototypeInstance = createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}else {String scopeName = mbd.getScope();if (!StringUtils.hasLength(scopeName)) {throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");}Scope scope = this.scopes.get(scopeName);if (scope == null) {throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");}try {  // session.getAttriute(beaName)  setAttriObject scopedInstance = scope.get(beanName, () -> {beforePrototypeCreation(beanName);try {return createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}});beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);}catch (IllegalStateException ex) {throw new ScopeNotActiveException(beanName, scopeName, ex);}}}catch (BeansException ex) {beanCreation.tag("exception", ex.getClass().toString());beanCreation.tag("message", String.valueOf(ex.getMessage()));cleanupAfterBeanCreationFailure(beanName);throw ex;}finally {beanCreation.end();}}// 检查通过name所获得到的beanInstance的类型是否是requiredType//看代码v1.5return adaptBeanInstance(name, beanInstance, requiredType);}

v1.1 transformedBeanName

根据传入的名字获取bean真正的名字(有可能传入的是别名或者工厂类别名,以&开头的),特别需要说明的是,spring针对于别名专门使用一个map(aliasMap)进行存储,key为别名,而value则是bean真正的名字。所以在创建bena第一步就需要先根据名字获取到bean真正的名字

protected String transformedBeanName(String name) {return canonicalName(BeanFactoryUtils.transformedBeanName(name));}
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
//先判断名字是否是工厂类的名字,如果不是,则直接返回名字,如果是以& 开头的,则循环截取第一个字符直到不以&开头public static String transformedBeanName(String name) {Assert.notNull(name, "'name' must not be null");if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {return name;}return transformedBeanNameCache.computeIfAbsent(name, beanName -> {do {beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());}while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));return beanName;});}
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
public String canonicalName(String name) {String canonicalName = name;// Handle aliasing...String resolvedName;do {//从别名map中获取bean的真实名字resolvedName = this.aliasMap.get(canonicalName);if (resolvedName != null) {canonicalName = resolvedName;}}while (resolvedName != null);return canonicalName;}
v1.2 getSingleton

获取单例对象

	public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {Assert.notNull(beanName, "Bean name must not be null");synchronized (this.singletonObjects) {Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {if (this.singletonsCurrentlyInDestruction) {throw new BeanCreationNotAllowedException(beanName,"Singleton bean creation not allowed while singletons of this factory are in destruction " +"(Do not request a bean from a BeanFactory in a destroy method implementation!)");}if (logger.isDebugEnabled()) {logger.debug("Creating shared instance of singleton bean '" + beanName + "'");}//创建bean之前的一些准备//1 判断beanName是否是被过滤的,如果是需要过滤的,则抛出异常//2 将beanName添加到singletonsCurrentlyInCreation集合中,表示bean正在创建//上面条件其中一个失败都会抛出异常beforeSingletonCreation(beanName);boolean newSingleton = false;boolean recordSuppressedExceptions = (this.suppressedExceptions == null);if (recordSuppressedExceptions) {this.suppressedExceptions = new LinkedHashSet<>();}try {//开始创建单例对象,调用外部的lambda表达式singletonObject = singletonFactory.getObject();newSingleton = true;}catch (IllegalStateException ex) {// Has the singleton object implicitly appeared in the meantime ->// if yes, proceed with it since the exception indicates that state.singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {throw ex;}}catch (BeanCreationException ex) {if (recordSuppressedExceptions) {for (Exception suppressedException : this.suppressedExceptions) {ex.addRelatedCause(suppressedException);}}throw ex;}finally {if (recordSuppressedExceptions) {this.suppressedExceptions = null;}//结束创建过程//1 判断beanName是否是被过滤的,如果是需要过滤的,则抛出异常//2 将beanName移除singletonsCurrentlyInCreation集合,表示bean不在创建过程中(已经创建结束了)//上面条件其中一个失败都会抛出异常afterSingletonCreation(beanName);}// 添加到单例池if (newSingleton) {addSingleton(beanName, singletonObject);}}return singletonObject;}}
v1.3 isDependent
	private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {if (alreadySeen != null && alreadySeen.contains(beanName)) {return false;}String canonicalName = canonicalName(beanName);//dependentBeanMapbeanName为key  以被key依赖的所有bean名字的集合为valueSet<String> dependentBeans = this.dependentBeanMap.get(canonicalName);if (dependentBeans == null) {return false;}if (dependentBeans.contains(dependentBeanName)) {return true;}for (String transitiveDependency : dependentBeans) {if (alreadySeen == null) {alreadySeen = new HashSet<>();}alreadySeen.add(beanName);if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {return true;}}return false;}
v1.4 adaptBeanInstance
	<T> T adaptBeanInstance(String name, Object bean, @Nullable Class<?> requiredType) {// Check if required type matches the type of the actual bean instance.if (requiredType != null && !requiredType.isInstance(bean)) {try {// SimpleTypeConverterObject convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);if (convertedBean == null) {throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}return (T) convertedBean;}catch (TypeMismatchException ex) {if (logger.isTraceEnabled()) {logger.trace("Failed to convert bean '" + name + "' to required type '" +ClassUtils.getQualifiedName(requiredType) + "'", ex);}throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}}return (T) bean;}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 谷粒商城实战笔记-122~124-全文检索-ElasticSearch-分词
  • JVM—虚拟机类加载器
  • 机器学习练手(三):基于决策树的iris 多分类和波士顿房价预测
  • 华为的流程体系
  • 【大模型】【面试】独家总结表格
  • ISA95-Part8-错误处理的设计与集成
  • 【二】测试工具
  • 21天学通C++:理解函数对象、Lambda表达式
  • 微信小程序css中配置了文字超出一行或两行则显示省略号对纯数字或纯字母或小数点无效的解决办法
  • C Primer Plus 第5章——第一篇
  • C++ | Leetcode C++题解之第318题最大单词长度乘积
  • git clone private repo
  • 【iOS】多界面传值
  • pycharm中安装、使用扩展工具,以QT Designer为例
  • Centos 8系统xfs文件系统类型进行扩容缩容 (LVM)
  • JS 中的深拷贝与浅拷贝
  • 2018天猫双11|这就是阿里云!不止有新技术,更有温暖的社会力量
  • android图片蒙层
  • Android组件 - 收藏集 - 掘金
  • C++类中的特殊成员函数
  • co模块的前端实现
  • httpie使用详解
  • k8s 面向应用开发者的基础命令
  • niucms就是以城市为分割单位,在上面 小区/乡村/同城论坛+58+团购
  • Python爬虫--- 1.3 BS4库的解析器
  • React-生命周期杂记
  • Vue 重置组件到初始状态
  • 对话:中国为什么有前途/ 写给中国的经济学
  • 缓存与缓冲
  • 老板让我十分钟上手nx-admin
  • 扫描识别控件Dynamic Web TWAIN v12.2发布,改进SSL证书
  • 推荐一款sublime text 3 支持JSX和es201x 代码格式化的插件
  • 智能网联汽车信息安全
  • Play Store发现SimBad恶意软件,1.5亿Android用户成受害者 ...
  • ​ 无限可能性的探索:Amazon Lightsail轻量应用服务器引领数字化时代创新发展
  • ​HTTP与HTTPS:网络通信的安全卫士
  • ​比特币大跌的 2 个原因
  • ​一些不规范的GTID使用场景
  • ‌前端列表展示1000条大量数据时,后端通常需要进行一定的处理。‌
  • # wps必须要登录激活才能使用吗?
  • # 消息中间件 RocketMQ 高级功能和源码分析(七)
  • #### go map 底层结构 ####
  • #Lua:Lua调用C++生成的DLL库
  • (7) cmake 编译C++程序(二)
  • (vue)el-checkbox 实现展示区分 label 和 value(展示值与选中获取值需不同)
  • (八)Flask之app.route装饰器函数的参数
  • (八)光盘的挂载与解挂、挂载CentOS镜像、rpm安装软件详细学习笔记
  • (二十九)STL map容器(映射)与STL pair容器(值对)
  • (更新)A股上市公司华证ESG评级得分稳健性校验ESG得分年均值中位数(2009-2023年.12)
  • (十三)Java springcloud B2B2C o2o多用户商城 springcloud架构 - SSO单点登录之OAuth2.0 根据token获取用户信息(4)...
  • (四)JPA - JQPL 实现增删改查
  • (算法)N皇后问题
  • (转)真正的中国天气api接口xml,json(求加精) ...
  • ./mysql.server: 没有那个文件或目录_Linux下安装MySQL出现“ls: /var/lib/mysql/*.pid: 没有那个文件或目录”...
  • .babyk勒索病毒解析:恶意更新如何威胁您的数据安全