构造函数注入
属性注入
方法注入
目前绝大部分的代码都使用第2、第3种。第1种在bean实例化时完成,而第2、第3种的实现原理都是一样的,在属性填充时完成。本篇将介绍第二第三种的是实现原理
在开始之前,如果我们自己设计@Autowired,我们应该怎么实现?我想做法还是比较简单的
通过反射查找bean的class下所有注解了@Autowired的字段和方法获取到字段,通过getBean(字段)获取到对应bean,然后再通过反射调用field的set将bean注入 @Autowired源码分析AutowiredAnnotationBeanPostProcessor类
该类是@Autowired的具体实现类,先预览一下类方法
发现实际有机会介入bean的创建操作只有可能是后置处理器,用于后置处理的有3个方法,其中一个过时不用,分别是postProcessMergedBeanDefinition、postProcessProperties后置处理,我们再看一下这2个方法的具体代码
跟我们的猜想是一样的,首先先找出所有注解了@Autowired的属性或者方法,然后进行注入,当然postProcessMergedBeanDefinition后置处理器的调用肯定是在postProcessProperties之前的,这里我们回顾一下spring bean的创建过程。
2个处理器我已用黄色标出
1.查找所有@Autowired可以看到spring依然在用缓存的方式提高性能,继续跟踪核心代码buildAutowiringMetadata(clazz)
外层 do … while … 的循环被用于递归的查找父类的@Autowired属性或方法通过反射的方式获取到所有属性并循环验证每一个属性是否被@Autowired注解将查找到包含@Autowired注解的filed封装成AutowiredFieldElement,加入到列表中循环查找在方法上的注解将找到的方法封装成AutowiredMethodElement,并加入列表这里需要特别强调一点,InjectedElement被AutowiredFieldElement、AutowiredMethodElement所继承,他们都有各自的inject函数,实现各自的注入。因此改ArrayList elements是拥有2种类型的属性
将找到的所有元素列表和clazz作为参数生成metadata数据返回 2. 注入利用for循环,遍历刚刚我们查到到的elements列表,进行注入。
在上面有特别提醒,这里的element有可能是AutowiredFieldElement类型、或AutowiredMethodElement类型。各自代表@Autowired注解在属性上、以及注解在方法上的2种不同元素。因此他们调用的element.inject(target, beanName, pvs);也是不一样的
2.1 字段注入(AutowiredFieldElement)上方大部分的工作都在做待注入bean的获取以及类型的转换,如果深究下去可以再把spring Ioc讲一遍,但是核心还是getBean(字段)获取到对应bean…我们这里就关心核心的语句,就是这2句
spring通过反射的方式,调用field的set进行属性的注入
2.2 方法注入(AutowiredMethodElement)这里与属性注入最大的区别在于,@Autowired注解在方法上,方法可以拥有多个参数,因此这里需要通过循环将一个个获取,而获取bean的方式于上面一样,本质都是通过getBean获取。
而核心语句还是2句
与属性注入不同的是,当@Autowired注解在方法上,例如我们注解在setter方法上,则只需要直接调用该setter方法将参数数组传入即可以,即使用invoke触发方法,具体属性赋值的过程在setter方法中由用户自行编写
到此这篇关于Java超详细分析@Autowired原理的文章就介绍到这了,更多相关Java @Autowired内容请搜索七叶笔记以前的文章或继续浏览下面的相关文章希望大家以后多多支持七叶笔记!