好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Spring Bean生命周期之属性赋值阶段详解

前言

上节在谈论Bean的实例化过程时,在说明实例化后阶段时只是粗略地看了一下 populateBean ,并未展开分析。本节接着 populateBean 开始分析对象赋值阶段的事情。

populateBean其实主要做了以下几件事:

Bean实例化后回调,来决定是否进行属性赋值 (上节分析过了) 对属性进行自动装配 InstantiationAwareBeanPostProcessor 属性赋值前回调 属性的真正赋值

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {

         //省略无关代码

         // 1、 Bean实例化后回调,来决定是否进行属性赋值

         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 );

         //2、对属性进行自动装配

         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);

         //3、InstantiationAwareBeanPostProcessor属性赋值前回调

         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 (pvs != null ) {

           //属性的赋值

             applyPropertyValues(beanName, mbd, bw, pvs);

         }

     }

属性自动装配

PropertyValues 对bd中属性的封装,可以理解为bd中属性键值均由其保存,其常用实现类为MutablePropertyValues,在BeanDefinition的概述及使用 有介绍其使用,可点击查看

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

//这里的bd是已经执行过合并BeanDefinition操作了

//如果bd存在属性 则获取

PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null );

//获取bd的自动注入模式

//注入模式有四种:

//1.构造函数注入 2、按照名称注入 3、按照类型注入 4、不注入(默认,依然可能会被注解驱动注入)

int resolvedAutowireMode = mbd.getResolvedAutowireMode();

//如果是按名称注入或类型注入时

if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {

     MutablePropertyValues newPvs = new MutablePropertyValues(pvs);

     //按名称注入

     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;

}

下面我们分别来大致看下 autowireByName 及 autowireByType  熟悉下实现原理

autowireByName

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

protected void autowireByName(

             String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

         //获取属性名称

         String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);

         //遍历属性名称

         for (String propertyName : propertyNames) {

             //如果属性名称已在beanDefinitionMap中,说明其是bd 并已被注册待IoC容器

             if (containsBean(propertyName)) {

                 //根据名称获取其bean对象

                 Object bean = getBean(propertyName);

                 //以键值方法赋值到pvs

                 pvs.add(propertyName, bean);

                 // 这里是维护dependentBeanMap、dependenciesForBeanMap两个集合,

                 // 这里不再展开 在说到LifecycleProcessor时再展开

                 registerDependentBean(propertyName, beanName);

                 //省略日志输出

             }

             else {

                 //省略日志输出

             }

         }

     }

autowireByType

按类型注入稍显复杂些,但流程上与按名称注入类似

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

protected void autowireByType(

             String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

         //类型转换器

         TypeConverter converter = getCustomTypeConverter();

         if (converter == null ) {

             converter = bw;

         }

         Set<String> autowiredBeanNames = new LinkedHashSet<>( 4 );

         //依然是获取属性名称

         String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);

         //遍历属性名称

         for (String propertyName : propertyNames) {

             try {

                 //获取属性描述对象

                 PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);

                 //不对Object类型做注入,因此这里判断条件如下

                 if (Object. class != pd.getPropertyType()) {

                     MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);

                     boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);

                     DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);

                     //解析依赖

                     Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);

                     if (autowiredArgument != null ) {

                     //以键值方法赋值到pvs

                         pvs.add(propertyName, autowiredArgument);

                     }

                     for (String autowiredBeanName : autowiredBeanNames) {

                      // 这里是维护dependentBeanMap、dependenciesForBeanMap两个集合,

                      // 这里不再展开 在说到LifecycleProcessor时再展开

                         registerDependentBean(autowiredBeanName, beanName);

                         //省略日志输出

                     }

                     autowiredBeanNames.clear();

                 }

             }

             catch (BeansException ex) {

                 //省略异常信息

         }

     }

接下来我们进入到 resolveDependency ,大致分析下解析依赖的主要流程

