Spring框架你敢写精通,面试官就敢问@Autowired注解的实现原理
面试官: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注解的实现原理相关推荐
- 视频教程-Spring框架快速入门到精通-Java
Spring框架快速入门到精通 十年项目开发经验,主要从事java相关的开发,熟悉各种mvc开发框架. 王振伟 ¥18.00 立即订阅 扫码下载「CSDN程序员学院APP」,1000+技术好课免费看 ...
- 我这样回答了Spring 5的新特性,面试官对我刮目相看 | 文末送书
最近,有一个小伙伴拿到了自己满意的Offer,和他交谈的过程中得知他面试官问他关于Spring的问题比较多,其中最让面试官满意的就是自己回答关于Spring 5的知识点回答的不错. Spring5是2 ...
- ❤️六万字《Spring框架从入门到精通》(建议收藏)❤️
❤️ Spring 代码:https://github.com/Donkequan/Spring-Study ❤️ 希望各位博友三连+关注!!! 1.简介 spring理念:是现有的技术更加容易使用, ...
- 【Spring】3.助你跟面试官侃一个小时的AOP
使用 代理模式 是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系 ...
- java录排名怎么写_面试官:Java排名靠前的工具类你都用过哪些?
你知道的越多,不知道的就越多,业余的像一棵小草! 你来,我们一起精进!你不来,我和你的竞争对手一起精进! 编辑:业余草 推荐:https://www.xttblog.com/?p=5158 在Java ...
- vue插槽面试题_关于前端Vue框架的面试题,面试官可能会问到哪些。?
这年头,程序员面试都讲究坐姿,姿势不对,努力白费. 参照下图,请同学们对号入座. 回想一下,自己平时面试的坐姿,你在面试官眼里,大概是什么形象,可能是工程师,也可能是键盘侠,或者找麻烦的. 当然了,想 ...
- Spring框架从入门到精通(纯干货,建议收藏)
文章目录 概述 ioc控制反转 配置文件 使用spring创建对象 给属性赋值 set注入 构造注入 引用类型的自动注入 注解 简单类型属性注入@Value(掌握) 引用类型注入@Autowired ...
- [一年前写]华为面试官面试
呵呵,今天赶巧碰上了华为的面试官,很不辛的被pass掉了.讲讲大概的经过吧. 说起来能被华为面试确实有点巧,我在华清远见培训嵌入式,然后武汉软通动力公司就来培训的地方面试,过了很久很久--我不记得有 ...
- Spring框架面试题总结(面试必备)
1. spring 概述部分 1.1 什么是spring? 1.2 spring框架的核心? 1.3 spring框架的优缺点 1.4 spring5 的主要模块构成 1.5 Spring 框架中都用 ...
最新文章
- Science发布2021年度十大科学突破榜单:除了AlphaFold2,还有哪些大丰收?
- mysql 2006测试_狂神说MySQL06:事务和索引
- 多线程:线程池里的队列BlockingQueue
- 电气期刊论文实现:基于遗传优化的非侵入式居民负荷分解方法(有代码)
- 《别做正常的傻瓜》读书笔记
- redux-form(V7.4.2)笔记(三)之Flow简介
- 12.04 ubuntu 安装微软雅黑的字体
- Java集合框架--List、Set、Map
- Fastjson 1.2.22-24 反序列化漏洞分析
- RxJAVA notes
- Android 代码中的常见的问题总结
- STM32F407 FSMC驱动NAND FLASH MX30LF2GE8AB 附带测试程序链接
- PLL锁相环及其locked信号
- JavaScript JSON 格式操作
- mysql select if 使用
- iOS关于subView和superview的关系
- java: 读取D:\repository\org\lz4\lz4-java\1.7.1\lz4-java.jar时出错; error in opening zip file解决方案
- 用pyQt实现信号采集数据图形化显示
- 李建忠设计模式之“单一职责”模式
- java阿姆斯特朗数,Java判断阿姆斯特朗数