深入理解Spring IOC(六)、 bean的填充以及初始化工作(下)

简介: 深入理解Spring IOC(六)、 bean的填充以及初始化工作(下)

代码块3中3处


到了3.3这里,spring已经知道了bean的哪个属性需要注入,并且注入的值已经拿到,我们来看看这里的代码:


代码块6
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
  // 如果pvs为空过直接返回
  if (pvs == null || pvs.isEmpty()) {
    return;
  }
  MutablePropertyValues mpvs = null;
  List<PropertyValue> original;
  if (System.getSecurityManager() != null) {
    if (bw instanceof BeanWrapperImpl) {
      ((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
    }
  }
  if (pvs instanceof MutablePropertyValues) {
    mpvs = (MutablePropertyValues) pvs;
    // 如果mpvs的属性值已经被转换成为对应的类型,则可以直接去设置
    if (mpvs.isConverted()) {
      try {
        // 这里也是为什么使用BeanWrapper而不是使用beanInstance的原因
        // 因为BeanWrapper实现了PropertyAccessor接口,可以直接给set值
        // 这块有兴趣的可以自行研究一下
        bw.setPropertyValues(mpvs);
        return;
      }catch (BeansException ex) {
        throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Error setting property values", ex);
      }
    }
    original = mpvs.getPropertyValueList();
  }else {
    // 获取原始的属性
    original = Arrays.asList(pvs.getPropertyValues());
  }
  TypeConverter converter = getCustomTypeConverter();
  if (converter == null) {
    converter = bw;
  }
  // 获取解析器
  BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
  // 对原始属性进行深拷贝,避免修改后引起的原始属性值修改
  // deepcopy是后边直接用作给bean填充属性的
  List<PropertyValue> deepCopy = new ArrayList<PropertyValue>(original.size());
  boolean resolveNecessary = false;
  for (PropertyValue pv : original) {
    // 如果某个属性被转换过则直接加入deepCopy
    if (pv.isConverted()) {
      deepCopy.add(pv);
    // 否则的话进行转换
    }else {
      // 拿到原始属性值和属性名称
      String propertyName = pv.getName();
      Object originalValue = pv.getValue();
      // 并进行解析,并进行必要的解析
      Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
      Object convertedValue = resolvedValue;
      // propertyName对应的属性是个可以写的 && 不能是嵌套属性或者下标属性
      boolean convertible = bw.isWritableProperty(propertyName) &&
          !PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
      if (convertible) {
        convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
      }
      // 将转换过的值存起来避免重新转换
      if (resolvedValue == originalValue) {
        if (convertible) {
          pv.setConvertedValue(convertedValue);
        }
        deepCopy.add(pv);
      }else if (convertible && originalValue instanceof TypedStringValue &&
          !((TypedStringValue) originalValue).isDynamic() &&
          !(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
        pv.setConvertedValue(convertedValue);
        deepCopy.add(pv);
      }else {
        resolveNecessary = true;
        deepCopy.add(new PropertyValue(pv, convertedValue));
      }
    }
  }
  // 将converted设置为true
  if (mpvs != null && !resolveNecessary) {
    mpvs.setConverted();
  }
  // 用deepCopy里的值来进行属性填充
  try {
    bw.setPropertyValues(new MutablePropertyValues(deepCopy));
  }catch (BeansException ex) {
    throw new BeanCreationException(
        mbd.getResourceDescription(), beanName, "Error setting property values", ex);
  }
}


这下doCreateBean中对bean的填充也完了,其实对bean的工作都是在BeanPostProcessor中完成的,在populateBean这个方法中只是对BeanPostProcessor的方法进行了调用而已。我们继续看1.4处,这个方法主要是针对bean的初始化的。


代码块1中4处


代码块7
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
    // 调用几个Aware接口
    if (System.getSecurityManager() != null) {
      AccessController.doPrivileged(new PrivilegedAction<Object>() {
        @Override
        public Object run() {
          // 1.调用aware
          invokeAwareMethods(beanName, bean);
          return null;
        }
      }, getAccessControlContext());
    }
    else {
      invokeAwareMethods(beanName, bean);
    }
    // 2.调用所有的BeanPostProcessor的postProcessBeforeInitialization
    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
      wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }
    try {
      // 3.调用InitializingBean的方法和自定义初始化方法
      invokeInitMethods(beanName, wrappedBean, mbd);
    }catch (Throwable ex) {
      throw new BeanCreationException(
          (mbd != null ? mbd.getResourceDescription() : null),
          beanName, "Invocation of init method failed", ex);
    }
    // 4.执行所有BeanPostProcessor的postProcessAfterInitialization方法
    if (mbd == null || !mbd.isSynthetic()) {
      wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }
    return wrappedBean;
  }


第1处主要是调用aware接口,aware接口我也会去写文章专门介绍,我们这会先来看这个方法做了什么:


代码块7中1处


