【小家Spring】AbstractBeanFactory#getBean()、doGetBean完成Bean的初始化、实例化,以及BeanPostProcessor后置处理器源码级详细分析(中)

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 【小家Spring】AbstractBeanFactory#getBean()、doGetBean完成Bean的初始化、实例化,以及BeanPostProcessor后置处理器源码级详细分析(中)

resolveBeforeInstantiation详解:


  @Nullable
  protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    // beforeInstantiationResolved 这个属性如果是false,表示不需要被前置处理了
    // 然后,唯一能改变它的值的地方,是下面这仅仅一行代码而已,它的访问权限为package
    if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
      // Make sure bean class is actually resolved at this point.
      // 这里hasInstantiationAwareBeanPostProcessors()方法就是看属性hasInstantiationAwareBeanPostProcessors的值。就是标记容器里是否有InstantiationAwareBeanPostProcessor的实现
      // 显然,在执行addBeanPostProcessor,发现这个Bean是这个子类型的时候,就会设为true了。同理的还有hasDestructionAwareBeanPostProcessors这个属性,表示销毁的处理器
      if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        // 拿到最终的目标类型(放置被别的包装过)显然此处是;com.fsx.service.HelloServiceImpl
        // 可能依赖于AbstractBeanFactory#resolveBeanClass这个方法去解析
        Class<?> targetType = determineTargetType(beanName, mbd);
        if (targetType != null) {
          // 先执行执行InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation回调方法  
          // 里面的逻辑也比较简单:拿到缓存好的(List装着的)所有的BeanPostProcessors,如果是InstantiationAwareBeanPostProcessor就执行吧~~
          // 只要有一个result不为null;后面的所有 后置处理器的方法就不执行了,直接返回(所以执行顺序很重要)
          //1、ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor这个内部类就是这个类型。主要还是去增强、完善处理@Configuration这种类   但是它并没有重写postProcessBeforeInstantiation这个方法,所以默认是返回null的
          //2、CommonAnnotationBeanPostProcessor/Autowired。。。也没做处理(若你自己不去注册,那系统里就再没有了)
          // 需要注意的是,如果我们采用了AOP、声明式事务等等,这里就会有了,后面又会回来讲解这一块
          bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
          // 我们可以看到,如果bean不为null,那就直接返回了  短路掉后面的After也就不执行了
          if (bean != null) {
            // 注意,这里是Initialization,是初始化的后置方法,是BeanPostProcessor的方法,也就是说初始化完成后的方法。
            // 为何这里执行这个方法呢?是因为我们上面说了,如果返回不为null,后面都都会被短路掉。但是此处Spring还是让我们执行了初始化后的处理器方法,这点需要引起注意
            // 就是说:即使Bean在实例化前已经返回了一个不为null的对象,别的方法都被短路了,但是我的【初始化】后处理器方法applyBeanPostProcessorsAfterInitializationh还是可以执行的
            // 这里面可以关注一下这个类:ApplicationListenerDetector
            //初始化之后的方法返回了null,那就需要调用doCreateBean生成对象了==============
            bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
          }
        }
      }
      mbd.beforeInstantiationResolved = (bean != null);
    }
    return bean;
  }


BeanPostProcessor和InstantiationAwareBeanPostProcessor和SmartInstantiationAwareBeanPostProcessor和MergedBeanDefinitionPostProcessor

这两个接口,是比较容易搞混的,需要这里注意区分一下。InstantiationAwareBeanPostProcessor代表了Spring的另外一段生命周期:实例化。先区别一下Spring Bean的实例化和初始化两个阶段的主要作用:


  • 实例化:实例化的过程是一个创建Bean的过程,即调用Bean的构造函数,单例的Bean放入单例池中
  • 初始化:初始化的过程是一个赋值的过程,即调用Bean的setter,设置Bean的属性


所以现在就清楚了:InstantiationAwareBeanPostProcessor是作用于 实例化 前后,所以是先执行的。BeanPostProcessor是作用于 初始化 前后,给Bean各个属性赋值的时候执行的(比如我们的属性依赖注入,都是这个时候生效的)


BeanPostProcessor中的方法是初始化类时候的处理器(实例化早于初始化)在spring中初始化指的一般是在调用init-method属性前后

