• Spring 源码(14)Spring Bean 的创建过程(5)


    到目前为止,我们知道Spring创建Bean对象有5中方法,分别是:

    • 使用FactoryBeangetObject方法创建
    • 使用BeanPostProcessor的子接口InstantiationAwareBeanPostProcessorpostProcessBeforeInstantiation方法创建
    • 设置BeanDefinitionSupplier属性进行创建
    • 设置BeanDefinitionfactory-method进行创建
    • 使用全过程:getBean-->doGetBean-->createBean-->doCreateBean 反射进行创建

    前面4中已经介绍,接下来介绍第5种,我们知道如果使用反射创建,那么必然要知道使用构造函数进行实例化,因为使用构造函数能够将带有参数的设置进去。

    SmartInstantiationAwareBeanPostProcessor 接口

    在前面讲过InstantiationAwareBeanPostProcessor 是用来提前实例化对象的,而SmartInstantiationAwareBeanPostProcessorInstantiationAwareBeanPostProcessor 的子接口,他是用来干啥呢?

    createBeanInstance方法中的源码:

    // 省略代码....
    // 明确构造器从BeanPostProcessor中,对应的是 AutowiredAnnotationBeanPostProcessor
    // 他是 SmartInstantiationAwareBeanPostProcessor 的子类,使用determineCandidateConstructors进行
    // 解析构造函数
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
        mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
      return autowireConstructor(beanName, mbd, ctors, args);
    }
    // 省略代码....
    
    

    点进去:

    protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
      throws BeansException {
    
      if (beanClass != null && hasInstantiationAwareBeanPostProcessors()) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
          if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
            SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
            // 决定候选的构造函数
            Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
            if (ctors != null) {
              return ctors;
            }
          }
        }
      }
      return null;
    }
    

    可以看到这个接口是用来解析BeanClass的构造函数的,SmartInstantiationAwareBeanPostProcessor的实现类AutowiredAnnotationBeanPostProcessor,这个类是用来解析确定合适的构造函数,重点解析了@Autowired注解,并且还解析了@Value注解和@Lookup注解。

    当解析出来构造函数之后,那么就调用autowireConstructor方法进行实例化,解析时会new一个构造器解析器ConstructorResolver ,在解析factoryMehod时也是使用的这个类使用的是instantiateUsingFactoryMethod这个方法,并且解析factoryMethod更加复杂,需要判断是否是静态的工厂创建还是实例工厂创建,而自动装配的构造解析相对来说简单一些,使用autowireConstructor方法进行解析。

    最终解析出构造方法和构造参数之后进行实例化:

    // 使用合适的构造方法和构造参数进行实例化
    bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
    

    实例化:

    private Object instantiate(
      String beanName, RootBeanDefinition mbd, Constructor<?> constructorToUse, Object[] argsToUse) {
    
      try {
        // 获取实例化策略,一般使用 CglibSubClassingInstantiationStrategy
        InstantiationStrategy strategy = this.beanFactory.getInstantiationStrategy();
        if (System.getSecurityManager() != null) {
          return AccessController.doPrivileged((PrivilegedAction<Object>) () ->
                                               strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse),
                                               this.beanFactory.getAccessControlContext());
        }
        else {
          // 开始实例化
          return strategy.instantiate(mbd, beanName, this.beanFactory, constructorToUse, argsToUse);
        }
      }
      catch (Throwable ex) {
        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                        "Bean instantiation via constructor failed", ex);
      }
    }
    
    public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
                              final Constructor<?> ctor, Object... args) {
      if (!bd.hasMethodOverrides()) {
        if (System.getSecurityManager() != null) {
          // use own privileged to change accessibility (when security is on)
          AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            ReflectionUtils.makeAccessible(ctor);
            return null;
          });
        }
        // 实例化类,反射调用
        return BeanUtils.instantiateClass(ctor, args);
      }
      else {
        // 如果方法被覆盖,lookup-method 和 replace-method
        return instantiateWithMethodInjection(bd, beanName, owner, ctor, args);
      }
    }
    

    如果前面的解析都没有到Bean,那么就会使用无参构造函数进行解析:

    // 省略代码....
    // Preferred constructors for default construction?
    // 首选的构造器为默认的创建方式,使用了@Primary注解的为首选的创建对象方式
    ctors = mbd.getPreferredConstructors();
    if (ctors != null) {
      return autowireConstructor(beanName, mbd, ctors, null);
    }
    
    // No special handling: simply use no-arg constructor.
    // 调用无参构造函数实例化对象
    return instantiateBean(beanName, mbd);
    

    实例化Bean

    protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
      try {
        Object beanInstance;
        if (System.getSecurityManager() != null) {
          beanInstance = AccessController.doPrivileged(
            (PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
            getAccessControlContext());
        }
        else {
          // 实例化对象,使用反射进行创建
          beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
        }
        // 创建一个Bean的包装器
        BeanWrapper bw = new BeanWrapperImpl(beanInstance);
        // 初始化Bean的包装器
        initBeanWrapper(bw);
        return bw;
      }
      catch (Throwable ex) {
        throw new BeanCreationException(
          mbd.getResourceDescription(), beanName, "Instantiation of bean failed", ex);
      }
    }
    

    这里可以看到前面使用factoryMethodautowireConstructor 解析构造函数进行实例化还是使用无参构造函数进行实例化都是将Bean进行了包装,那这个包装有啥作用呢?

    BeanWrapper的作用

    我们先来看下前面的方法是怎么创建BeanWrapper的:

    factory-method 解析,ConstructorResolver#instantiateUsingFactoryMethod 方法:

    public BeanWrapper instantiateUsingFactoryMethod(
    			String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
    		// 创建一个Bean的包装器
    		BeanWrapperImpl bw = new BeanWrapperImpl();
    		this.beanFactory.initBeanWrapper(bw);
    		// factoryBean
    		Object factoryBean;
    		// factory 工厂类
    		Class<?> factoryClass;
    		// 标识是否是静态的工厂
    		boolean isStatic;
            // 省略代码....
    }  
    

    SmartInstantiationAwareBeanPostProcessor子类AutowiredAnnotationBeanPostProcessor 解析出构造函数,然后使用ConstructorResolver#autowireConstructor 执行:

    public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
    			@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {
    		// 创建一个包装器
    		BeanWrapperImpl bw = new BeanWrapperImpl();
    		// 初始化包装器
    		this.beanFactory.initBeanWrapper(bw);
    		// 构造函数
    		Constructor<?> constructorToUse = null;
    		// 构造参数
    		ArgumentsHolder argsHolderToUse = null;
    		// 需要使用的构造参数
    		Object[] argsToUse = null;
    		// 明确的构造参数不为空,则赋值给将要执行实例化的构造参数
    		if (explicitArgs != null) {
    			argsToUse = explicitArgs;
    		}
            // 省略代码....
    }
    

    最终都是会进行转换服务ConversionServicePropertyEditorRegistry的注册,一个是用来进行属性类型转换的,一个是用来属性值解析的:

    protected void initBeanWrapper(BeanWrapper bw) {
      // 获取转换服务放到bean的包装器中
      bw.setConversionService(getConversionService());
      // 注册定制的属性编辑器
      registerCustomEditors(bw);
    }
    

    在前面的文章中,介绍了这两个如何使用,而且还自定义了属性编辑器和类型转换,需要的小伙伴可以去看看:

    https://www.cnblogs.com/redwinter/p/16167214.htmlhttps://www.cnblogs.com/redwinter/p/16241328.html

    到这里Bean的实例化就完成了,接着往下看源码:

    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
      throws BeanCreationException {
    
      // Instantiate the bean.
      BeanWrapper instanceWrapper = null;
      // 从缓存中获取FactoryBean的Bean对象
      if (mbd.isSingleton()) {
        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
      }
      if (instanceWrapper == null) {
        // 实例化对象
        instanceWrapper = createBeanInstance(beanName, mbd, args);
      }
      // 从包装器中获取Bean对象
      Object bean = instanceWrapper.getWrappedInstance();
      // 从包装器中获取Bean类型
      Class<?> beanType = instanceWrapper.getWrappedClass();
      if (beanType != NullBean.class) {
        mbd.resolvedTargetType = beanType;
      }
    
      // Allow post-processors to modify the merged bean definition.
      synchronized (mbd.postProcessingLock) {
        if (!mbd.postProcessed) {
          try {
            // 合并Bean
            applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
          }
          catch (Throwable ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                            "Post-processing of merged bean definition failed", ex);
          }
          mbd.postProcessed = true;
        }
      }
    }
    

    点进去:

    protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
      for (BeanPostProcessor bp : getBeanPostProcessors()) {
        if (bp instanceof MergedBeanDefinitionPostProcessor) {
          MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
          // 执行合并BeanDefinition
          bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
        }
      }
    }
    

    可以看到这里出现了一个接口MergedBeanDefinitionPostProcessor,这个接口也是BeanPostProcessor的子接口,那他到底是干啥用的呢?

    MergedBeanDefinitionPostProcessor 接口

    点击发现这个接口的实现类全是跟注解相关的,包括AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessorInitDestroyAnnotationBeanPostProcessor 实现类,CommonAnnotationBeanPostProcessor在构造函数中设置了两个注解:@PostConstruct@PreDestroy ,一个是在初始化完之后调用,一个是容器销毁时调用。CommonAnnotationBeanPostProcessor这个类的父类为InitDestroyAnnotationBeanPostProcessor`,用于处理初始化和销毁方法的。

    CommonAnnotationBeanPostProcessor 的构造器:

    public CommonAnnotationBeanPostProcessor() {
    		setOrder(Ordered.LOWEST_PRECEDENCE - 3);
    		// 初始化PostConstruct PreDestroy注解
    		// 调用父类的方法进行设置
    		setInitAnnotationType(PostConstruct.class);
    		setDestroyAnnotationType(PreDestroy.class);
    		ignoreResourceType("javax.xml.ws.WebServiceContext");
    	}
    

    CommonAnnotationBeanPostProcessor 合并方法:

    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    		// 调用父类
    		super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
    		InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
    		metadata.checkConfigMembers(beanDefinition);
    	}
    

    点击postProcessMergedBeanDefinition方法发现调用了父类的这个方法,然后执行了一个叫查找生命周期元数据的方法findLifecycleMetadata

    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    		LifecycleMetadata metadata = findLifecycleMetadata(beanType);
    		metadata.checkConfigMembers(beanDefinition);
    	}
    

    查找生命周期元数据:

    private LifecycleMetadata findLifecycleMetadata(Class<?> clazz) {
    		if (this.lifecycleMetadataCache == null) {
    			// Happens after deserialization, during destruction...
    			return buildLifecycleMetadata(clazz);
    		}
    		// Quick check on the concurrent map first, with minimal locking.
    		// 查询缓存
    		LifecycleMetadata metadata = this.lifecycleMetadataCache.get(clazz);
    		if (metadata == null) {
    			synchronized (this.lifecycleMetadataCache) {
    				// 再次查询
    				metadata = this.lifecycleMetadataCache.get(clazz);
    				if (metadata == null) {
    					// 没有查询到就去构建生命周期的元数据
    					metadata = buildLifecycleMetadata(clazz);
    					this.lifecycleMetadataCache.put(clazz, metadata);
    				}
    				return metadata;
    			}
    		}
    		return metadata;
    	}
    

    构建生命周期元数据:

    private LifecycleMetadata buildLifecycleMetadata(final Class<?> clazz) {
      // 这里的initAnnotationType 就是子类set进去的@PostConstruct
      // destroyAnnotationType 就是子类set进去的@PreDestroy
      if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {
        return this.emptyLifecycleMetadata;
      }
      // 存放初始化方法
      List<LifecycleElement> initMethods = new ArrayList<>();
      // 存放销毁方法
      List<LifecycleElement> destroyMethods = new ArrayList<>();
      Class<?> targetClass = clazz;
    
      do {
        final List<LifecycleElement> currInitMethods = new ArrayList<>();
        final List<LifecycleElement> currDestroyMethods = new ArrayList<>();
    
        ReflectionUtils.doWithLocalMethods(targetClass, method -> {
          // 如果找到方法上有@PostConstruct注解,这加入到当前初始化方法集合中
          if (this.initAnnotationType != null && method.isAnnotationPresent(this.initAnnotationType)) {
            // 创建一个生命周期元素
            //LifecycleElement element = new LifecycleElement(method);
            currInitMethods.add(new LifecycleElement(method));
          }
          // 如果找到方法上标有@PreDestroy 注解,就加入到当前销毁方法集合中
          if (this.destroyAnnotationType != null && method.isAnnotationPresent(this.destroyAnnotationType)) {
            currDestroyMethods.add(new LifecycleElement(method));
          }
        });
        // 赋值到初始化方法集合和销毁方法集合中
        initMethods.addAll(0, currInitMethods);
        destroyMethods.addAll(currDestroyMethods);
        targetClass = targetClass.getSuperclass();
      }
      // 遍历查找
      while (targetClass != null && targetClass != Object.class);
      // 如果没有解析到,那么返回一个空的生命周期元数据,否则创建一个生命周期元素并放入初始化方法和销毁方法的集合
      return (initMethods.isEmpty() && destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :
              new LifecycleMetadata(clazz, initMethods, destroyMethods));
    }
    

    最终发现实际上就是在解析我们的Bean的方法上是否标记了@PostConstruct注解和@PreDestroy方法,如果有就加入到生命周期元数据中,并且将解析到的方法放入到BeanDefinitionexternallyManagedInitMethodsexternallyManagedDestroyMethods集合中。

    Bean初始化和销毁方法解析和执行流程如下:

    其实InitDestoryAnnotationBeanPostProcessor 主要是对Bean的做了自定义初始化和销毁方法的解析,以及在后期调用BPP时执行。

    自动装配注解的解析

    Spring中自动装配的注解一般来说比较常用的有两个,一个@AutowiredSpring提供的,还有个是@ResourceJava的注解,这两个注解都能够完成自动装配,不过在实现时@Autowired注解是由AutowiredAnnotationBeanPostProcessor解析的和执行,而@Resource注解是由CommonAnnotationBeanPostProcessor解析和执行的。

    除此之外,AutowiredAnnotationBeanPostProcessor还解析了@Value注解,CommonAnnotationBeanPostProcessor还解析了@EJB@WebServiceRef 不过这个不常用。这些注解的解析跟解析@PostConstruct@PreDestroy一样,这里就不做分析了,不同的是这几个注解可以标在字段和方法上,解析是需要对字段和方法都要解析,其他实现基本原理一致。

    Spring Bean的实例化基本就解析完了,接下来开始解析循环依赖和Bean的属性填充部分。

  • 相关阅读:
    吊死人小游戏 2.0版本
    分类预测 | MATLAB实现WOA-CNN-BiGRU鲸鱼算法优化卷积双向门控循环单元数据分类预测
    软考之软件设计师考试总结(内附资料)
    盘点|国内5款主流低代码开发平台介绍
    git如何拉去某个tag的代码
    【深度学习理论】(7) 长短时记忆网络 LSTM
    Java 7 - Java 21 新特性
    P2P实现远程控制
    threejs
    微服务【同步和异步通讯详解】第6章
  • 原文地址:https://www.cnblogs.com/redwinter/p/16268667.html