• Spring 源码(17)Spring Bean的创建过程(8)Bean的初始化


    知识回顾

    Bean的创建过程会经历getBeandoGetBeancreateBeandoCreateBean,然后Bean的创建又会经历实例化,属性填充,初始化。

    在实例化createInstance时大致可以分为三种方式进行实例化:

    • 使用Supplier 进行实例化,通过BeanFactoryPostProcessorBeanDefinition进行修改,增加一个Supplier属性,放置一个lambda表达式用于创建对象
    • 使用factory-method进行实例化
      • 使用实例工厂实例化
      • 使用静态工厂实例化
    • 使用构造器反射进行实例化
      • 使用SmartInstantiationAwareBeanPostProcessor解析构造器,然后反射实例化
      • 使用无参构造器进行实例化

    在属性填充populateBean时大致可以分为4个步骤:

    • 调用InstantiationAwareBeanPostProcessor接口的after方法修改Bean的信息
    • 自动装配,将解析的属性和属性值放入到pvs变量中
      • autowireByType自动装配
      • autowireByName自动装配
    • 执行通过CommonAnnotationBeanPostProcessorAtowiredAnnotationBeanPostProcessor解析的注解,然后注入到字段上
    • 对属性的值进行解析,解析pvs, 会涉及到参数转换,spel表达式解析,引用类型,String类型,List类型,Map类型,Set类型,Properties类型的解析,属性编辑器的解析等。

    接下来解读初始化阶段

    bean的初始化

    bean的初始化initializeBean方法,直接上源码:

    protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
      if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
          invokeAwareMethods(beanName, bean);
          return null;
        }, getAccessControlContext());
      }
      else {
        // 执行Aware 方法
        invokeAwareMethods(beanName, bean);
      }
    
      Object wrappedBean = bean;
      if (mbd == null || !mbd.isSynthetic()) {
        // 执行 BeanPostProcessor before 接口
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
      }
    
      try {
        // 执行 init-method 方法
        invokeInitMethods(beanName, wrappedBean, mbd);
      }
      catch (Throwable ex) {
        throw new BeanCreationException(
          (mbd != null ? mbd.getResourceDescription() : null),
          beanName, "Invocation of init method failed", ex);
      }
      if (mbd == null || !mbd.isSynthetic()) {
        // 执行BeanPostProcessor after 方法
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
      }
    
      return wrappedBean;
    }
    

    源码逻辑也很简单,大概就分成了4步:

    • 执行Aware接口的方法invokeAwareMethods
    • 执行BeanPostProcessor#postProcessBeforeInitialization
    • 执行初始化方法
    • 执行BeanPostProcessor#postProcessAfterInitialization

    执行Aware接口的方法

    点进去:

    private void invokeAwareMethods(String beanName, Object bean) {
      if (bean instanceof Aware) {
        // 执行BeanNameAware
        if (bean instanceof BeanNameAware) {
          ((BeanNameAware) bean).setBeanName(beanName);
        }
        // 执行BeanClassLoaderAware
        if (bean instanceof BeanClassLoaderAware) {
          ClassLoader bcl = getBeanClassLoader();
          if (bcl != null) {
            ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
          }
        }
        // 执行BeanFactoryAware
        if (bean instanceof BeanFactoryAware) {
          ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
        }
      }
    }
    

    这里只执行了3个接口的方法,BeanNameAwareBeanClassLoaderAwreBeanFactoryAware,在Spring容器中不止这些Aware接口,这里为什么只执行了三个Aware接口?

    Spring容器BeanFactory构造时,对这三个接口进行了忽略:

    public AbstractAutowireCapableBeanFactory() {
      super();
      ignoreDependencyInterface(BeanNameAware.class);
      ignoreDependencyInterface(BeanFactoryAware.class);
      ignoreDependencyInterface(BeanClassLoaderAware.class);
    }
    

    所以这里只执行了这三个Aware接口,这里忽略,实际上就是不然这些属性通过自动装配设置属性值,而是通过Spring自己的回调进行设置值。

    另外我们在开始的准备BeanFactory的时候又进行了忽略Aware接口:

    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
    
    

    这6个接口在哪里执行的呢?在BeanFactory准备阶段注册了一个BeanPostProcessor的实现叫ApplicationContextAwareProcessor类,这个类的before方法中就进行了调用:

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
      if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
            bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
            bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
        return bean;
      }
      AccessControlContext acc = null;
      if (System.getSecurityManager() != null) {
        acc = this.applicationContext.getBeanFactory().getAccessControlContext();
      }
      if (acc != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
          invokeAwareInterfaces(bean);
          return null;
        }, acc);
      }
      else {
        // 执行Aware接口
        invokeAwareInterfaces(bean);
      }
    
      return bean;
    }
    
    
    private void invokeAwareInterfaces(Object bean) {
      if (bean instanceof EnvironmentAware) {
        ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
      }
      if (bean instanceof EmbeddedValueResolverAware) {
        ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
      }
      if (bean instanceof ResourceLoaderAware) {
        ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
      }
      if (bean instanceof ApplicationEventPublisherAware) {
        ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
      }
      if (bean instanceof MessageSourceAware) {
        ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
      }
      if (bean instanceof ApplicationContextAware) {
        ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
      }
    }
    

    为什么要分开处理呢?

    个人认为主要是做了个区分而已,前面三个接口输入BeanFactory范畴,而这6个接口属于ApplicationContext范畴,只是进行了归类处理而已。

    执行BPP的Before方法

    代码比较简单,就是循环的执行了BPPbefore接口,这里在执行的时候,实现上也执行了在Bean进行merge的时候解析的@PostConstruct注解。

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
      LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
      try {
        // 执行初始化方法
        metadata.invokeInitMethods(bean, beanName);
      }
      catch (InvocationTargetException ex) {
        throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
      }
      catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
      }
      return bean;
    }
    

    这个方法的实现类为InitDestroyAnnotationBeanPostProcessor

    执行初始化方法

    执行初始化方法的时候,会分为两步,一个是执行InitializingBeanafterPropertiesSet方法,另一个是执行自定义的init-method方法

    protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
      throws Throwable {
      // 判断当前Bean是否是实现了InitializingBean
      boolean isInitializingBean = (bean instanceof InitializingBean);
      if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
        if (logger.isTraceEnabled()) {
          logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
        }
        if (System.getSecurityManager() != null) {
          try {
            AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
              ((InitializingBean) bean).afterPropertiesSet();
              return null;
            }, getAccessControlContext());
          }
          catch (PrivilegedActionException pae) {
            throw pae.getException();
          }
        }
        else {
          // 执行
          ((InitializingBean) bean).afterPropertiesSet();
        }
      }
    
      if (mbd != null && bean.getClass() != NullBean.class) {
        String initMethodName = mbd.getInitMethodName();
        if (StringUtils.hasLength(initMethodName) &&
            !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
            !mbd.isExternallyManagedInitMethod(initMethodName)) {
          // 执行自定义的初始化方法
          invokeCustomInitMethod(beanName, bean, mbd);
        }
      }
    }
    

    执行BPP的after接口

    BPP的after主要是用来实现AOP的,所以这里简单介绍下,循环执行after方法的调用。

    源码:

    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
      throws BeansException {
    
      Object result = existingBean;
      for (BeanPostProcessor processor : getBeanPostProcessors()) {
        Object current = processor.postProcessAfterInitialization(result, beanName);
        if (current == null) {
          return result;
        }
        result = current;
      }
      return result;
    }
    

    源码比较简单,就循环执行了方法的调用。

    初始化就解读完了,SpringBean的创建也基本讲完,最终创建出来的Bean对象就会放入到一级缓存singletonObjects中。

  • 相关阅读:
    Hadoop大数据通用处理平台
    [附源码]java毕业设计医院疫情疾控管理系统
    【torch高级】一种新型的概率学语言pyro(01/2)
    文件的打开方式
    人工智能的头号威胁:投毒攻击
    大数据架构:字节跳动开源Cloud Shuffle Service简介
    宝宝照片保存大法!一键制作照片书
    parquet-go的CSVWriter
    前端需要去了解的nodejs知识(fs文件处理)
    Leetcode.19 删除链表的倒数第 N 个结点
  • 原文地址:https://www.cnblogs.com/redwinter/p/16296394.html