// 咋一看,以为方法名都一样?哈哈  其实你区分出来两个单词的意思,就明白了
// Instantiation:[ɪnstænʃɪ'eɪʃən] 实例化,例示
// Initialization:[ɪˌnɪʃəlaɪ'zeɪʃn] 初始化,设定初始值
public interface BeanPostProcessor {
  @Nullable
  default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    return bean;
  }
  @Nullable
  default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    return bean;
  }
}
子接口:InstantiationAwareBeanPostProcessor
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
  @Nullable
  default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    return null;
  }
  default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
    return true;
  }
  @Nullable
  default PropertyValues postProcessPropertyValues(
      PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
    return pvs;
  }
}


内部类:BeanPostProcessorCheckersh实现了postProcessAfterInitialization方法:输出了一行日志而已


ApplicationListenerDetector重点实现了postProcessAfterInitialization方法:测那些实现了接口ApplicationListener的bean,在它们创建时初始化之后,将它们添加到应用上下文的事件多播器上。并在这些ApplicationListener bean销毁之前,将它们从应用上下文的事件多播器上移除。


子接口:SmartInstantiationAwareBeanPostProcessor


SmartInstantiationAwareBeanPostProcessor 继承自 InstantiationAwareBeanPostProcessor;

但是SmartInstantiationAwareBeanPostProcessor多了一个三个方法

// 从名字上,它有个Smart,是比较智能一些的
public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {
  // 预测Bean的类型,返回第一个预测成功的Class类型,如果不能预测返回null
  @Nullable
  default Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
    return null;
  }
  // 选择合适的构造器,比如目标对象有多个构造器,在这里可以进行一些定制化,选择合适的构造器
  // beanClass参数表示目标实例的类型,beanName是目标实例在Spring容器中的name
  // 返回值是个构造器数组,如果返回null,会执行下一个PostProcessor的determineCandidateConstructors方法;否则选取该PostProcessor选择的构造器
  @Nullable
  default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)
      throws BeansException {
    return null;
  }
  // 获得提前暴露的bean引用。主要用于解决循环引用的问题
  // 只有单例对象才会调用此方法
  // 在我们准们处理讲解循环引用的时候,这个方法会起到比较关键的作用
  default Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
    return bean;
  }
}


这个接口有什么作用的呢?这里举例两个实现,有个感觉就行:

比如AutowiredAnnotationBeanPostProcessor:依赖注入时的泛型依赖注入,就通过这个能智能判断类型来注入。


泛型依赖注入的优点:允许我们在使用spring进行依赖注入的同时,利用泛型的优点对代码进行精简,将可重复使用的代码全部放到一个类之中,方便以后的维护和修改。比如常用的Base设计。。。(属于Spring 4.0的新特性)


Spring4.0之后,这样是不报错的:

@Configuration
public class MyConfiguration {
  @Bean
  public BaseRepository<Student> studentRepository() {
    return new BaseRepository<Student>() {};
  }
  @Bean
  public BaseRepository<Faculty> facultyRepository() {
    return new BaseRepository<Faculty>() {};
  }
}
// 注意,这里能够正确注入到正确的Bean,虽然他们都是BaseRepository类型。但是在Spring4.0之后,泛型里面的东西
// 也可以作为一种分类Qualifier,随意这里虽然都是BaseRepositor类型,但是在容器中还是被分开了的
@Autowired private BaseRepository<Student> studentRepo; 
@Autowired private BaseRepository<Faculty> facultyRepo;


另外Spring-AOP包下有很多实现,比如我们最熟悉的:AnnotationAwareAspectJAutoProxyCreator等等这种类,具体我们在AOP分析的时候再详解


子类MergedBeanDefinitionPostProcessor


public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
  //来给后续回调中缓存一些meta信息使用
  void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
}


用来将merged BeanDefinition暴露出来的回调。看看它的一些主要实现:


//InitDestroyAnnotationBeanPostProcessor
  @Override
  public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    LifecycleMetadata metadata = findLifecycleMetadata(beanType);
    metadata.checkConfigMembers(beanDefinition);
  }
//CommonAnnotationBeanPostProcessor
  @Override
  public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
    InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
    metadata.checkConfigMembers(beanDefinition);
  }
//AutowiredAnnotationBeanPostProcessor
  @Override
  public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
    metadata.checkConfigMembers(beanDefinition);
  }
