spring依赖注入属性填充(上)
我们会经常使用@Autowired、@Resource、@Value 这些注解给属性赋值。
那么这几个注解是怎么给属性赋值的呢?还有其他的方法可以给属性赋值吗?使用@Bean注解+set方法,设置依赖注入方式(byName,byType)。
配置类
bean
测试
上面几张图:在配置类中使用@Bean 注解并设置注入方式, 配置bean。
这种方式在spring中已经被定义为过期的方法,但是还能用,只是spring不建议使用。
person类的属性上并没有加@Autowired,但是也能注入成功。
上图这段代码就是记录这种注入方式的代码,记住是记录,意思是说:只要用这种方式注入bean的spring都会在这个地方记录,就是将这些bean的名字存到一个集合中,方便后续注入。
PropertyDescriptor[] pds = bw.getPropertyDescriptors();
PropertyDescriptor:属性描述器, 是javaBean 里自带的。在这个属性描述器里会记录属性的名字,属性的set 方法 ,get方法,等等。
前提是必须要有set方法或是get方法,如果一个类里只定义了属性,没有set方法或则是getf方法,那么也是拿不到这个属性的。
PropertyDescriptor中的name属性是通过解析set方法获取的。例如:setOr123 , 那么name属性的值就是 or123。
spring 在拿到所有属性后进行循环遍历for (PropertyDescriptor pd : pds) { if (pd.getWriteMethod() != null && !isExcludedFromDependencyCheck(pd) && !pvs.contains(pd.getName()) && !BeanUtils.isSimpleProperty(pd.getPropertyType())) { result.add(pd.getName()); } }pd.getWriteMethod() != null : 将没有set方法的属性给过滤掉。!pvs.contains(pd.getName()) : 将在MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition方法中赋值过的属性过滤掉。!BeanUtils.isSimpleProperty(pd.getPropertyType()): 将简单类型的属性过滤掉。
上图这个方法的最后面,就是下面这段代码if (pvs != null) { applyPropertyValues(beanName, mbd, bw, pvs); }
将记录属性进行赋值。@Autowired,@Value,@Resource给属性赋值
上图中的1是处理 @Autowired,@Value ,2是处理@Resource。
以下主要看是AutowiredAnnotationBeanPostProcessor 这个实现类。
上图中可以看到 AutowiredAnnotationBeanPostProcessor 实现了SmartInstantiationAwareBeanPostProcessor 和 MergedBeanDefinitionPostProcessor 这两个接口。
MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition寻找注入点
根据类找到注入点
注入点:加了@Autowired 的属性或者方法。
ReflectionUtils.doWithLocalFields(targetClass, field -> { MergedAnnotation<?> ann = findAutowiredAnnotation(field); if (ann != null) { if (Modifier.isStatic(field.getModifiers())) { if (logger.isInfoEnabled()) { logger.info("Autowired annotation is not supported on static fields: " + field); } return; } boolean required = determineRequiredStatus(ann); currElements.add(new AutowiredFieldElement(field, required)); } });
上述代码就是拿到类的所有属性,然后循环判断属性上面有没有加注解(@Autowired或@Value只要有一个注解就行)如果有注解且不是静态属性,就会加入到缓存中 currElements。
1.静态的属性属于类的,不依赖于某个对象,也可以称为类属性。不同的对象都可以访问到类的属性。带参数的构造方法中不能包含静态的属性。 它的生命随着类的消亡而消亡。
2.非静态属性只能属于某个对象,其它的对象不能访问它的属性。随着对象的消亡而消亡。
boolean required = determineRequiredStatus(ann);
这行代码的作用 就是处理 required 的,如果等于true 就是必须要给该属性赋值,如果没有值就会报异常。ReflectionUtils.doWithLocalMethods(targetClass, method -> { Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) { return; } MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod); if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) { if (Modifier.isStatic(method.getModifiers())) { if (logger.isInfoEnabled()) { logger.info("Autowired annotation is not supported on static methods: " + method); } return; } if (method.getParameterCount() == 0) { if (logger.isInfoEnabled()) { logger.info("Autowired annotation should only be used on methods with parameters: " + method); } } boolean required = determineRequiredStatus(ann); PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz); currElements.add(new AutowiredMethodElement(method, required, pd)); } });
上述这段代码是处理方法的,和上面的属性大致差不多。
唯一不同的是:Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method); if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) { return; }
这个就是处理桥接方法,有兴趣的可以搜一下。
if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) { return InjectionMetadata.EMPTY; }
这段代码就是判断这个bean 的类型。如果是String等基础数据类型则不需要寻找注入点,就会直接返回。
SmartInstantiationAwareBeanPostProcessor.postProcessProperties 主要是处理属性
在拿到注入点后就会执行这个方法,这个方法中会找到注入点的值,并给注入点赋值。
标号1的地方是找值,找到值后,就会执行标号2 ,给注入点赋值。
全乱了!一则官宣令葡萄牙队内再变天,内维斯失宠,27岁悍将上位2022世界杯北京时间12月16日凌晨,葡萄牙足协官方确认,执教了球队8年的主帅桑托斯离任。当葡萄牙队在世界杯上被摩洛哥队爆冷淘汰后,桑托斯成为了众矢之的,他已经失去了葡萄牙队球迷
为什么宝妈一到冬天就给宝宝补乳铁蛋白?一到冬天,有些宝宝总得生几次病,感冒发烧咳嗽流鼻涕,甚至是呕吐拉肚子,就从来都没停过!这可愁坏了宝妈们!为什么一到冬天,宝宝就容易生病呢?这是因为1。冬天更利于病毒细菌的增长繁殖2
奥密克戎感染者样本调查无症状的多吗?重复感染比例高吗?近期,全国各地奥密克戎成流行态势,感染值正趋于高峰,社交媒体上出现不少人主动分享感染后自愈的经历,消除对病毒的恐惧。未来一定时期内,让更多人重新建立对新冠的具体认知,了解科学防治的
生完孩子肚子松弛,光减肥没用,可能和你的妊娠纹有关随着产后科普的普及,不少宝妈在产后都开始注重产后康复护理。其中对很多宝妈来说比较重要的就是产后减肥。生孩子的时候体重变重,是很多宝妈不能接受的。所以出了月子后就马不停蹄地开始减肥大
我的儿子一出生在2012年7月2日,成都的天气在这个时候很闷热,在这天早上800左右,医生查房,觉得娃娃可以生产了,鉴于娃娃及产妇的特殊情况(婴儿大及高龄产妇)医生早就确定了需要剖腹产。当
你不知道的冷知识食物跟人一样,也有性格点击上方关注我们,了解更多健康知识!人有急性子,也有慢性子等与生俱来的性格禀赋,食物和药物也跟人类似,也有它自己的性格。药食同源,食物和药物一样也分为寒热温凉四种性质。热性的食物就
为什么中药不能乱喝?为什么中药不能乱喝?鼻炎多年了一直很烦恼,鼻甲肥大鼻涕倒流有气泡,甚是苦恼。前段时间自抖音上看倪师视频后自己配药吃,喝了一周效果还不错,自己又添加了七八味药上去,又喝了一周效果非常
有哪些坏习惯会伤嗓子?1吸烟长期吸烟可使支气管黏膜的纤毛受损变短,影响纤毛的清除功能。此外,吸烟使黏膜下腺体增生肥大,黏液分泌增多,以及呼吸道微生态失调,容易阻塞细支气管。另外,被动吸烟和主动吸烟咽喉部
身上有4个防病开关!洗澡时按按,省下大笔买药钱对于大多数人来说,洗澡就是打上沐浴露冲冲洗洗,再简单不过了。但是,真正的养生高手,不会错过生活中每一个养生时机。洗澡这件小事,在他们眼中,就是个好机会!怎么洗个养生澡呢?很简单,洗
假球事件发酵!世界台联CEO颜丙涛主动承认,丁俊晖回应不知情假球事件发酵!世界台联CEO颜丙涛主动承认,丁俊晖回应不知情。目前已经有7位中国选手遭到了世界台联和中国台球协会的共同禁赛,分别是梁文博,颜丙涛,鲁宁,李行,常冰玉,白朗宁,赵剑波
国乒队伍迎大调整,三位队员淡出主力层,刘国梁大手一挥提拔一人2022年即将接近尾声,国乒队伍也已经完成了今年所有的比赛任务,目前正在海南进行冬训,详细总结的同时还要调整好状态,以此迎接2023全新的一年。而对于国乒队伍来说,步入2023年第