springboot@autowired注解注⼊为null_Spring注⼊对象处理过
依赖关系的处理
  上⼀篇⽂章中,通过 createBeanInstance() ⽅法,最终得到了 BeanWrapper 对象。再得到这个对象之后,在Spring中,对于依赖 关系的处理,是通过 BeanWrapper 来完成的。
1.⾃动装配与@Autowired
  这⾥⾸先做⼀个区分,因为在之前的很长⼀段时间内,我都错误的以为 @Autowired 就是⾃动装配。这也就引发了我⼀直错误的任务Spring的⾃动 装配⾸先是 byType 然后是 byName 的。通过这段时间对于源码的阅读,我才意识到这个错误。
  当涉及到⾃动装配Bean的依赖关系时,Spring提供了4种⾃动装配策略。
public interface AutowireCapableBeanFactory{
//⽆需⾃动装配
int AUTOWIRE_NO = 0;
//按名称⾃动装配bean属性
int AUTOWIRE_BY_NAME = 1;
//按类型⾃动装配bean属性
int AUTOWIRE_BY_TYPE = 2;
//按构造器⾃动装配
int AUTOWIRE_CONSTRUCTOR = 3;
//过时⽅法,Spring3.0之后不再⽀持
@Deprecated
int AUTOWIRE_AUTODETECT = 4;
...
}
1.1 ⾃动装配
  在 xml 中定义 Bean的时候,可以通过如下的⽅式指定⾃动装配的类型。
<bean id="demoServiceOne" class="DemoServiceOne" autowire="byName"/>
<bean id="userService" class="UserService" autowire="byType"/>
<bean id="user" class="User" autowire="constructor">bean>
如果使⽤了根据类型来⾃动装配,那么在IOC容器中只能有⼀个这样的类型,否则就会报错!
1.2 使⽤注解来实现⾃动装配
  @Autowired 注解,它可以对类成员变量、⽅法及构造函数进⾏标注,完成⾃动装配的⼯作。Spring是通过 @Autowired 来实现⾃动装配的。当然,Spring还⽀持其他的⽅式来实现⾃动装配,如:「JSR-330的@Inject注解」、「JSR-250的@Resource注解」。
  通过注解的⽅式来⾃动装配 Bean 的属性,它允许更细粒度的⾃动装配,我们可以选择性的标注某⼀
个属性来对其应⽤⾃动装配。
2.依赖注⼊
  在这篇⽂章中,我将详细的分析,在⼀个对象中通过 @Autowired注⼊或 @Resource 注⼊属性的处理过程。这⾥我还是采取使⽤情形,然后画出简要 流程图,最后再是源码分析的⽅式来介绍本⽂所要涉及的知识点。
2.1 ⽇常开发中注⼊对象的⽅式
「情形⼀」:通过 @Autowired 注解对象的⽅式
@Service
public class DemoServiceTwo {
@Autowired
DemoServiceThree demoServiceThree;
}
「情形⼆」:通过 @Autowired 注解构造器的⽅式
@Service
public class DemoServiceTwo {
DemoServiceOne demoServiceOne;
@Autowired
public DemoServiceTwo(DemoServiceOne demoServiceOne){
this.demoServiceOne = demoServiceOne;
}
}
「情形三」:通过 @Resource 注解对象的⽅式
@Service
public class DemoServiceTwo {
@Resource
DemoServiceOne demoServiceOne;
}
「情形四」:通过 @Autowired 注解⽅法的⽅式
@Service
public class DemoServiceTwo {
DemoServiceOne demoServiceOne;
@Autowired
public void prepare(DemoServiceOne demoServiceOne){
this.demoServiceOne = demoServiceOne;
}
}
  上述的四种⽅式是我们在⽇常开发中经常⽤到的注⼊对象的⽅式。这四种⽅式,在 Spring 对应不同的处理逻辑。
2.2 对象之间依赖关系处理流程
对象之间依赖关系处理流程
1. 上图中描述了前⾯ 「
2.1」 中所介绍的四种情形的处理,其中蓝⾊线条所表⽰的是 @Resource注解的处理过程。
2. 红⾊线条表⽰ @Autowired注解的处理过程,与之对应的有拆分成三种⼦情况
AutowiredFieldElement 表⽰注解属性的情况
AutowiredMethodElement 表⽰注解⽅法的情况
绿颜⾊的线条表⽰注解在构造⽅法上的情况
  通过上述流程图,我从中到了以下⼏点。通过以下⼏点我们也可以区分 @Resource 和 @Autowired。
1. 两种注解的处理⽅式都是通过后置处理器来完成处理的,getBeanPostProcessors() 在我们不做任何扩展的情况下,Spring 中只有五
个。如有忘记请查看:「容器初始化先发五虎」;
2. 对于 @Resource 的处理是通过 CommonAnnotationBeanPostProcessor 来完成的。
3. 对于 @Autowired 的处理是通过 AutowiredAnnotationBeanPostProcessor来处理的。
4. 对于 @Autowired 注解构造器的⽅式,获取到被注解元素为 null 则直接返回。完成 populateBean() 的过程。
5. 对于剩下的情形,处理思路⼀致,都是先获取到被注⼊的对象,然后将维护对象属性之间的关系。
6. 重点突出⼀下 getBean() 这⾥还是我们熟悉的 getBean()...
7. field.set() 维护对象之间的依赖关系。
3.源码分析
  源码分析⾸当其冲的就是⽅法⼊⼝,在对象的包装 BeanWrapper 创建完成之后,populateBean()来处理对象之间的依赖关系:
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {
throw new BeanCreationException(
}
else {
// Skip property population phase for null instance.
// 没有任何属性需要填充
return;
}
}
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
resource和autowired注解的区别/**
* InstantiationAwareBeanPostProcessor 的 postProcessAfterInstantiation() ⽅法的应⽤
* 可以控制程序是否进⾏属性填充
*/
if (!ibp.WrappedInstance(), beanName)) {
return;
}
}
}
}
/**
* 取得BeanDefinition 中设置的 Property值,
* 这些property来⾃对BeanDefinition的解析,
* 具体的过程可以参看对 BeanDefinition的分析
* 这⾥是Spring 内部设置的属性值,⼀般不会设置
*/
PropertyValues pvs = (mbd.hasPropertyValues() ? PropertyValues() : null);
/**
* 处理⾃动装配,xml的⽅式可能会有配置⾃动装配类型的情况
* 处理⾃动装配,xml的⽅式可能会有配置⾃动装配类型的情况
* 或者通过 setAutowireMode() 的⽅式设置⾃动装配的模式
*/
int resolvedAutowireMode = ResolvedAutowireMode();
// Spring 默认既不是 byType 也不是 byName, 默认是null
// 这⾥之所以做这个判断是因为某种特殊的场景下,会修改到⾃动注⼊的模型,所以需要做判断
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
/**
* byName 处理
* 通过反射从当前Bean中得到需要注⼊的属性名,
* 然后使⽤这个属性名向容器申请与之同名的Bean,
* 这样实际⼜触发了另⼀个Bean⽣成和依赖注⼊的过程
*/
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// byType 处理
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 后置处理器已经初始化
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 需要检查依赖
boolean needsDepCheck = (DependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);
PropertyDescriptor[] filteredPds = null;
if (hasInstAwareBpps) {
if (pvs == null) {
// 与构造⽅法的处理⼀样,对象有但对象⾥⾯的属性没有
pvs = PropertyValues();
}
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);
}
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。