//ApplicationListenerDetector
  @Override
  public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
    this.singletonNames.put(beanName, beanDefinition.isSingleton());
  }


稍微总结下:


  1. InstantiationAwareBeanPostProcessor接口的主要作用在于目标对象的实例化过程中需要处理的事情,包括实例化对象的前后过程以及实例的属性设置
  2. postProcessBeforeInstantiation方法是最先执行的方法,它在目标对象实例化之前调用,该方法的返回值类型是Object,我们可以返回任何类型的值。由于这个时候目标对象还未实例化,所以这个返回值可以用来代替原本该生成的目标对象的实例(比如代理对象)。如果该方法的返回值代替原本该生成的目标对象,后续只有postProcessAfterInitialization方法会调用,其它方法不再调用;否则按照正常的流程走
  3. postProcessAfterInstantiation方法在目标对象实例化之后调用,这个时候对象已经被实例化,但是该实例的属性还未被设置,都是null。因为它的返回值是决定要不要调用postProcessPropertyValues方法的其中一个因素(因为还有一个因素是mbd.getDependencyCheck());如果该方法返回false,并且不需要check,那么postProcessPropertyValues就会被忽略不执行;如果返回true,postProcessPropertyValues就会被执行
  4. postProcessPropertyValues方法对属性值进行修改(这个时候属性值还未被设置,但是我们可以修改原本该设置进去的属性值)。如果postProcessAfterInstantiation方法返回false,该方法可能不会被调用。可以在该方法内对属性值进行修改
  5. 父接口BeanPostProcessor的2个方法postProcessBeforeInitialization和postProcessAfterInitialization都是在目标对象被实例化之后,并且属性也被设置之后调用的
  6. Instantiation表示实例化,Initialization表示初始化。实例化的意思在对象还未生成,初始化的意思在对象已经生成


创建Bean的最终方法,绝大多数Bean的实例化、初始化都会走这里:

AbstractAutowireCapableBeanFactory#doCreateBean:


spring的ioc创建bean的最核心代码 我们来看看他具体做了啥 怎么做


讲解之前,贤了解下BeanWrapper吧:


BeanWrapper 是Spring提供的一个用来操作javaBean属性的工具,使用它可以直接修改一个对象的属性。

BeanWrapper大部分情况下是在spring ioc内部进行使用,通过BeanWrapper,spring ioc容器可以用统一的方式来访问bean的属性。用户很少需要直接使用BeanWrapper进行编程。


对于bean属性的操作,我们熟知的主要有下面这些工具类:


   1.Apache的BeanUtils和PropertyUtils

   2.cglib的BeanMap和BeanCopier

   3.spring的BeanUtils


Spring中BeanWrapper 的主要在于如下三点:

1· 支持设置嵌套属性

2. 支持属性值的类型转换(设置ConversionService)

3. 提供分析和操作标准JavaBean的操作:获取和设置属性值(单独或批量),获取属性描述符以及查询属性的可读性/可写性的能力

public interface BeanWrapper extends ConfigurablePropertyAccessor {
   //为数组和集合自动增长指定一个限制。在普通的BeanWrapper上默认是无限的。
  void setAutoGrowCollectionLimit(int autoGrowCollectionLimit);
  //返回数组和集合自动增长的限制。
  int getAutoGrowCollectionLimit();
    //如果有的话,返回由此对象包装的bean实例
  Object getWrappedInstance();
  //返回被包装的JavaBean对象的类型。
  Class<?> getWrappedClass();
  //获取包装对象的PropertyDescriptors(由标准JavaBeans自省确定)。
  PropertyDescriptor[] getPropertyDescriptors();
  //获取包装对象的特定属性的属性描述符。
  PropertyDescriptor getPropertyDescriptor(String propertyName) throws InvalidPropertyException;
}


BeanWrapperImpl是Spring提供的唯一实现类。具体此处不深究了,知道它是Spring用来统一处理Bean的就成了


