• Spring-FactoryBean的源码——简略解析(下)


    其实就是调用了FactoryBean的getObject()返回该bean的。

    通过上面Spring-FactoryBean的源码——简略解析(上)_快撑死的鱼的博客-CSDN博客的分析,WebServiceFactoryBean是一个FactoryBean,
    getBean("&webServiceFactoryBean"),此时spring中会创建一个WebServiceFactoryBean实例,而且返回也是WebServiceFactoryBean实例本身。因此spring容器还利用不到WebServiceFactoryBean的getObject()来返回WebService相关实例。

    那么spring是在什么时候去调用getBean("webServiceFactoryBean"),然后利用WebServiceFactoryBean的getObject()来返回WebServiceWrapper的呢?

    我们仅仅知道的是TestController依赖了WebService,根据前面提到spring托管bean的流程,TestController在依赖注入的时候,一定会找到WebServiceWrapper!!!下面我们根据这个思路去debug分析下源码:

    下面看下TestController的依赖注入阶段:

    1. protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
    2. throws BeanCreat BeanWrapper instanceWrapper = null;
    3. // Initialize the bean instance.
    4. Object exposedObject = bean;
    5. try {
    6. populateBean(beanName, mbd, instanceWrapper);
    7. exposedObject = initializeBean(beanName, exposedObject, mbd);
    8. }
    9. }

    一个bean依赖注入的入口方法就是populateBean():

    1. protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    2. for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
    3. PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
    4. }
    5. }

    InstantiationAwareBeanPostProcessor 是一个bean的实例化处理接口,
    postProcessProperties()主要目的是对实例的属性进行处理。
    其中有一个实现类:AutowiredAnnotationBeanPostProcessor就是用来实现依赖注入的。大概看下该类上的注释和构造器:

    1. /**
    2. 自动连接注释字段、setter方法和任意配置方法的BeanPostProcessor实现。这些要注入的成员是通过注释检测的:默认情况下,是Spring的@Autowired@Value注释。
    3. 还支持JSR-330的@Inject注释(如果可用的话),作为Spring自己的@Autowired的直接替代。
    4. */
    5. public AutowiredAnnotationBeanPostProcessor() {
    6. this.autowiredAnnotationTypes.add(Autowired.class);
    7. this.autowiredAnnotationTypes.add(Value.class);
    8. try {
    9. this.autowiredAnnotationTypes.add((Classextends Annotation>)
    10. ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
    11. logger.trace("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
    12. }
    13. catch (ClassNotFoundException ex) {
    14. // JSR-330 API not available - simply skip.
    15. }
    16. }

    其实就是我们项目中使用的@Autowired,@Value等注入的实现方式。autowiredAnnotationTypes指定了支持哪些注解。

    下面看下AutowiredAnnotationBeanPostProcessor的postProcessProperties():

    1. public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    2. // 找到需要注入的字段
    3. InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    4. try {
    5. // 对每个字段进行注入
    6. metadata.inject(bean, beanName, pvs);
    7. }
    8. catch (BeanCreationException ex) {
    9. throw ex;
    10. }
    11. catch (Throwable ex) {
    12. throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
    13. }
    14. return pvs;
    15. }
    16. public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    17. Collection checkedElements = this.checkedElements;
    18. Collection elementsToIterate =
    19. (checkedElements != null ? checkedElements : this.injectedElements);
    20. if (!elementsToIterate.isEmpty()) {
    21. for (InjectedElement element : elementsToIterate) {
    22. // 对每个依赖字段进行注入
    23. element.inject(target, beanName, pvs);
    24. }
    25. }
    26. }

    对于TestController来说,只有一个WebService字段需要注入,因此会只有一个InjectedElement要进行inject。InjectedElement有两个实现类AutowiredFieldElement和AutowiredMethodElement。由于我们这里是字段注入,所以看看AutowiredFieldElement的inject();

    1. protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
    2. // 当前要注入的字段是什么
    3. Field field = (Field) this.member;
    4. // 给该字段赋值的值到底是什么?
    5. Object value;
    6. if (this.cached) {
    7. try {
    8. value = resolvedCachedArgument(beanName, this.cachedFieldValue);
    9. }
    10. catch (NoSuchBeanDefinitionException ex) {
    11. // Unexpected removal of target bean for cached argument -> re-resolve
    12. value = resolveFieldValue(field, bean, beanName);
    13. }
    14. }
    15. else {
    16. // 根据该字段信息,解析出value
    17. value = resolveFieldValue(field, bean, beanName);
    18. }
    19. if (value != null) {
    20. // 如果解析出来的值不为空,那么就进行赋值
    21. ReflectionUtils.makeAccessible(field);
    22. field.set(bean, value);
    23. }
    24. }

    doResolveDependency()方法中,有个关键点,那就java的Field提供了当前Field的java类型是什么。spring利用了这一点,然后根据类型去找到候选者!!!
    此时type=WebService.class

    一路debug,在findAutowireCandidates()方法中,发现candidateNames中出现了,webServiceFactoryBean,也就是说spring把webServiceFactoryBean当作了一个WebService.其实大概测试也知道是因为WebServiceFactoryBean的getObjectType()返回了WebService.class和要依赖注入的字段相匹配。

    因此关键的代码是:

    1. public static String[] beanNamesForTypeIncludingAncestors(
    2. ListableBeanFactory lbf, Class type, boolean includeNonSingletons, boolean allowEagerInit) {
    3. // 根据WebService.class去找到候选者的bean
    4. String[] result = lbf.getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
    5. }
    6. @Override
    7. public String[] getBeanNamesForType(@Nullable Class type, boolean includeNonSingletons, boolean allowEagerInit) {
    8. String[] resolvedBeanNames = cache.get(type);
    9. if (resolvedBeanNames != null) {
    10. return resolvedBeanNames;
    11. }
    12. resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);
    13. return resolvedBeanNames;
    14. }
    15. private String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {
    16. List result = new ArrayList<>();
    17. // Check all bean definitions.
    18. for (String beanName : this.beanDefinitionNames) {
    19. boolean isFactoryBean = isFactoryBean(beanName, mbd);
    20. BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();
    21. boolean matchFound = false;
    22. boolean allowFactoryBeanInit = (allowEagerInit || containsSingleton(beanName));
    23. boolean isNonLazyDecorated = (dbd != null && !mbd.isLazyInit());
    24. if (!isFactoryBean) {
    25. if (includeNonSingletons || isSingleton(beanName, mbd, dbd)) {
    26. matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
    27. }
    28. }
    29. else {
    30. if (includeNonSingletons || isNonLazyDecorated ||
    31. (allowFactoryBeanInit && isSingleton(beanName, mbd, dbd))) {
    32. matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
    33. }
    34. if (!matchFound) {
    35. // In case of FactoryBean, try to match FactoryBean instance itself next.
    36. beanName = FACTORY_BEAN_PREFIX + beanName;
    37. if (includeNonSingletons || isSingleton(beanName, mbd, dbd)) {
    38. matchFound = isTypeMatch(beanName, type, allowFactoryBeanInit);
    39. }
    40. }
    41. }
    42. if (matchFound) {
    43. result.add(beanName);
    44. }
    45. }
    46. }
    47. protected boolean isTypeMatch(String name, ResolvableType typeToMatch, boolean allowFactoryBeanInit)
    48. throws NoSuchBeanDefinitionException {
    49. if (beanInstance instanceof FactoryBean) {
    50. if (!isFactoryDereference) {
    51. Class type = getTypeForFactoryBean((FactoryBean) beanInstance);
    52. return (type != null && typeToMatch.isAssignableFrom(type));
    53. }
    54. else {
    55. return typeToMatch.isInstance(beanInstance);
    56. }
    57. }
    58. }
    59. protected Class getTypeForFactoryBean(FactoryBean factoryBean) {
    60. try {
    61. if (System.getSecurityManager() != null) {
    62. return AccessController.doPrivileged(
    63. (PrivilegedAction>) factoryBean::getObjectType, getAccessControlContext());
    64. }
    65. else {
    66. return factoryBean.getObjectType();
    67. }
    68. }
    69. catch (Throwable ex) {
    70. // Thrown from the FactoryBean's getObjectType implementation.
    71. logger.info("FactoryBean threw exception from getObjectType, despite the contract saying " +
    72. "that it should return null if the type of its object cannot be determined yet", ex);
    73. return null;
    74. }
    75. }

    在匹配的过程中,如果一个bean是FactoryBean,那么就去检查它的getObjectType()返回的类型是否匹配。对于TestController来说,它的成员字段webService是WebService类型,于是spring会去容器中找,恰好WebServiceFactoryBean的getObjectType()返回就是WebService类型,于是匹配。

    在上面doResolveDependency()中的 findAutowireCandidates()返回了一个WebServiceFactoryBean作为匹配的bean,但是还并没有返回需要注入的value,下面接着看doResolveDependency()

    1. public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
    2. @Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
    3. String autowiredBeanName;
    4. Object instanceCandidate;
    5. String autowiredBeanName;
    6. Object instanceCandidate;
    7. if (matchingBeans.size() > 1) {
    8. autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
    9. if (autowiredBeanName == null) {
    10. if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
    11. return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
    12. }
    13. else {
    14. // In case of an optional Collection/Map, silently ignore a non-unique case:
    15. // possibly it was meant to be an empty collection of multiple regular beans
    16. // (before 4.3 in particular when we didn't even look for collection beans).
    17. return null;
    18. }
    19. }
    20. instanceCandidate = matchingBeans.get(autowiredBeanName);
    21. }
    22. else {
    23. // We have exactly one match.
    24. Map.Entry entry = matchingBeans.entrySet().iterator().next();
    25. autowiredBeanName = entry.getKey();
    26. instanceCandidate = entry.getValue();
    27. }
    28. if (autowiredBeanNames != null) {
    29. autowiredBeanNames.add(autowiredBeanName);
    30. }
    31. if (instanceCandidate instanceof Class) {
    32. instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
    33. }
    34. Object result = instanceCandidate;
    35. return result;
    36. }

    matchingBeans 目前的只包含一个key-value,其中key是webServiceFactoryBean,value则是WebServiceFactoryBean.class。因此真正的value是来自于上面的
    descriptor.resolveCandidate()方法:

    1. public Object resolveCandidate(String beanName, Class requiredType, BeanFactory beanFactory)
    2. throws BeansException {
    3. return beanFactory.getBean(beanName);
    4. }

    这里注意到到,传入的beanName是webServiceFactoryBean!!!这一下子联想到前面说的,spring对于获取FactoryBean本身必须要对beanName加一个特殊的前缀。否则。。。否则就不是返回它自己啦,不用跟踪源码,我们也能够大概猜得到,对于FactoryBean如果beanName不加特殊前缀返回的bean,是调用FactoryBean的getObject()方法返回的!!!结合前面的源码,确实如此。到此FactoryBean的实现原理分析结束。

  • 相关阅读:
    ZYNQ--MIG核配置
    R语言时间序列数据算术运算:使用diff函数计算时间序列数据的逐次差分、使用除法将两个长度不等时间序列数据进行相除、使用固定值乘以指定的时间序列
    Linux常用工具集
    团子杂记:整合后的SAP企业项目管理解决方案-EPPM概览
    数据结构与算法-第六章 图的最小生成树
    合并两个有序链表(每日一题)
    【重识云原生】第六章容器6.1.9节——Docker镜像技术剖析
    Python&SQL应用随笔4——PySpark创建SQL临时表
    Python操作MongoDB数据库
    Python 笔记07(Mysql数据库基本操作)
  • 原文地址:https://blog.csdn.net/qq_38334677/article/details/127838972