范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

Spring源码SpringBean的创建过程(14)

  到目前为止,我们知道Spring创建Bean对象有5中方法,分别是: 使用FactoryBean的getObject方法创建 使用BeanPostProcessor的子接口InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法创建 设置BeanDefinition的Supplier属性进行创建 设置BeanDefinition的factory-method进行创建 使用全过程:getBean-->doGetBean-->createBean-->doCreateBean 反射进行创建
  前面4种已经介绍,接下来介绍第5种,我们知道如果使用反射创建,那么必然要知道使用构造函数进行实例化,因为使用构造函数能够将带有参数的设置进去。 SmartInstantiationAwareBeanPostProcessor 接口
  在前面讲过InstantiationAwareBeanPostProcessor 是用来提前实例化对象的,而SmartInstantiationAwareBeanPostProcessor是InstantiationAwareBeanPostProcessor 的接口,他是用来干啥呢?
  在createBeanInstance方法中的源码: // 省略代码.... // 明确构造器从BeanPostProcessor中,对应的是 AutowiredAnnotationBeanPostProcessor // 他是 SmartInstantiationAwareBeanPostProcessor 的子类,使用determineCandidateConstructors进行 // 解析构造函数 Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName); if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||     mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {   return autowireConstructor(beanName, mbd, ctors, args); } // 省略代码....
  点进去: protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)   throws BeansException {    if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {     for (BeanPostProcessor bp : getBeanPostProcessors()) {       if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {         SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;         // 决定候选的构造函数         Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);         if (ctors != null) {           return ctors;         }       }     }   }   return null; }
  可以看到这个接口是用来解析BeanClass的构造函数的,SmartInstantiationAwareBeanPostProcessor的实现类AutowiredAnnotationBeanPostProcessor,这个类是用来解析确定合适的构造函数,重点解析了@Autowired注解,并且还解析了@Value注解和@Lookup注解。
  当解析出来构造函数之后,那么就调用autowireConstructor方法进行实例化,解析时会new一个构造器解析器ConstructorResolver ,在解析factoryMehod时也是使用的这个类使用的是instantiateUsingFactoryMethod这个方法,并且解析factoryMethod更加复杂,需要判断是否是静态的工厂创建还是实例工厂创建,而自动装配的构造解析相对来说简单一些,使用autowireConstructor方法进行解析。
  最终解析出构造方法和构造参数之后进行实例化: // 使用合适的构造方法和构造参数进行实例化 bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
  实例化: private Object instantiate(   String beanName, RootBeanDefinition mbd, Constructor<?> constructorToUse, Object[] argsToUse) {    try {     // 获取实例化策略,一般使用 CglibSubClassingInstantiationStrategy     InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy();     if (System.getSecurityManager() != null) {       return AccessController.doPrivileged((PrivilegedAction) () ->                                            strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse),                                            this.beanFactory.getAccessControlContext());     }     else {       // 开始实例化       return strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);     }   }   catch (Throwable ex) {     throw new BeanCreationException(mbd.getResourceDescription(), beanName,                                     "Bean instantiation via constructor failed", ex);   } }  public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,                           final Constructor<?> ctor, Object... args) {   if (!bd.hasMethodOverrides()) {     if (System.getSecurityManager() != null) {       // use own privileged to change accessibility (when security is on)       AccessController.doPrivileged((PrivilegedAction) () -> {         ReflectionUtils.makeAccessible(ctor);         return null;       });     }     // 实例化类,反射调用     return BeanUtils.instantiateClass(ctor, args);   }   else {     // 如果方法被覆盖,lookup-method 和 replace-method     return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);   } }
  如果前面的解析都没有到Bean,那么就会使用无参构造函数进行解析: // 省略代码.... // Preferred constructors for default construction? // 首选的构造器为默认的创建方式,使用了@Primary注解的为首选的创建对象方式 ctors = mbd.getPreferredConstructors(); if (ctors != null) {   return autowireConstructor(beanName, mbd, ctors, null); }  // No special handling: simply use no-arg constructor. // 调用无参构造函数实例化对象 return instantiateBean(beanName, mbd);
  实例化Bean: protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {   try {     Object beanInstance;     if (System.getSecurityManager() != null) {       beanInstance = AccessController.doPrivileged(         (PrivilegedAction) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),         getAccessControlContext());     }     else {       // 实例化对象,使用反射进行创建       beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);     }     // 创建一个Bean的包装器     BeanWrapper bw = new BeanWrapperImpl(beanInstance);     // 初始化Bean的包装器     initBeanWrapper(bw);     return bw;   }   catch (Throwable ex) {     throw new BeanCreationException(       mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);   } }
  这里可以看到前面使用factoryMethod 和autowireConstructor 解析构造函数进行实例化还是使用无参构造函数进行实例化都是将Bean进行了包装,那这个包装有啥作用呢? BeanWrapper的作用
  我们先来看下前面的方法是怎么创建BeanWrapper的:
  factory-method 解析,ConstructorResolver#instantiateUsingFactoryMethod 方法: public BeanWrapper instantiateUsingFactoryMethod( 			String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) { 		// 创建一个Bean的包装器 		BeanWrapperImpl bw = new BeanWrapperImpl(); 		this.beanFactory.initBeanWrapper(bw); 		// factoryBean 		Object factoryBean; 		// factory 工厂类 		Class<?> factoryClass; 		// 标识是否是静态的工厂 		boolean isStatic;         // 省略代码.... }
  SmartInstantiationAwareBeanPostProcessor子类AutowiredAnnotationBeanPostProcessor 解析出构造函数,然后使用ConstructorResolver#autowireConstructor 执行: public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd, 			@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) { 		// 创建一个包装器 		BeanWrapperImpl bw = new BeanWrapperImpl(); 		// 初始化包装器 		this.beanFactory.initBeanWrapper(bw); 		// 构造函数 		Constructor<?> constructorToUse = null; 		// 构造参数 		ArgumentsHolder argsHolderToUse = null; 		// 需要使用的构造参数 		Object[] argsToUse = null; 		// 明确的构造参数不为空,则赋值给将要执行实例化的构造参数 		if (explicitArgs != null) { 			argsToUse = explicitArgs; 		}         // 省略代码.... }
  最终都是会进行转换服务ConversionService和PropertyEditorRegistry的注册,一个是用来进行属性类型转换的,一个是用来属性值解析的: protected void initBeanWrapper(BeanWrapper bw) {   // 获取转换服务放到bean的包装器中   bw.setConversionService(getConversionService());   // 注册定制的属性编辑器   registerCustomEditors(bw); }
  在前面的文章中,介绍了这两个如何使用,而且还自定义了属性编辑器和类型转换,需要的小伙伴可以去看看:
  https://www.cnblogs.com/redwinter/p/16167214.html 和 https://www.cnblogs.com/redwinter/p/16241328.html
  到这里Bean的实例化就完成了,接着往下看源码: protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)   throws BeanCreationException {    // Instantiate the bean.   BeanWrapper instanceWrapper = null;   // 从缓存中获取FactoryBean的Bean对象   if (mbd.isSingleton()) {     instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);   }   if (instanceWrapper == null) {     // 实例化对象     instanceWrapper = createBeanInstance(beanName, mbd, args);   }   // 从包装器中获取Bean对象   Object bean = instanceWrapper.getWrappedInstance();   // 从包装器中获取Bean类型   Class<?> beanType = instanceWrapper.getWrappedClass();   if (beanType != NullBean.class) {     mbd.resolvedTargetType = beanType;   }    // Allow post-processors to modify the merged bean definition.   synchronized (mbd.postProcessingLock) {     if (!mbd.postProcessed) {       try {         // 合并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;     }   } }
  点进去: protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {   for (BeanPostProcessor bp : getBeanPostProcessors()) {     if (bp instanceof MergedBeanDefinitionPostProcessor) {       MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;       // 执行合并BeanDefinition       bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);     }   } }
  可以看到这里出现了一个接口MergedBeanDefinitionPostProcessor,这个接口也是BeanPostProcessor的子接口,那他到底是干啥用的呢? MergedBeanDefinitionPostProcessor 接口
  点击发现这个接口的实现类全是跟注解相关的,而最重要的是CommonAnnotationBeanPostProcessor实现类,在构造函数中设置了两个注解:@PostConstruct 和 @PreDestroy ,一个是在初始化完之后调用,一个是容器销毁时调用。CommonAnnotationBeanPostProcessor这个类的父类为InitDestroyAnnotationBeanPostProcessor,用于处理初始化和销毁方法的。
  CommonAnnotationBeanPostProcessor 的构造器: public CommonAnnotationBeanPostProcessor() { 		setOrder(Ordered.LOWEST_PRECEDENCE - 3); 		// 初始化PostConstruct PreDestroy注解 		// 调用父类的方法进行设置 		setInitAnnotationType(PostConstruct.class); 		setDestroyAnnotationType(PreDestroy.class); 		ignoreResourceType("javax.xml.ws.WebServiceContext"); 	}
  CommonAnnotationBeanPostProcessor 合并方法: public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) { 		// 调用父类 		super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName); 		InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null); 		metadata.checkConfigMembers(beanDefinition); 	}
  点击postProcessMergedBeanDefinition方法发现调用了父类的这个方法,然后执行了一个叫查找生命周期元数据的方法findLifecycleMetadata。 public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) { 		LifecycleMetadata metadata = findLifecycleMetadata(beanType); 		metadata.checkConfigMembers(beanDefinition); 	}
  查找生命周期的元数据: private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) { 		if (this.lifecycleMetadataCache == null) { 			// Happens after deserialization, during destruction... 			return buildLifecycleMetadata(clazz); 		} 		// Quick check on the concurrent map first, with minimal locking. 		// 查询缓存 		LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz); 		if (metadata == null) { 			synchronized (this.lifecycleMetadataCache) { 				// 再次查询 				metadata = this.lifecycleMetadataCache.get(clazz); 				if (metadata == null) { 					// 没有查询到就去构建生命周期的元数据 					metadata = buildLifecycleMetadata(clazz); 					this.lifecycleMetadataCache.put(clazz, metadata); 				} 				return metadata; 			} 		} 		return metadata; 	}
  构建生命周期元数据: private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {   // 这里的initAnnotationType 就是子类set进去的@PostConstruct   // destroyAnnotationType 就是子类set进去的@PreDestroy   if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {     return this.emptyLifecycleMetadata;   }   // 存放初始化方法   List initMethods = new ArrayList<>();   // 存放销毁方法   List destroyMethods = new ArrayList<>();   Class<?> targetClass = clazz;    do {     final List currInitMethods = new ArrayList<>();     final List currDestroyMethods = new ArrayList<>();      ReflectionUtils.doWithLocalMethods(targetClass, method -> {       // 如果找到方法上有@PostConstruct注解,这加入到当前初始化方法集合中       if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {         // 创建一个生命周期元素         //LifecycleElement element = new LifecycleElement(method);         currInitMethods.add(new LifecycleElement(method));       }       // 如果找到方法上标有@PreDestroy 注解,就加入到当前销毁方法集合中       if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {         currDestroyMethods.add(new LifecycleElement(method));       }     });     // 赋值到初始化方法集合和销毁方法集合中     initMethods.addAll(0, currInitMethods);     destroyMethods.addAll(currDestroyMethods);     targetClass = targetClass.getSuperclass();   }   // 遍历查找   while (targetClass != null && targetClass != Object.class);   // 如果没有解析到,那么返回一个空的生命周期元数据,否则创建一个生命周期元素并放入初始化方法和销毁方法的集合   return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :           new LifecycleMetadata(clazz, initMethods, destroyMethods)); }
  最终发现实际上就是在解析我们的Bean的方法上是否标记了@PostConstruct注解和@PreDestroy方法,如果有就加入到生命周期元数据中,并且将解析到的方法放入到BeanDefinition的externallyManagedInitMethods和externallyManagedDestroyMethods集合中。
  Bean初始化和销毁方法解析和执行流程如下:
  Bean的合并大概的意思就是做了自定义初始化和销毁方法的解析,并在后期调用BPP时执行。
  Spring Bean的实例化基本就解析完了,接下来开始解析循环依赖和Bean的属性填充部分。
  如果本文对你有帮助,别忘记给我个3连 ,点赞,转发,评论,,咱们下期见。
  收藏 等于白嫖,点赞才是真情。
  原文 https://www.cnblogs.com/redwinter/p/16268667.html
上海各大互联网医院接诊量急遽增加!建议勿重复配药,发热了也可打电话咨询连日来,上海各大医疗机构的互联网医院门诊和处方量急遽增加,线下门诊开药人数也居高不下。医生提醒,解热镇痛药品种很多药理相近,请市民理性配药,不要重复囤药。线上看病接诊量成倍上升复诊绿色水运看湖南常德石门航道为旅游注入新动能编者按湖南是内河水运大省,航道里程1。2万公里全国第三,其中千吨级以上航道1209公里千吨级以上港口泊位124个,2021年全省完成港口货物吞吐量2。46亿吨。近年来,湖南用绿色为常年晚饭配白酒的人,如今身体怎样了?30年酒龄大爷给出答案曹操曾说过何以解忧,唯有杜康。酒能不能解忧暂且不说,在辛苦劳累了一整天之后,偶尔喝点小酒倒也不失为一个放松解压的好办法,邻居的王大爷就是如此,据他自己所说,每日里必然要喝上2两小酒薛立斋医案79岁老爷子少妾入房之后,身体竟出现这些症状住在通安桥的一人,叫顾大,今天的医案是他父亲,年纪79岁高龄,这个年纪在古代应该是高寿了,放在今天也算是很高寿。仲冬将出,在这年的冬天马上快要过去的时候,冬主蜇藏,而春主生发,冬天科学家将谷物醇溶蛋白支架用于干细胞培养,为生产细胞肉提供思路近日,新加坡国立大学食品科学系教授黄德建团队通过在蛋白支架上接种和培养猪肌肉干细胞,成功制备一种细胞培养猪肉片原型,为生产细胞培养肉提供了新思路。具体来说,他们首次以谷物醇溶蛋白(怎样缓解眼部疲劳?现在大部分人都跟小编一样,白天在伏案工作,晚上回到家通过手机和电脑看剧玩游戏就连学生也是天天通过手机或电脑上网课。这样每天超负荷用眼就容易导致眼睛疲劳,使得视力下降,甚至患上各种眼阳了不用惊慌,症状比较轻,居家备好这4样食物,心里才有底2023年的春节比较特殊,赶上新冠疫情防控的放开,大家居家过年的比例会更大些。我们居家时也要防止家人被感染,如果不小心阳了,大家不用惊慌。若身体的症状比较轻,记得备好以下这4样食物国足缘何没肌肉?前边缘国脚我们专注脚下功夫,不重视身体对抗卡塔尔世界杯已经接近尾声。将近一个月的比赛,各个平台的解说员,有不少是国内的退役足球运动员。可以发现,整个解说的过程,很少会提到咱们自家的事情,毕竟没去世界杯,提到了自然避免不了尴河南一酒友,喝了10年的白酒单火了,行家真会喝,都是珍品佳酿河南人的酒量在全国可谓是名列前茅。因为提到河南,我们总是先想到人口大省粮食大省,可殊不知河南还是一个白酒消耗大省,每年在白酒上的消耗高达600亿。但可惜的是,河南虽然盛产粮食,却并晚上不到10点就开始犯困,凌晨34点就醒,这是衰老的前兆吗?导语睡眠对于维持身体健康而言,有着非常重要的意义和作用,在人们的一生当中,大约有13的时间都是在睡眠里度过的,我们大家与床铺接触的时间比拥抱父母的时间还要更多一些。不管是白发苍苍的武汉每晚最低温都在零度常吃5种食物帮你健康过冬!武汉市气象台预计,未来三天武汉晴天到多云,早晚温差较大,空气质量轻度污染,老人和孩子适当减少外出,注意保暖。今天白天晴天最高气温12,最低气温1湿度5090,风偏北风3级明天晴天到
交易15场5创生涯新高!毕竟是能单换KD的鹈鹕117112击败了老鹰全场CJ26投9中,拿到25分8助4板,命中率虽然不高吧,但整体表现确实相当不错。被交易到鹈鹕之后,CJ总计打了15场比赛,投篮命中率高达50。5,真实命中国足坛文体恋,那英苦恋高峰无果,李金羽梅开二度中国足坛产生过几对引入瞩目的文体恋,但几乎都是以分手或者离婚收场。让我们来看看有哪些1陶伟吕丽萍陶伟,1966年出生于北京市,80年代效力于北京队,曾入选过国家青年队。1988年,大手分4个等级乔丹抓南瓜A级,J博士单手大回环S级,那SSS呢?毫不夸张地说,能够被NBA球队看中并选入联盟的球员,无一例外都是身体素质最为顶级的,除了弹跳速度等动态天赋惊人外,他们的静态天赋更是一绝,尤其是手掌,那尺寸简直大到超出了人们的常识苏炳添,你的奥运奖牌终于来了据国际田联官网信息,国际田联的运动员介绍中,苏炳添谢震业吴智强汤星强的资料上都标注了奥运会铜牌。恭喜中国接力队!在去年举行的东京奥运会田径男子4100米接力比赛中,中国队苏炳添谢震中国名将02022羽毛球全英公开赛进入到半决赛的较量,女单半决赛,中国台北名将戴资颖对阵韩国天才少女安洗莹,最终,戴资颖连输两局02完败出局,安洗莹则是顺利晋级,锁定了首个女单决赛席位。已经詹姆斯用19年,砍下36947分,贾巴尔19年拿了多少分?在超越邮差马龙之后,摆在詹姆斯面前的名字,只剩下最后一个了,那就是天勾贾巴尔。翻看NBA历史总得分榜,名列前茅的个个都是超级巨星,一共只有7位30000分先生,从超越张伯伦诺维茨基14岁宣称要成为传奇人物他,容颜如玉,身姿如松,翩若惊鸿,宛若游龙,一个14岁就宣称要成为传奇人物的花样滑冰选手羽生结弦。日本资深体育新闻记者野口美惠新书羽生结弦王者之路讲述这位不待扬鞭自奋蹄的花样滑冰奥F1巴林站法拉利1。2带回,周冠宇创造历史拿1分,红牛0分刚刚结束的2022F1巴林站法拉利青春组合勒克莱尔和赛恩斯分获冠亚军,法拉利也是正式宣布重回巅峰。梅赛德斯奔驰的汉密尔顿最后时刻逼的佩雷兹失误夺得第3,本站梅奔显然没有足够的速度争尘埃落定,196cm国字号新星加盟新疆,能否成为后卫线的答案?送走多位老将,加上莫泰无法回归,新疆男篮前两阶段遭遇了低谷期,从一支冲冠球队,沦为CBA弱旅,好在摩尔特里的到来,加上球队状态触底反弹,新疆男篮目前排在第13名,依然保留了冲击季后19分惨败!CBA瞩目1战定3队命运,12强出炉,徐长锁要感谢杜锋CBA常规赛进入最后阶段,本轮迎来一场焦点大战,广东男篮正面迎战新疆男篮。虽然新疆男篮已经已非往日,但是近期的出色战绩,已经季后赛的关键时刻,标志着即便是面对劲敌广东,依旧百分百的带头大哥天下英雄谁敌手,梅罗?踢波当如齐玄宗!普通人一冠难求,而他却拿到手软,联赛冠军杯赛冠军欧冠冠军欧洲冠军世界冠军法甲最佳意甲最佳欧冠最佳法国足球先生欧洲金球奖世界足球先生冠军教练,法