doCreateBean源码解析

  protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
      throws BeanCreationException {
    // 用BeanWrapper来持有创建出来的Bean对象
    BeanWrapper instanceWrapper = null;
    //如果是单例的话,则先把缓存中的同名bean清除(同名的)
    if (mbd.isSingleton()) {
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
    }
    //实际创建的交给createBeanInstance来完成,
    //bean的生成,这里会使用默认的类生成器,包装成BeanWrapperImpl类,为了下面的populateBean方法的属性注入做准备 
    if (instanceWrapper == null) {
      instanceWrapper = createBeanInstance(beanName, mbd, args);
    }
    final Object bean = instanceWrapper.getWrappedInstance();
    Class<?> beanType = instanceWrapper.getWrappedClass();
    //如果不是NullBean,则将resolvedTargetType 属性设置为当前的WrappedClass
    if (beanType != NullBean.class) {
      mbd.resolvedTargetType = beanType;
    }
    // Allow post-processors to modify the merged bean definition.
    synchronized (mbd.postProcessingLock) {
      if (!mbd.postProcessed) {
        try {
          // 此处处理这个接口的处理器:MergedBeanDefinitionPostProcessor,他在BeanPostProcessor的基础上增加了postProcessMergedBeanDefinition方法,在此处就被调用了
          // 主要是处理@PostConstruct,@Autowire,@Value,@Resource,@PreDestory等这些注解。(显然对应哪去处理器,一目了然了) 下面会举例看看AutowiredAnnotationBeanPostProcessor的处理
          applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
        } catch (Throwable ex) {
          throw new BeanCreationException(mbd.getResourceDescription(), beanName,
              "Post-processing of merged bean definition failed", ex);
        }
        mbd.postProcessed = true;
      }
    }
    // Eagerly cache singletons to be able to resolve circular references
    // even when triggered by lifecycle interfaces like BeanFactoryAware.
    //如果当前bean是单例,且支持循环依赖,且当前bean正在创建,通过往singletonFactories添加一个objectFactory,这样后期如果有其他bean依赖该bean 可以从singletonFactories获取到bean
    //getEarlyBeanReference可以对返回的bean进行修改,这边目前除了可能会返回动态代理对象 其他的都是直接返回bean
    boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
        isSingletonCurrentlyInCreation(beanName));
    if (earlySingletonExposure) {
      if (logger.isDebugEnabled()) {
        logger.debug("Eagerly caching bean '" + beanName +
            "' to allow for resolving potential circular references");
      }
      // 这里面主要是解决循环引用问题~~~~~~~~~借助了这个工厂
      //这里主要是调用处理器:SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference方法去寻找到前期的Bean们(若存在这种处理器的话)
      addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    }
    // Initialize the bean instance.
    // 这个Obj,就是最终要返回的对象了
    Object exposedObject = bean;
    try {
      // 这又是非常非常重要的一步:给已经初始化的属性们赋值===================对bean进行填充,在这里面完成依赖注入的相关内容
      // 啥都不说了,看下面的详解吧
      populateBean(beanName, mbd, instanceWrapper);
      //完成属性依赖注入后,进一步初始化Bean  具体进行了以下操作:
      //若实现了BeanNameAware, BeanClassLoaderAware,BeanFactoryAwareAware等接口,则注入相关对象
      //遍历后置处理器,调用实现的postProcessBeforeInitialization方法,
      //如果实现了initialzingBean,调用实现的 afterPropertiesSet()
      //如果配置了init-mothod,调用相应的init方法
      //遍历后置处理器,调用实现的postProcessAfterInitialization
      // 关于populateBean和initializeBean的详解,下贴出了博文链接参考~~~~~~
      exposedObject = initializeBean(beanName, exposedObject, mbd);
    } catch (Throwable ex) {
      if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
        throw (BeanCreationException) ex;
      } else {
        throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
      }
    }
    //如果earlySingletonExposure为true,尝试从缓存获取该bean(一般存放在singletonFactories对象通过调用getObject 把对象存入earlySingletonObjects),
    // 分别从singletonObjects和earlySingletonObjects获取对象   这里依然是处理循环依赖相关问题的
    if (earlySingletonExposure) {
      Object earlySingletonReference = getSingleton(beanName, false);
      //如果获取到对象了
      if (earlySingletonReference != null) {
        if (exposedObject == bean) {
          exposedObject = earlySingletonReference;
        }
        else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
          String[] dependentBeans = getDependentBeans(beanName);
          Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
          for (String dependentBean : dependentBeans) {
            if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
              actualDependentBeans.add(dependentBean);
            }
          }
          if (!actualDependentBeans.isEmpty()) {
            throw new BeanCurrentlyInCreationException(beanName,
                "Bean with name '" + beanName + "' has been injected into other beans [" +
                StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                "] in its raw version as part of a circular reference, but has eventually been " +
                "wrapped. This means that said other beans do not use the final version of the " +
                "bean. This is often the result of over-eager type matching - consider using " +
                "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
          }
        }
      }
    }
    // Register bean as disposable.
    try {
      // 如果有需要,就注册DisposableBean,这样Bean销毁的时候此种后置处理器也会生效了
      registerDisposableBeanIfNecessary(beanName, bean, mbd);
    } catch (BeanDefinitionValidationException ex) {
      throw new BeanCreationException(
          mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
    }
    return exposedObject;
  }