代码块8
private void invokeAwareMethods(final String beanName, final Object bean) {
  // 所谓的xxxAware,就是让这个bean和xxx产生关联
  if (bean instanceof Aware) {
    // 设置名称
    if (bean instanceof BeanNameAware) {
      ((BeanNameAware) bean).setBeanName(beanName);
    }
    // 类加载器
    if (bean instanceof BeanClassLoaderAware) {
      ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
    }
    // 我们有时候使用BeanFactoryAware去拿BeanFactory,就是在这步设置的
    if (bean instanceof BeanFactoryAware) {
      ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
    }
  }
}


代码块7中2处


代码块9
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
      throws BeansException {
  Object result = existingBean;
  // 调用所有的BeanPostProcessor的postProcessBeforeInitialization(前置处理)方法
  // 其中@PostConstruct就是在CommonAnnotationBeanPostProcessor中执行的
  for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
    result = beanProcessor.postProcessBeforeInitialization(result, beanName);
    if (result == null) {
      return result;
    }
  }
  return result;
}


代码块7中3处

这个方法主要是执行初始化方法,主要执行@InitialBean中的初始化方法和自定义的初始化方法:


代码块10
protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
      throws Throwable {
  // 调用InitializingBean的afterPropertiesSet方法,还是特权调用和普通调用
  boolean isInitializingBean = (bean instanceof InitializingBean);
  if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
    if (logger.isDebugEnabled()) {
      logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
    }
    if (System.getSecurityManager() != null) {
      try {
        AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
          @Override
          public Object run() throws Exception {
            // 
            ((InitializingBean) bean).afterPropertiesSet();
            return null;
          }
        }, getAccessControlContext());
      }
      catch (PrivilegedActionException pae) {
        throw pae.getException();
      }
    }
    else {
      ((InitializingBean) bean).afterPropertiesSet();
    }
  }
  if (mbd != null) {
    String initMethodName = mbd.getInitMethodName();
    if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
        !mbd.isExternallyManagedInitMethod(initMethodName)) {
      // 调用自定义的初始化方法,主要是通过反射调用
      invokeCustomInitMethod(beanName, bean, mbd);
    }
  }
}


代码块7中4处


这个方法也是初始化的最后一步


代码块11
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
      throws BeansException {
  // 执行所有BeanPostProcessor的postProcessAfterInitialization(后置处理)方法
  Object result = existingBean;
  // 遍历执行
  for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
    result = beanProcessor.postProcessAfterInitialization(result, beanName);
    if (result == null) {
      return result;
    }
  }
  return result;
}


至此,xml中bean的加载解析我们已经讲完,下一篇,我们将对整个流程做个总结,以及扩充一些面试涉及到的点,以让你更好的理解bean加载的整个流程。

目录
相关文章
|
7天前
|
XML Java 数据格式
【SpringFramework】Spring IoC-基于XML的实现
本文主要讲解SpringFramework中IoC和DI相关概念,及基于XML的实现方式。
96 69
|
5天前
|
Java Spring 容器
【SpringFramework】Spring IoC-基于注解的实现
本文主要记录基于Spring注解实现IoC容器和DI相关知识。
40 21
|
12天前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
10天前
|
存储 Java Spring
【Spring】获取Bean对象需要哪些注解
@Conntroller,@Service,@Repository,@Component,@Configuration,关于Bean对象的五个常用注解
|
10天前
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
|
16天前
|
XML Java 数据格式
Spring容器Bean之XML配置方式
通过对以上内容的掌握,开发人员可以灵活地使用Spring的XML配置方式来管理应用程序的Bean,提高代码的模块化和可维护性。
53 6
|
3月前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
256 2
|
12天前
|
Java 数据库连接 Maven
最新版 | 深入剖析SpringBoot3源码——分析自动装配原理(面试常考)
自动装配是现在面试中常考的一道面试题。本文基于最新的 SpringBoot 3.3.3 版本的源码来分析自动装配的原理,并在文未说明了SpringBoot2和SpringBoot3的自动装配源码中区别,以及面试回答的拿分核心话术。
最新版 | 深入剖析SpringBoot3源码——分析自动装配原理(面试常考)
|
19天前
|
NoSQL Java Redis
Spring Boot 自动配置机制:从原理到自定义
Spring Boot 的自动配置机制通过 `spring.factories` 文件和 `@EnableAutoConfiguration` 注解,根据类路径中的依赖和条件注解自动配置所需的 Bean,大大简化了开发过程。本文深入探讨了自动配置的原理、条件化配置、自定义自动配置以及实际应用案例,帮助开发者更好地理解和利用这一强大特性。
68 14
|
2月前
|
缓存 IDE Java
SpringBoot入门(7)- 配置热部署devtools工具
SpringBoot入门(7)- 配置热部署devtools工具
58 1
SpringBoot入门(7)- 配置热部署devtools工具