@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相关推荐

  1. Spring框架你敢写精通,面试官就敢问@Autowired注解的实现原理

    面试官:Spring框架中的@Autowired注解可以标注在哪些地方? 小小白:@Autowired注解可以被标注在构造函数.属性.setter方法或配置方法上,用于实现依赖自动注入. 面试官:有没 ...

  2. 实例化bean中有@Autowired注解的有参构造函数(二)

    接着上一篇继续分析有参构造函数: 伪代码: @Autowiredpublic AutowiredConstructorBean(SC sc,CQ cq) {System.out.println(sc) ...

  3. autowired java配置_使用autowired注解怎么配置配置文件

    展开全部 1. 使用Spring注解来注入属性e69da5e6ba9062616964757a686964616f31333363363434 1.1. 使用注解以前我们是怎样注入属性的 类的实现: ...

  4. @autowired注解原理_Spring框架第二谈:IOC,xml配置文件给属性赋值,注解实现赋值...

    在spring的对象文件中,给Java对象的属性赋值: di依赖注入,表示创建对象,给属性赋值di的实现方法有两种:1.在spring的配置文件中,使用标签完成,叫做基于XML的di实现2.使用spr ...

  5. @autowired注解原理_SpringBoot注解大全,收藏一波!!!

    一.注解(annotations)列表 二.注解(annotations)详解 三.JPA注解 四.springMVC相关注解 五.全局异常处理 <Java 2019 超神之路> < ...

  6. @autowired注解_SpringBoot常用注解大全

    作者:tanwei81 , 链接:www.cnblogs.com/tanwei81 一.注解(annotations)列表 @SpringBootApplication: 包含了@ComponentS ...

  7. 不能执行autowired_想用@Autowired注入static静态成员?官方不推荐你却还偏要这么做...

    生命太短暂,不要去做一些根本没有人想要的东西.本文已被 https://www.yourbatman.cn 收录,里面一并有Spring技术栈.MyBatis.JVM.中间件等小而美的专栏供以免费学习 ...

  8. Spring 基于注解(annotation)的配置之@Autowired注解

    Setter 方法中的 @Autowired 当 Spring遇到一个在 setter 方法中使用的 @Autowired 注解,它会试图执行 byType 自动连接.换言之,加了@Autowired ...

  9. Spring自动装配----注解装配----Spring自带的@Autowired注解

    Spring自动装配----注解装配----Spring自带的@Autowired注解 父类 package cn.ychx;public interface Person {public void ...

最新文章

  1. ubuntu18.04.4 安装 dlib (解决 Running setup.py install for dlib ... error错误)
  2. fastJson,gosn使用小结
  3. RHEL8 配置光盘源和yum源
  4. ON_NOTIFY消息中的id坑了我一天
  5. p内的a截取字符串,会将a与p的其他内容撑开(IE6、IE7)
  6. java调用其他程序吗_java本地方法如何调用其他程序函数,方法详解
  7. BI工具那么多 该如何选择
  8. 计算机及软件工程专业基础综合,2019年东华大学854计算机及软件工程专业基础综合考研初试大纲...
  9. python实现图片拼接长图_python 多张图片拼接为一张长图
  10. PSP自制程序打包ISO方法及注意事项
  11. 虚幻AI蓝图基础笔记(万字整理)
  12. 177G Python语言编程视频教程大全
  13. 微信小程序文字链接生成二维码,扫描识别二维码
  14. hdu5761Rower Bo(计算几何)
  15. TreeMap和LinkedHashMap
  16. 电力、工业、林业、安防都在用的国产测距仪---TFN D4KI 激光测距仪 双目
  17. 朴素贝叶斯文本分类(python代码实现)
  18. ICPC Latin American Regional – 2017 B题(模拟+思维)
  19. pytorch 利用tensorboard显示loss,acc曲线等
  20. matlab 对称天线动态图,关于Matlab的对称振子天线分析.pdf

热门文章

  1. [转载] Java之继承
  2. ruby hash方法_Ruby中带有示例的Hash.flatten方法
  3. 单链表删除整表_单链表删除
  4. Linux中远程文件的传输
  5. 利用永恒之蓝入侵服务器复制文件,msf利用永恒之蓝进行漏洞攻击
  6. 聚类分析在用户行为中的实例_用户关注行为数据分析过程详解-描述统计+聚类...
  7. css 百分比 怎么固定正方形_css样式写出三角形,宽高自适应的正方形,扇形!...
  8. php设置用户头像,PHP针对多用户实现更换头像功能
  9. fastdfs java token_fastdfs 开启 token 防盗链
  10. 数据库拆分字符串函数_PHP | 不使用库函数将逗号分隔的字符串拆分为数组