doCreateBean依赖的createBeanInstance 和 populateBean两个方法解释:

在 createBeanInstance 中生成了Bean所包含的java对象:


  protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // Make sure bean class is actually resolved at this point.
    //一样的,确保bean类实际上已经解析过了,可以实例化
    Class<?> beanClass = resolveBeanClass(mbd, beanName);
    //确保class不为空,并且访问权限为public  所以注意如果你的Class不是public的,Spring给你创建不了对象
    if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
      throw new BeanCreationException(mbd.getResourceDescription(), beanName,
          "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
    }
    // 配置的一种特殊的callback回调方法,通过这个callback创建bean
    // Supplier返回的Obj,最终会交给obtainFromSupplier包装成BeanWrapper 
    Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
    if (instanceSupplier != null) {
      return obtainFromSupplier(instanceSupplier, beanName);
    }
    // 这是Spring支持的又一种方式:使用工厂方法来进行bean的实例化
    if (mbd.getFactoryMethodName() != null)  {
      return instantiateUsingFactoryMethod(beanName, mbd, args);
    }
    // Shortcut when re-creating the same bean...
    // 一个类可能有多个构造器,所以Spring得根据参数个数、类型确定需要调用的构造器
    // 在使用构造器创建实例后,Spring会将解析过后确定下来的构造器或工厂方法保存在缓存中,避免再次创建相同bean时再次解析
    // 此部分在循环依赖中,会有更深入的说明~~~~~~~~~~~~~~~~
    boolean resolved = false;
    boolean autowireNecessary = false;
    if (args == null) {
      synchronized (mbd.constructorArgumentLock) {
        if (mbd.resolvedConstructorOrFactoryMethod != null) {
          // 标记一下,已经解析过class的构造器
          resolved = true;
          autowireNecessary = mbd.constructorArgumentsResolved;
        }
      }
    }
    // resolved若为true,表示已经解析过构造器了,就下面直接使用解析好的构造器实例化Bean
    if (resolved) {
      if (autowireNecessary) {
        return autowireConstructor(beanName, mbd, null, null);
      }
      else {
        return instantiateBean(beanName, mbd);
      }
    }
    // Need to determine the constructor...
    // 通过此方法,去检测到一个可用的构造器:这里面智能使用SmartInstantiationAwareBeanPostProcessor啦,它通过循环调用处理器的determineCandidateConstructors方法,谁第一个发现一个可用的构造器,就return,否则返回null
    // 详情见下面讲解AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors方法的讲解
    // 这里需要注意:如果你的Bean没有空的构造函数(比如只有一个参数的构造函数,那么Spring会用这个构造函数给你实例化Bean,并且入参会自动帮你从容器里去找出来)
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    if (ctors != null ||
        mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
        mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
      return autowireConstructor(beanName, mbd, ctors, args);
    }
    // No special handling: simply use no-arg constructor.
    return instantiateBean(beanName, mbd);
  }


AutowiredAnnotationBeanPostProcessor#determineCandidateConstructors:检测出候选的构造器们(也就是我们常说的:构造器注入)

