深入理解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加载的整个流程。

目录
相关文章
|
1天前
|
Java Spring
解决 Spring 中 Prototype Bean 注入后被固定的问题
【6月更文挑战第8天】学习 Spring 框架内不原理的意义就是,当遇到问题时,分析出原因,就可以从多个切入点,利用 Spring 的特性,来解决问题。
13 2
|
6天前
|
Oracle Java 关系型数据库
|
6天前
|
XML Java 数据格式
|
6天前
|
druid Java 关系型数据库
|
6天前
|
Java Spring 容器
|
8天前
|
存储 Java C++
理解SpringIOC和DI第一课(Spring的特点),IOC对应五大注解,ApplicationContext vs BeanFactory
理解SpringIOC和DI第一课(Spring的特点),IOC对应五大注解,ApplicationContext vs BeanFactory
|
9天前
|
存储 前端开发 Java
Spring IoC&DI(3)—DI详解
Spring IoC&DI(3)—DI详解
11 0
|
9天前
|
存储 Java 程序员
Spring IoC&DI(2)—IoC详解
Spring IoC&DI(2)—IoC详解
16 2
|
9天前
|
存储 自动驾驶 Java
Spring IoC&DI(1)—入门
Spring IoC&DI(1)—入门
11 1
|
11天前
|
Java Spring 缓存
Spring Bean循环依赖详解
【6月更文挑战第2天】
21 2