DefaultListableBeanFactory#resolveDependency

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,

             @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

         descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());

     //如果依赖类型是Optional

         if (Optional. class == descriptor.getDependencyType()) {

             return createOptionalDependency(descriptor, requestingBeanName);

         }

   //如果依赖类型是ObjectFactory或ObjectProvider

         else if (ObjectFactory. class == descriptor.getDependencyType() ||

                 ObjectProvider. class == descriptor.getDependencyType()) {

             return new DependencyObjectProvider(descriptor, requestingBeanName);

         }

    //如果依赖类型是Inject

         else if (javaxInjectProviderClass == descriptor.getDependencyType()) {

             return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);

         }

         else {

             Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(

                     descriptor, requestingBeanName);

             if (result == null ) {

         //实际执行解析依赖的逻辑代码 

                 result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);

             }

             return result;

         }

     }

     @Nullable

     public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,

             @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

         InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);

         try {

             Object shortcut = descriptor.resolveShortcut( this );

             if (shortcut != null ) {

                 return shortcut;

             }

             //获取依赖类型

             Class<?> type = descriptor.getDependencyType();

       //获取依赖类型的默认值,如@Value注解 可提供默认值

             Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);

             if (value != null ) {

         //如果默认值是String类型

                 if (value instanceof String) {

           //从配置文件中解析出指定key的数据

                     String strVal = resolveEmbeddedValue((String) value);

                     BeanDefinition bd = (beanName != null && containsBean(beanName) ? getMergedBeanDefinition(beanName) : null );

                     value = evaluateBeanDefinitionString(strVal, bd);

                 }

         //类型转换器 用于转换类型,如配置文件中声明的是字符串类型的数字,而java中使用Integer接收,则类型转换器就派上用场了

                 TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());

                 return (descriptor.getField() != null ?

                         converter.convertIfNecessary(value, type, descriptor.getField()) :

                         converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));

             }

             //解析出类型是Stream、Map、数组、Collection等集合类型的依赖。解析的思路很类似 即去IoC容器中 查找集合类实际泛型对应的Bean

             Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);

             if (multipleBeans != null ) {

                 return multipleBeans;

             }

             //这里主要是查找单实例Bean的,如果某个类型的Bean有多个,这里会被全部查找出来,因此使用Map接收

             Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);

             if (matchingBeans.isEmpty()) {

                 if (isRequired(descriptor)) {

                     raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);

                 }

                 return null ;

             }

             String autowiredBeanName;

             Object instanceCandidate;

       //如果查找出的Bean有多个,

             if (matchingBeans.size() > 1 ) {

         //找出标注了@Primary的那个Bean名称,作为查找出的Bean

                 autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);

                 if (autowiredBeanName == null ) {

                     if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {

             //如果没有@Primary注解标注,那么抛出NoUniqueBeanDefinitionException

                         return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);

                     }

                     else {

                         return null ;

                     }

                 }

                 instanceCandidate = matchingBeans.get(autowiredBeanName);

             }

             else {

         //如果查找出的Bean只有1个 那么说明找到了。

                 Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();

                 autowiredBeanName = entry.getKey();

                 instanceCandidate = entry.getValue();

             }

             if (autowiredBeanNames != null ) {

                 autowiredBeanNames.add(autowiredBeanName);

             }

             if (instanceCandidate instanceof Class) {

                 instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this );

             }

             Object result = instanceCandidate;

             if (result instanceof NullBean) {

                 if (isRequired(descriptor)) {

                     raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);

                 }

                 result = null ;

             }

             if (!ClassUtils.isAssignableValue(type, result)) {

                 throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());

             }

             return result;

         }

         finally {

             ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);

         }

     }

可以看出 resolveDependency 方法还是很强大的,无论是单一类型对象还是集合类型对象,无论是Optional类型还是延迟加载ObjectFactory类型 其均可以解析出来。

属性赋值前回调

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

//boolean值 判断有没有InstantiationAwareBeanPostProcessor存在

  boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();

  // 这是 是否依赖检查的标记 不是我们此次的重点

boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

PropertyDescriptor[] filteredPds = null ;

//IoC容器中如果存在InstantiationAwareBeanPostProcessor

if (hasInstAwareBpps) {

     if (pvs == null ) {

         pvs = mbd.getPropertyValues();

     }

     //遍历BeanPostProcessor,找到InstantiationAwareBeanPostProcessor类型

     for (BeanPostProcessor bp : getBeanPostProcessors()) {

         if (bp instanceof InstantiationAwareBeanPostProcessor) {

             InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;

             //postProcessProperties、postProcessPropertyValues两个方法含义类似。如果postProcessProperties未被重写 则执行postProcessPropertyValues方法

             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;

         }

     }

}

这里针对一个小案例说明下 postProcessPropertyValues 和 postProcessProperties 的使用

需求:将注入的user对象中name属性由wojiushiwo修改为abc

实体对象User

?

1

2

3

4

5

6

7

8

9

10

11

12

@Data

@ToString

public class User {

     private String name;

     private Integer age;

     public User() {

     }

     public User(String name, Integer age) {

         this .name = name;

         this .age = age;

     }

}

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

public class MyInstantiationBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

     @Override

     public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {

         if (ObjectUtils.nullSafeEquals( "user" ,beanName) && User. class .equals(bean.getClass())){

             final MutablePropertyValues propertyValues;

             if (pvs instanceof MutablePropertyValues){

                 propertyValues= (MutablePropertyValues) pvs;

             } else {

                 propertyValues= new MutablePropertyValues();

             }

             if (propertyValues.contains( "name" )){

                 propertyValues.removePropertyValue( "name" );

                 propertyValues.addPropertyValue( "name" , "abcd" );

             }

             return propertyValues;

         }

         return null ;

     }

}

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

public class BeanPostProcessDemo {

     public static void main(String[] args) {

         BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User. class );

         beanDefinitionBuilder.addPropertyValue( "name" , "wojiushiwo" );

         beanDefinitionBuilder.addPropertyValue( "age" , 20 );

         // 获取 AbstractBeanDefinition

         AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();

         // 附加属性(

         beanDefinition.setAttribute( "name" , "我是附加属性" );

         // 当前 BeanDefinition 来自哪里(辅助作用)

         beanDefinition.setSource(BeanPostProcessDemo. class );

         DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

         beanFactory.addBeanPostProcessor( new MyInstantiationBeanPostProcessor());

         // 注册 User 的 BeanDefinition

         beanFactory.registerBeanDefinition( "user" , beanDefinition);

         User user = beanFactory.getBean( "user" , User. class );

         System.out.println(user);

     }

}

输出结果:

User(name=abcd, age=20)

属性的真正赋值

?

1

2

3

4

if (pvs != null ) {

         //将从前面步骤得到的pvs 赋值到beanWrapper中以实现属性赋值,这部分具体源码这里不展开了

         applyPropertyValues(beanName, mbd, bw, pvs);

     }

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注的更多内容!

原文链接:https://blog.csdn.net/zyxwvuuvwxyz/article/details/123271627

查看更多关于Spring Bean生命周期之属性赋值阶段详解的详细内容...

  阅读:15次