面试官:Spring框架中的@Autowired注解可以标注在哪些地方?

小小白:@Autowired注解可以被标注在构造函数、属性、setter方法或配置方法上,用于实现依赖自动注入。

面试官:有没有研究过@Autowired注解的实现原理?

小小白:看过它的实现源码。

面试官:那你说一下@Autowired注解的工作原理?

小小白:@Autowired注解的作用是由AutowiredAnnotationBeanPostProcessor实现的,查看该类的源码会发现它实现了MergedBeanDefinitionPostProcessor接口,进而实现了接口中的postProcessMergedBeanDefinition方法,@Autowired注解正是通过这个方法实现注入类型的预解析,将需要依赖注入的属性信息封装到InjectionMetadata类中,InjectionMetadata类中包含了哪些需要注入的元素及元素要注入到哪个目标类中,在Spring容器启动的过程中初始化单例bean的时候通过populateBean方法实现对属性的注入。

public class AutowiredAnnotationBeanPostProcessor extends InstantiationAwareBeanPostProcessorAdapter implements MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {if (beanType != null) {InjectionMetadata metadata = this.findAutowiringMetadata(beanName, beanType, (PropertyValues)null);metadata.checkConfigMembers(beanDefinition);}}public class InjectionMetadata {private static final Log logger = LogFactory.getLog(InjectionMetadata.class);private final Class<?> targetClass;private final Collection<InjectedElement> injectedElements;private volatile Set<InjectedElement> checkedElements;

面试官:AutowiredAnnotationBeanPostProcessor类的postProcessMergedBeanDefinition方法是在什么时候被调用的?

小小白:Spring容器在启动的时候会执行AbstractApplicationContext类的refresh方法,在refresh方法执行的过程中先注册AutowiredAnnotationBeanPostProcessor,然后在对非延迟初始化的单例bean进行初始化时,会间接调用。具体实现细节分析如下。

public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing.prepareRefresh();// Tell the subclass to refresh the internal bean factory.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.// 重点看这里:在这里对AutowiredAnnotationBeanPostProcessor注册registerBeanPostProcessors(beanFactory);// Initialize message source for this context.initMessageSource();// Initialize event multicaster for this context.initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.onRefresh();// Check for listener beans and register them.registerListeners();// Instantiate all remaining (non-lazy-init) singletons.// 重点看这里:对非延迟初始化的单例bean进行初始化finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.finishRefresh();}catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +            "cancelling refresh attempt: " + ex);}// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset 'active' flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;}finally {// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore...resetCommonCaches();}}
}

refresh方法中registerBeanPostProcessors(beanFactory)完成了对AutowiredAnnotationBeanPostProcessor的注册,当执行finishBeanFactoryInitialization(beanFactory)方法对非延迟初始化的单例bean进行初始化时,会执行到AbstractAutowireCapableBeanFactory类的doCreateBean方法,在这个方法中有如下这么一段代码。

synchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {try {applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Post-processing of merged bean definition failed", ex);}mbd.postProcessed = true;}
}

在这段代码中会执行applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName),深入到这个applyMergedBeanDefinitionPostProcessors方法中。

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof MergedBeanDefinitionPostProcessor) {MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);}}
}

可以看到,if的条件判断逻辑是否属于MergedBeanDefinitionPostProcessor,而AutowiredAnnotationBeanPostProcessor正好实现了MergedBeanDefinitionPostProcessor接口,所以在这里调用AutowiredAnnotationBeanPostProcessor类的postProcessMergedBeanDefinition方法。

面试官:你在说一下注入的过程?

小小白:使用AutowiredFieldElement实现对标注在属性上的注入,使用AutowiredMethodElement对标注在方法上的注入。注入过程:根据需要注入的元素的描述信息,按类型或名称查找需要的依赖值,如果依赖没有实例化先实例化依赖,然后使用反射进行赋值。

面试官:@Resource或者@Autowired注解有什么区别?

小小白:虽然@Resource和@Autowired都可以书写标注在属性或者该属性的setter方法之上,但是@Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入;@Autowired默认是按照类型装配注入的,默认情况下它要求依赖对象必须存在如果允许为null,可以设置它required属性为false,如果想按照名称来注入,则需要结合@Qualifier一起使用;@Resource注解是由JDK提供,而@Autowired是由Spring提供。