检测Bean的构造器,可以检测出多个候选构造器,再有相应的策略决定使用哪一个。它将将自动扫描通过@Autowired/@Value注解的构造器从而可以完成构造器注入

  @Override
  @Nullable
  public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, final String beanName)
      throws BeanCreationException {
    // Let's check for lookup methods here..
    // 检测@Lookup注解,这个注解的注入方式,已经不推荐使用了===========
    if (!this.lookupMethodsChecked.contains(beanName)) {
      try {
        ReflectionUtils.doWithMethods(beanClass, method -> {
          Lookup lookup = method.getAnnotation(Lookup.class);
          if (lookup != null) {
            Assert.state(beanFactory != null, "No BeanFactory available");
            LookupOverride override = new LookupOverride(method, lookup.value());
            try {
              RootBeanDefinition mbd = (RootBeanDefinition) beanFactory.getMergedBeanDefinition(beanName);
              mbd.getMethodOverrides().addOverride(override);
            }
            catch (NoSuchBeanDefinitionException ex) {
              throw new BeanCreationException(beanName,
                "Cannot apply @Lookup to beans without corresponding bean definition");
            }
          }
        });
      }
      catch (IllegalStateException ex) {
        throw new BeanCreationException(beanName, "Lookup method resolution failed", ex);
      }
      this.lookupMethodsChecked.add(beanName);
    }
    // Quick check on the concurrent map first, with minimal locking.
    // 先从缓存里去看,有没有解析过此类的构造函数~~~
    对每个类的构造函数只解析一次,解析完会存储结果,以备下次复用
    Constructor<?>[] candidateConstructors = this.candidateConstructorsCache.get(beanClass);
    if (candidateConstructors == null) {
      // Fully synchronized resolution now...
      synchronized (this.candidateConstructorsCache) {
        // 为了线程安全,这里继续校验一次
        candidateConstructors = this.candidateConstructorsCache.get(beanClass);
        if (candidateConstructors == null) {
          Constructor<?>[] rawCandidates;
          try {
            // 拿到此Class所有的构造函数们(一般的类都只有一个空的构造函数)  当然我们也可以写多个
            rawCandidates = beanClass.getDeclaredConstructors();
          } catch (Throwable ex) {
            throw new BeanCreationException(beanName,
                "Resolution of declared constructors on bean Class [" + beanClass.getName() +
                "] from ClassLoader [" + beanClass.getClassLoader() + "] failed", ex);
          }
          List<Constructor<?>> candidates = new ArrayList<>(rawCandidates.length);
          Constructor<?> requiredConstructor = null;
          Constructor<?> defaultConstructor = null;
          // 兼容Kotlin类型做的处理~~~~~~~~~~~~
          Constructor<?> primaryConstructor = BeanUtils.findPrimaryConstructor(beanClass);
          int nonSyntheticConstructors = 0;
          // 遍历处理每个每个构造器~~~~~~~~~~~~~~~~~~
          for (Constructor<?> candidate : rawCandidates) {
            if (!candidate.isSynthetic()) {
              nonSyntheticConstructors++;
            }
            else if (primaryConstructor != null) {
              continue;
            }
            // 找到构造器里有@Aotowaired或者@Value注解的直接信息们
            AnnotationAttributes ann = findAutowiredAnnotation(candidate);
            if (ann == null) {
              // 此方法的目的是拿到目标类:比如若是被cglib代理过的,那就拿到父类(因为cglib是通过子类的形式加强的)
              Class<?> userClass = ClassUtils.getUserClass(beanClass);
              // 说明确实是被CGLIB代理过的,那就再解析一次  看看父类是否有@Autowaired这种构造器
              if (userClass != beanClass) {
                try {
                  Constructor<?> superCtor = userClass.getDeclaredConstructor(candidate.getParameterTypes());
                  ann = findAutowiredAnnotation(superCtor);
                } catch (NoSuchMethodException ex) {
                  // Simply proceed, no equivalent superclass constructor found...
                }
              }
            }
            // 这里是是存在注解标注的这种构造器的
            if (ann != null) {
              // 这个判断很有必要,表示要求的构造器最多只能有一个
              //画外音:@Autowired标注的构造器数量最多只能有一个(当然,required=true的只能有一个,=false的可以有多个)
              if (requiredConstructor != null) {
                throw new BeanCreationException(beanName,
                    "Invalid autowire-marked constructor: " + candidate +
                    ". Found constructor with 'required' Autowired annotation already: " +
                    requiredConstructor);
              }
              //获取autowire注解中required属性值
              boolean required = determineRequiredStatus(ann);
              // 只有是true,就往下走(默认值为true)
              if (required) {
                if (!candidates.isEmpty()) {
                  throw new BeanCreationException(beanName,
                      "Invalid autowire-marked constructors: " + candidates +
                      ". Found constructor with 'required' Autowired annotation: " +
                      candidate);
                }
                // 这样子,这个构造器就是必须的了,记录下来
                requiredConstructor = candidate;
              }
              // 把标注有@Autowired注解的构造器,记录下来,作为候选的构造器
              candidates.add(candidate);
            }
            // 这个就重要了,处理精妙
            // 若该构造器没有被标注@Autowired注解,但是它是无参构造器,那就当然候选的构造器(当然是以标注了@Autowired的为准)
             else if (candidate.getParameterCount() == 0) {
              // 这里注意:虽然把默认的构造函数记录下来了,但是并没有加进candidates里
              defaultConstructor = candidate;
            }
          }
          // 若能找到候选的构造器,这里注意,如果仅仅只有一个构造器的情况(没有标注@Autowired注解),这个亏胡原始股fakse,下面的elseif会处理的。。。。
          if (!candidates.isEmpty()) {
            // Add default constructor to list of optional constructors, as fallback.
            // 这个是candidates里面有值了,并且还没有requiredConstructor (相当于标注了注解@Autowired,但是required=false)   的情况下,会吧默认的构造函数加进candidates
            if (requiredConstructor == null) {
              if (defaultConstructor != null) {
                candidates.add(defaultConstructor);
              }
              //如果没有默认的无参构造函数,且有@Autowired(required = false)的构造函数,则发出警告信
              else if (candidates.size() == 1 && logger.isWarnEnabled()) {
                logger.warn("Inconsistent constructor declaration on bean with name '" + beanName +
                    "': single autowire-marked constructor flagged as optional - " +
                    "this constructor is effectively required since there is no " +
                    "default constructor to fall back to: " + candidates.get(0));
              }
            }
            candidateConstructors = candidates.toArray(new Constructor<?>[0]);
          }
          // 这个意思是:有且仅有一个构造器,并且该构造器的参数大于0个,那就是我们要找的构造器了
          // 这种情况,也是平时我们使用得比较多的情况
          else if (rawCandidates.length == 1 && rawCandidates[0].getParameterCount() > 0) {
            candidateConstructors = new Constructor<?>[] {rawCandidates[0]};
          }
          // 处理primaryConstructor以及nonSyntheticConstructors    兼容Kotlin一般都达不到
          else if (nonSyntheticConstructors == 2 && primaryConstructor != null
              && defaultConstructor != null && !primaryConstructor.equals(defaultConstructor)) {
            candidateConstructors = new Constructor<?>[] {primaryConstructor, defaultConstructor};
          }
          else if (nonSyntheticConstructors == 1 && primaryConstructor != null) {
            candidateConstructors = new Constructor<?>[] {primaryConstructor};
          }
          // 啥构造器都没找到,那就是空数组
          else {
            candidateConstructors = new Constructor<?>[0];
          }
          this.candidateConstructorsCache.put(beanClass, candidateConstructors);
        }
      }
    }
    // 若有多个构造函数,但是没有一个标记了@Autowired,此处不会报错,但是返回null,交给后面的策略处理
    return (candidateConstructors.length > 0 ? candidateConstructors : null);
  }

