@Autowired注解能用在static属性吗?autowired注入static属性上为null
@Autowired注解能用在static属性吗?
答案是否定的,我们来测试下:
日志信息已经很明确了,表示static不能被@Autowired进行复制。为什么呢?我们现在就来一起了解其原因。
首先将我们的测试环境搭建好,
User1类
@Componentpublic
class User1 { @Autowired private static User2 user2; @Autowired private User2 user3;
}
User2类
@Componentpublic
class User2 {}
AppConfig类
@Configuration@ComponentScan("staticDemo")
/*@EnableAspectJAutoProxy*/
/*@Import(MyImportBeanDefinitionRegistrar.class)*/
public class AppConfig {}
Test类
public class Test { public static void main(String[] args) { AnnotationConfigApplicationContext annotationConfigApplicationContext=new AnnotationConfigApplicationContext(AppConfig.class); }
}
然后将代码定位在依赖注入的入口
此时我们的beanName是User1类,我们需要注入User1类,然后我们进入这个方法
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) { if (bw == null) { if (mbd.hasPropertyValues()) { throw new BeanCreationException( mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance"); } else { // Skip property population phase for null instance. return; } } // Give any InstantiationAwareBeanPostProcessors the opportunity to modify the // state of the bean before properties are set. This can be used, for example, // to support styles of field injection. //Spring判断你是不是自己实现了InstantiationAwareBeanPostProcessor,如果实现了,而且返回false, // Spring就不会继续执行了,一般不会用到 if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) { return; } } } } //判断是否已经对属性赋值 PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); //判断属性植入的模式,默认NO int resolvedAutowireMode = mbd.getResolvedAutowireMode(); if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) { MutablePropertyValues newPvs = new MutablePropertyValues(pvs); // Add property values based on autowire by name if applicable. if (resolvedAutowireMode == AUTOWIRE_BY_NAME) { autowireByName(beanName, mbd, bw, newPvs); } // Add property values based on autowire by type if applicable. if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) { autowireByType(beanName, mbd, bw, newPvs); } pvs = newPvs; } boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors(); boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE); PropertyDescriptor[] filteredPds = null; if (hasInstAwareBpps) { if (pvs == null) { pvs = mbd.getPropertyValues(); } //这里才是通过后置处理器完成属性注入的工作 for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp; PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); if (pvsToUse == null) { return; } } pvs = pvsToUse; } } } if (needsDepCheck) { if (filteredPds == null) { filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching); } checkDependencies(beanName, mbd, filteredPds, pvs); } if (pvs != null) { applyPropertyValues(beanName, mbd, bw, pvs); } }
这里有两个for循环,我们关注第二个for循环,找到后置处理器是
然后点进去
这里第一行代码就是获取我们的数据信息,并且用InjectionMetadata的方式进行封装,获取InjectionMetadata后就可以通过反射的方式进行属性注入了,这里在前面的Spring源码章节我们已经详细介绍了,就不再叙述。我们进入这个findAutowiringMetadata方法,瞧一瞧他是如何获取的,
我们看到InjectionMetadata封装了哪些信息,其中包含了我们的user3这个属性,注意这个user3是没有static修饰的,user2是被static修饰了的,而这里确没有user2这个属性,先记住这一点,然后我们再看我们的metadata是通过injectionMetadataCache缓存获取的,说明一个我们的static是在存放缓存的时候就将我们的static属性屏蔽掉,接下来我们就验证我们的猜想。
Spring何时屏蔽static属性?
我们将代码定位在AbstractAutowireCapableBeanFactory.doCreateBean方法
跟踪进去
再跟踪
可以看到已经回到了我们find方法,点进去,注意下面的红线表示我们这里是找的user1类的属性
然后这里我们关注的是injectionMetadataCache缓存
此时缓存里并没有user1的元信息,我们再次跟进
首先看到这里ReflectionUtils.doWithLocalFields,我们点进去
可以看到这里获取了两个我们的属性,一个是静态属性一个是常态属性,然后我们再回到buildAutowiringMetadata方法,注意这里的filed是函数试变成,它会回调这里的代码
我们就可以看到如果我们的属性是static,那么Spring会直接抛弃,
可以看到我们已经得到了验证,Spring就是在这里抛弃了static的属性,至于为什么要抛弃static属性呢?笔者猜测这里需要回到JVM的一些知识,我们都知道static是面向类级别,而Spring通常是面向普通的单例对象,如果我们将单例的对象中static属性赋值,那么就会影响我们这个类的其他对象的值,个人认为这是Spring不希望看到的,这也是不科学的。
@Autowired注解能用在static属性吗?autowired注入static属性上为null相关推荐
- Spring框架你敢写精通,面试官就敢问@Autowired注解的实现原理
面试官:Spring框架中的@Autowired注解可以标注在哪些地方? 小小白:@Autowired注解可以被标注在构造函数.属性.setter方法或配置方法上,用于实现依赖自动注入. 面试官:有没 ...
- 实例化bean中有@Autowired注解的有参构造函数(二)
接着上一篇继续分析有参构造函数: 伪代码: @Autowiredpublic AutowiredConstructorBean(SC sc,CQ cq) {System.out.println(sc) ...
- autowired java配置_使用autowired注解怎么配置配置文件
展开全部 1. 使用Spring注解来注入属性e69da5e6ba9062616964757a686964616f31333363363434 1.1. 使用注解以前我们是怎样注入属性的 类的实现: ...
- @autowired注解原理_Spring框架第二谈:IOC,xml配置文件给属性赋值,注解实现赋值...
在spring的对象文件中,给Java对象的属性赋值: di依赖注入,表示创建对象,给属性赋值di的实现方法有两种:1.在spring的配置文件中,使用标签完成,叫做基于XML的di实现2.使用spr ...
- @autowired注解原理_SpringBoot注解大全,收藏一波!!!
一.注解(annotations)列表 二.注解(annotations)详解 三.JPA注解 四.springMVC相关注解 五.全局异常处理 <Java 2019 超神之路> < ...
- @autowired注解_SpringBoot常用注解大全
作者:tanwei81 , 链接:www.cnblogs.com/tanwei81 一.注解(annotations)列表 @SpringBootApplication: 包含了@ComponentS ...
- 不能执行autowired_想用@Autowired注入static静态成员?官方不推荐你却还偏要这么做...
生命太短暂,不要去做一些根本没有人想要的东西.本文已被 https://www.yourbatman.cn 收录,里面一并有Spring技术栈.MyBatis.JVM.中间件等小而美的专栏供以免费学习 ...
- Spring 基于注解(annotation)的配置之@Autowired注解
Setter 方法中的 @Autowired 当 Spring遇到一个在 setter 方法中使用的 @Autowired 注解,它会试图执行 byType 自动连接.换言之,加了@Autowired ...
- Spring自动装配----注解装配----Spring自带的@Autowired注解
Spring自动装配----注解装配----Spring自带的@Autowired注解 父类 package cn.ychx;public interface Person {public void ...
最新文章
- ubuntu18.04.4 安装 dlib (解决 Running setup.py install for dlib ... error错误)
- fastJson,gosn使用小结
- RHEL8 配置光盘源和yum源
- ON_NOTIFY消息中的id坑了我一天
- p内的a截取字符串,会将a与p的其他内容撑开(IE6、IE7)
- java调用其他程序吗_java本地方法如何调用其他程序函数,方法详解
- BI工具那么多 该如何选择
- 计算机及软件工程专业基础综合,2019年东华大学854计算机及软件工程专业基础综合考研初试大纲...
- python实现图片拼接长图_python 多张图片拼接为一张长图
- PSP自制程序打包ISO方法及注意事项
- 虚幻AI蓝图基础笔记(万字整理)
- 177G Python语言编程视频教程大全
- 微信小程序文字链接生成二维码,扫描识别二维码
- hdu5761Rower Bo(计算几何)
- TreeMap和LinkedHashMap
- 电力、工业、林业、安防都在用的国产测距仪---TFN D4KI 激光测距仪 双目
- 朴素贝叶斯文本分类(python代码实现)
- ICPC Latin American Regional – 2017 B题(模拟+思维)
- pytorch 利用tensorboard显示loss,acc曲线等
- matlab 对称天线动态图,关于Matlab的对称振子天线分析.pdf
热门文章
- [转载] Java之继承
- ruby hash方法_Ruby中带有示例的Hash.flatten方法
- 单链表删除整表_单链表删除
- Linux中远程文件的传输
- 利用永恒之蓝入侵服务器复制文件,msf利用永恒之蓝进行漏洞攻击
- 聚类分析在用户行为中的实例_用户关注行为数据分析过程详解-描述统计+聚类...
- css 百分比 怎么固定正方形_css样式写出三角形,宽高自适应的正方形,扇形!...
- php设置用户头像,PHP针对多用户实现更换头像功能
- fastdfs java token_fastdfs 开启 token 防盗链
- 数据库拆分字符串函数_PHP | 不使用库函数将逗号分隔的字符串拆分为数组