Spring框架你敢写精通,面试官就敢问@Autowired注解的实现原理相关推荐

  1. 视频教程-Spring框架快速入门到精通-Java

    Spring框架快速入门到精通 十年项目开发经验,主要从事java相关的开发,熟悉各种mvc开发框架. 王振伟 ¥18.00 立即订阅 扫码下载「CSDN程序员学院APP」,1000+技术好课免费看 ...

  2. 我这样回答了Spring 5的新特性,面试官对我刮目相看 | 文末送书

    最近,有一个小伙伴拿到了自己满意的Offer,和他交谈的过程中得知他面试官问他关于Spring的问题比较多,其中最让面试官满意的就是自己回答关于Spring 5的知识点回答的不错. Spring5是2 ...

  3. ❤️六万字《Spring框架从入门到精通》(建议收藏)❤️

    ❤️ Spring 代码:https://github.com/Donkequan/Spring-Study ❤️ 希望各位博友三连+关注!!! 1.简介 spring理念:是现有的技术更加容易使用, ...

  4. 【Spring】3.助你跟面试官侃一个小时的AOP

    使用 代理模式 是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系 ...

  5. java录排名怎么写_面试官:Java排名靠前的工具类你都用过哪些?

    你知道的越多,不知道的就越多,业余的像一棵小草! 你来,我们一起精进!你不来,我和你的竞争对手一起精进! 编辑:业余草 推荐:https://www.xttblog.com/?p=5158 在Java ...

  6. vue插槽面试题_关于前端Vue框架的面试题,面试官可能会问到哪些。?

    这年头,程序员面试都讲究坐姿,姿势不对,努力白费. 参照下图,请同学们对号入座. 回想一下,自己平时面试的坐姿,你在面试官眼里,大概是什么形象,可能是工程师,也可能是键盘侠,或者找麻烦的. 当然了,想 ...

  7. Spring框架从入门到精通(纯干货,建议收藏)

    文章目录 概述 ioc控制反转 配置文件 使用spring创建对象 给属性赋值 set注入 构造注入 引用类型的自动注入 注解 简单类型属性注入@Value(掌握) 引用类型注入@Autowired ...

  8. [一年前写]华为面试官面试

    呵呵,今天赶巧碰上了华为的面试官,很不辛的被pass掉了.讲讲大概的经过吧.  说起来能被华为面试确实有点巧,我在华清远见培训嵌入式,然后武汉软通动力公司就来培训的地方面试,过了很久很久--我不记得有 ...

  9. Spring框架面试题总结(面试必备)

    1. spring 概述部分 1.1 什么是spring? 1.2 spring框架的核心? 1.3 spring框架的优缺点 1.4 spring5 的主要模块构成 1.5 Spring 框架中都用 ...

最新文章

  1. Science发布2021年度十大科学突破榜单:除了AlphaFold2,还有哪些大丰收?
  2. mysql 2006测试_狂神说MySQL06:事务和索引
  3. 多线程:线程池里的队列BlockingQueue
  4. 电气期刊论文实现:基于遗传优化的非侵入式居民负荷分解方法(有代码)
  5. 《别做正常的傻瓜》读书笔记
  6. redux-form(V7.4.2)笔记(三)之Flow简介
  7. 12.04 ubuntu 安装微软雅黑的字体
  8. Java集合框架--List、Set、Map
  9. Fastjson 1.2.22-24 反序列化漏洞分析
  10. RxJAVA notes
  11. Android 代码中的常见的问题总结
  12. STM32F407 FSMC驱动NAND FLASH MX30LF2GE8AB 附带测试程序链接
  13. PLL锁相环及其locked信号
  14. JavaScript JSON 格式操作
  15. mysql select if 使用
  16. iOS关于subView和superview的关系
  17. java: 读取D:\repository\org\lz4\lz4-java\1.7.1\lz4-java.jar时出错; error in opening zip file解决方案
  18. 用pyQt实现信号采集数据图形化显示
  19. 李建忠设计模式之“单一职责”模式
  20. java阿姆斯特朗数,Java判断阿姆斯特朗数

热门文章

  1. DHCP的基本介绍以及在HC3上配置DHCP中继和DHCP snooping
  2. OSChina 周六乱弹 —— 买楼出一块钱,你们出么?
  3. 解决MSDTC 53258故障
  4. Web网页布局的主要方式
  5. React系列---React+Redux工程目录结构划分
  6. 网易OpenStack部署运维实战
  7. 2016年EDM营销新年策略分享
  8. 一种创建进程间COM来启动IE的方式
  9. Cisco BFD双向转发检测技术部署案例
  10. CSS 文字处理总结