可能有小伙伴会问:其实最终找到的构造器都是一个,这里为何返回一个数组呢?如果是这么认为,那你就还是没有太完全理解这里面的处理原理,比如下面情况:


@Service
public class HelloServiceImpl implements HelloService {
    private ApplicationContext applicationContext;
    private BeanFactory beanFactory;
    @Autowired(required = false)
    public HelloServiceImpl(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }
    @Autowired(required = false)
    public HelloServiceImpl(ApplicationContext applicationContext, BeanFactory beanFactory) {
        this.applicationContext = applicationContext;
        this.beanFactory = beanFactory;
    }
}


这里就返回的是2个构造器。这里最终会执行2个参数的构造器。这种情况:


    private ApplicationContext applicationContext;
    private BeanFactory beanFactory;
    HelloServiceImpl() {
        System.out.println("我是空构造~");
    }
    @Autowired(required = false)
    public HelloServiceImpl(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }
    @Autowired(required = false)
    public HelloServiceImpl(ApplicationContext applicationContext, BeanFactory beanFactory) {
        this.applicationContext = applicationContext;
        this.beanFactory = beanFactory;
    }


会返回3个构造器。最终执行的,还是参数最多的那个构造器。若返回多个构造器,Spring具体的执行策略,下面继续说:


Spring初始化Bean的执行策略(实例化Bean的过程)


