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 ,给注入点赋值。
从终南山回望长安(外二首)文连忠照从终南山回望长安(外二首)文连忠照站在冬天的终南山上回望长安长安不见只有无边的蓝烟覆盖着茫茫的长安就像韩愈站在蓝关长安不见只有无边的忧愁让他抹一抹双眼带着揪心的疼痛去了无边的远方在
读书活着最戳你的心窝的地方作者余华文桃子姐姐如果觉得生活艰难,请一定看一下这本书,读完不会觉得活着也是一种幸运。它告诉我们,活着不是为了什么,只是为了活着本身,活着是人生上不能被剥夺的意志,展示人自强不息坚
七夕会养育雨后的山夏日的黄昏,刚下过一场雨,天空格外明净,一朵朵祥云像棉花糖一样浮游着。夕阳西斜,也将云朵映照得更加雪白。雨后的公园,像洗过一样清新,也有了一丝秋天似的凉爽。人群三三两两,有的在湖边
iPadmini6真的适合你么?颜值方面ipadmini6很合我心意,对我这种手小力气小的女生来说,ipadmini6的大小正正好好,外出携带也很方便,躺在床上刷也不觉得很重。全面屏的设计很好看,颜色我买的是粉色
将历代经典iPhone装裱起来!电子垃圾也能变废为宝一般来说,苹果用户的忠诚度很高,很多人是从iPhone4一直用到今天的。而对于之前那些淘汰的iPhone,大家是怎么处理的?其实这些经典的旧iPhone可以拆开做成艺术品,最好是那
体验天龙PMA900NECD播放器最近我们拿到一台天龙的PMA900HNE功放,这是天龙第一台集成HEOS和流媒体功能的HiFi功放机。从天龙官网我们可以看到,它的HIFI产品序列并不复杂,级别最高的当属2500N
模拟火车世界3面向各大平台公布9月6日推出DovetailGames日前公布了模拟火车世界系列的新作模拟火车世界3。该游戏将于9月6日在PC(Steam和Epic游戏商店)PS5PS4XboxSeriesXS和XboxOn
开源MySQLweb端SQL审核平台Yearning开源精选是我们分享GithubGitee等开源社区中优质项目的栏目,包括技术学习实用与各种有趣的内容。本期推荐的是一个开源的web端MySQL审核平台Yearning。Yearni
美媒评下赛季小前TOP10塔杜卡詹前四,嘴哥未进前十引争议今天凌晨,美媒Hoopshype专家团投票选出20222023赛季联盟25大小前锋,塔图姆杜兰特伦纳德詹姆斯位居前四。维金斯未进前十(排名11)具体排名如下1塔图姆2杜兰特3伦纳德
曾经的五位第一中锋生涯数据大比拼曾经的五位第一中锋生涯数据大比拼,有人沦为无人问津的角色!1。霍华德2004年状元,生涯总薪金2。45亿美元,场均15。7分11。8篮板1。3助攻1。8盖帽,58。7命中率生涯获得
麦迪09年的湖人,把科比换成克劳福德照样夺冠,科比的队友太强麦迪09年的湖人,把科比换成克劳福德照样夺冠,科比的队友太强本人认为,能突破二轮就烧高香了。有些球星只能在巨星身边发挥最大价值,加索尔再厉害为什么在灰熊连季后赛都进不去,这些人后面