主要处理代码如下:


    if (ctors != null ||
        // 或者标注了处理机制是构造器注入方式 AbstractBeanDefinition#setAutowireMode可以设置模式
        mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
        mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
      // 构造器选择策略,注入逻辑
      return autowireConstructor(beanName, mbd, ctors, args);
    }



相关文章
|
15天前
|
XML 安全 Java
|
15天前
|
XML Java 数据格式
Spring Core核心类库的功能与应用实践分析
【12月更文挑战第1天】大家好,今天我们来聊聊Spring Core这个强大的核心类库。Spring Core作为Spring框架的基础,提供了控制反转(IOC)和依赖注入(DI)等核心功能,以及企业级功能,如JNDI和定时任务等。通过本文,我们将从概述、功能点、背景、业务点、底层原理等多个方面深入剖析Spring Core,并通过多个Java示例展示其应用实践,同时指出对应实践的优缺点。
40 14
|
1月前
|
缓存 Java Spring
实战指南:四种调整 Spring Bean 初始化顺序的方案
本文探讨了如何调整 Spring Boot 中 Bean 的初始化顺序,以满足业务需求。文章通过四种方案进行了详细分析: 1. **方案一 (@Order)**:通过 `@Order` 注解设置 Bean 的初始化顺序,但发现 `@PostConstruct` 会影响顺序。 2. **方案二 (SmartInitializingSingleton)**:在所有单例 Bean 初始化后执行额外的初始化工作,但无法精确控制特定 Bean 的顺序。 3. **方案三 (@DependsOn)**:通过 `@DependsOn` 注解指定 Bean 之间的依赖关系,成功实现顺序控制,但耦合性较高。
实战指南:四种调整 Spring Bean 初始化顺序的方案
|
13天前
|
安全 Java 开发者
Spring容器中的bean是线程安全的吗?
Spring容器中的bean默认为单例模式,多线程环境下若操作共享成员变量,易引发线程安全问题。Spring未对单例bean做线程安全处理,需开发者自行解决。通常,Spring bean(如Controller、Service、Dao)无状态变化,故多为线程安全。若涉及线程安全问题,可通过编码或设置bean作用域为prototype解决。
26 1
|
2月前
|
Java 测试技术 Windows
咦!Spring容器里为什么没有我需要的Bean?
【10月更文挑战第11天】项目经理给小菜分配了一个紧急需求,小菜迅速搭建了一个SpringBoot项目并完成了开发。然而,启动测试时发现接口404,原因是控制器包不在默认扫描路径下。通过配置`@ComponentScan`的`basePackages`字段,解决了问题。总结:`@SpringBootApplication`默认只扫描当前包下的组件,需要扫描其他包时需配置`@ComponentScan`。
|
3月前
|
SQL 监控 druid
springboot-druid数据源的配置方式及配置后台监控-自定义和导入stater(推荐-简单方便使用)两种方式配置druid数据源
这篇文章介绍了如何在Spring Boot项目中配置和监控Druid数据源,包括自定义配置和使用Spring Boot Starter两种方法。
|
2月前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
219 2
|
1天前
|
NoSQL Java Redis
Spring Boot 自动配置机制:从原理到自定义
Spring Boot 的自动配置机制通过 `spring.factories` 文件和 `@EnableAutoConfiguration` 注解,根据类路径中的依赖和条件注解自动配置所需的 Bean,大大简化了开发过程。本文深入探讨了自动配置的原理、条件化配置、自定义自动配置以及实际应用案例,帮助开发者更好地理解和利用这一强大特性。
28 14
|
23天前
|
缓存 IDE Java
SpringBoot入门(7)- 配置热部署devtools工具
SpringBoot入门(7)- 配置热部署devtools工具
41 1
SpringBoot入门(7)- 配置热部署devtools工具
|
1月前
|
缓存 IDE Java
SpringBoot入门(7)- 配置热部署devtools工具
SpringBoot入门(7)- 配置热部署devtools工具
43 2
 SpringBoot入门(7)- 配置热部署devtools工具