Spring注解扫描--源码解析

本文深入探讨了Spring中BeanDefinition的概念及其在不同场景下的应用,包括BeanDefinition的抽象实现如AbstractBeanDefinition、GenericBeanDefinition、RootBeanDefinition和ChildBeanDefinition。详细介绍了BeanDefinition的扫描过程,特别是ClassPathBeanDefinitionScanner的角色,以及如何通过doScan方法收集和处理带有特定注解的类。同时,文章还涉及了ConfigurationClassPostProcessor如何处理@ComponentScan、@Import和@Bean注解,以及Bean生命周期中的各种处理器接口。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、bean的定义BeanDefinition

  • BeanDefinition的含义 BeanDefinition就是用来描述一个Bean或者BeanDefinition就是Bean的定义。

    **Spirng官网描述**
    SpringIoc容器管理一个Bean或多个Bean,这些Bean通过我们提供给容器的配置元数据被创建出来(例如,在xml中的定义) 在容器中,这些Bean的定义用BeanDefinition对象来表示,
    包含以下元数据:
    
    全限定类名, 通常是Bean的实际实现类;
    Bean行为配置元素,它们说明Bean在容器中的行为(作用域、生命周期回调等等);
    Bean执行工作所需要的的其他Bean的引用,这些Bean也称为协作者或依赖项;
    其他配置信息,例如,管理连接池的bean中,限制池的大小或者使用的连接的数量。

    在Spring容器中,定义bean的方式:

  • <bean/>标签
    
    @Bean注解
    
    @Component(@Service、@Controller)

    从xml配置文件或者类路径中收集Spring需要的管理对象

    在Spring的启动过程第一步就是找到需要被管理的类,比如标注的@Configuration类

    找到之后将这些类封装到BeanDefinition对象,也就是bean,包含了这些类的全部信息BeanDefinition是一个接口,有三个实现RootBeanDefinition、ChildBeanDefinition、GenericBeanDefinition。所以也可以通过BeanDefinition这个对象定义一个bean我们通过,@Bean,@Component等方式所定义的Bean,最终都会被解析为BeanDefinition对象,所有的。

  • 使用BeanDefinition定义bean的流程:

    导入依赖:
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.6.RELEASE</version>
    </dependency>
    
    测试实体类:
    public class User {
        private Long id;
        private String name;
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void init(){
        System.out.println("初始化");
      }
    }
    
    启动类:
    public static void main(String[] args) {
      // 定义了一个BeanDefinition
      AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition()
        .getBeanDefinition();
      // 当前Bean对象的类型
      beanDefinition.setBeanClass(User.class);
      // 将BeanDefinition注册到BeanFactory中
      DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
      beanFactory.registerBeanDefinition("user", beanDefinition);
      // 获取Bean
      System.out.println(beanFactory.getBean("user"));
    }
    结果:com.gongj.entity.User@70177ecd
    
    
    **BeanDefinition可以设置其他属性**
    // 设置作用域
    beanDefinition.setScope("prototype");
    // 设置初始化方法
    beanDefinition.setInitMethodName("init");
    // 设置自动装配模型
    beanDefinition.setAutowireMode(AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE); 
    结果:
    初始化
    com.gongj.entity.User@1e88b3c
    
    

    BeanDefinition继承关系

  •  AttributeAccessor:定义用于附加和访问元数据的通用协定的接口,可以是任意对象。

  • public interface AttributeAccessor {
     
      //设置属性的值(名称唯一)
      void setAttribute(String name, Object value);
     
      //获得指定属性名称的值,如果不存在返回null
      Object getAttribute(String name);
     
      //删除指定的name的属性,如果不存在则返回null
      Object removeAttribute(String name);
     
          //判断指定的属性名称是否存在
      boolean hasAttribute(String name);
     
      //返回所有属性的名称
      String[] attributeNames();
    }
    

        BeanDefinition的源码:

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

// 单例Bean还是原型Bean
 String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
 String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

// Bean角色
 int ROLE_APPLICATION = 0;  //用户自己定义的 Bean
 int ROLE_SUPPORT = 1;  //来源于配置文件的 Bean
 int ROLE_INFRASTRUCTURE = 2;//Spring 内部的 Bean

//配置 /获取父BeanDefinition的名称   XML中的 <bean parent="">
 void setParentName(@Nullable String parentName);
 @Nullable
 String getParentName();

//配置/获取 Bean 的 Class 全路径  XML 中的 <bean class="">
 void setBeanClassName(@Nullable String beanClassName);
 @Nullable
 String getBeanClassName();

//配置/获取  Bean 的作用域  XML中的 <bean scope=""> 配置。
 void setScope(@Nullable String scope);
 @Nullable
 String getScope();

//配置 / 获取 Bean 是否懒加载(默认false,立马加载)
// XML 中的 <bean lazy-init="">
 void setLazyInit(boolean lazyInit);
 boolean isLazyInit();

//配置/获取 Bean 的依赖对象  XML中的 <bean depends-on="">
 void setDependsOn(@Nullable String... dependsOn);
 @Nullable
 String[] getDependsOn();

//配置/获取 Bean 是否是自动装配的候选者 默认为 true XML中的 <bean autowire-candidate="">
 void setAutowireCandidate(boolean autowireCandidate);
 boolean isAutowireCandidate();

//如果找到了多个可注入bean,那么则选择被Primary标记的bean/获取当
//前 Bean 是否为首选的 Bean  XML中的 <bean primary="">
 void setPrimary(boolean primary);
 boolean isPrimary();

// 配置/获取 FactoryBean 的名字  XML中的<bean factory-bean="">
 void setFactoryBeanName(@Nullable String factoryBeanName);
 @Nullable
 String getFactoryBeanName();

//配置/获取 FactoryMethod 的名字,可以是某个实例的方法(和factoryBean配合使用)
//也可以是静态方法。 XML 中的<bean factory-method=""> 
 void setFactoryMethodName(@Nullable String factoryMethodName);
 @Nullable
 String getFactoryMethodName();

//返回该 Bean 构造方法的参数值
 ConstructorArgumentValues getConstructorArgumentValues();

//判断 getConstructorArgumentValues 是否是空对象。
 default boolean hasConstructorArgumentValues() {
  return !getConstructorArgumentValues().isEmpty();
 }

//获取普通属性的集合
 MutablePropertyValues getPropertyValues();

//判断 getPropertyValues 是否为空对象
 default boolean hasPropertyValues() {
  return !getPropertyValues().isEmpty();
 }

// 配置/获取 Bean 的初始化方法 XML中的<bean init-method="">
 void setInitMethodName(@Nullable String initMethodName);
 @Nullable
 String getInitMethodName();

// 配置/获取 Bean 的销毁方法  XML中的<bean destroy-method="">
 void setDestroyMethodName(@Nullable String destroyMethodName);
 @Nullable
 String getDestroyMethodName();

//配置/获取 Bean的角色
 void setRole(int role);
 int getRole();

//配置/获取 Bean 的描述
 void setDescription(@Nullable String description);
 @Nullable
 String getDescription();

//用来解析一个Bean对应的类型上的各种信息,比如泛型
 ResolvableType getResolvableType();

//是否为单例
 boolean isSingleton();

// 是否为原型
 boolean isPrototype();

//是否抽象  XML 中的<bean abstract="true">
 boolean isAbstract();

//返回定义 Bean 的资源描述
 @Nullable
 String getResourceDescription();

// 如果当前 BeanDefinition 是一个代理对象,那么该方法可以用来返回原始的 BeanDefinition
 @Nullable
 BeanDefinition getOriginatingBeanDefinition();
}

具体关系图:

一、先说AbstractBeanDefinition AbstractBeanDefinition是一个抽象类,在BeanDefinition接口中只定义了get和set方法, 没有提供属性,具体的属性在AbstractBeanDefinition中定义

  • 1、源码

```Java
public abstract class AbstractBeanDefinition extends 
BeanMetadataAttributeAccessor
implements BeanDefinition, Cloneable {

  //默认作用域名称的常量:等效于单例
  public static final String SCOPE_DEFAULT = "";
  
  //自动装配的一些常量
  // autowireMode  = 0,默认值,未激活Autowiring。
  // bean 标签的 autowire 属性值为 no
  // 1、在xml中需要手动指定依赖注入对象 配置 property标签或者 constructor-arg标签
  // 2、使用 @Autowired 注解,autowireMode 的值也是 0
  public static final int AUTOWIRE_NO = AutowireCapableBeanFactory.AUTOWIRE_NO;
  
  //autowireMode  = 1,根据set方法的的名称作为Bean名称进行依赖查找
  //(去掉set,并尝试将首字母变为小写),并将对象设置到该set方法的参数上
  // bean 标签的 autowire 属性值配置为 byName
  public static final int AUTOWIRE_BY_NAME = 
  AutowireCapableBeanFactory.AUTOWIRE_BY_NAME;
  
  //autowireMode  = 2,根据set方法参数的类型作为Bean类型进行依赖查找
  //并将对象设置到该set方法的参数上
  // bean 标签的 autowire 属性值配置为 byType
  public static final int AUTOWIRE_BY_TYPE = 
  AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE;
  
  //autowireMode  = 3,构造器注入
  // bean 标签的 autowire 属性值配置为 constructor
  public static final int AUTOWIRE_CONSTRUCTOR = 
  AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR;
  
  //表明通过Bean的class的内部来自动装配 Spring3.0被弃用。
  // bean 标签的 autowire 属性值配置为 autodetect
  @Deprecated
  public static final int AUTOWIRE_AUTODETECT = 
  AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;
  
  //检查依赖是否合法,在本类中,默认不进行依赖检查
  //不进行检查
  public static final int DEPENDENCY_CHECK_NONE = 0;
  
  //对对象引用进行依赖性检查
  public static final int DEPENDENCY_CHECK_OBJECTS = 1;
  
  //对“简单”属性进行依赖性检查
  public static final int DEPENDENCY_CHECK_SIMPLE = 2;
  
  //对所有属性进行依赖检查
  public static final int DEPENDENCY_CHECK_ALL = 3;
  
  //若Bean未指定销毁方法,容器应该尝试推断Bean的销毁方法的名字,
  //目前,推断的销毁方法的名字一般为close或是shutdown
  public static final String INFER_METHOD = "(inferred)";
  
  //Bean的class对象或是类的全限定名
  @Nullable
  private volatile Object beanClass;
  
  //默认的scope是单例,对应bean属性scope
  //@Scope
  @Nullable
  private String scope = SCOPE_DEFAULT;
  
  //是否是抽象,对应bean属性abstract
  private boolean abstractFlag = false;
  
  //是否懒加载,对应bean属性lazy-init,默认不是懒加载
  //@Lazy
  @Nullable
  private Boolean lazyInit;
  
  //自动注入模式,对应bean属性autowire,默认不进行自动装配
  private int autowireMode = AUTOWIRE_NO;
  
  //是否进行依赖检查,默认不进行依赖检查
  private int dependencyCheck = DEPENDENCY_CHECK_NONE;
  
  //用来表示一个bean的实例化是否依靠另一个bean的实例化,先加载dependsOn的bean,
  //对应bean属性depend-on
  //@DependsOn
  @Nullable
  private String[] dependsOn;
  
  /**
   * autowire-candidate属性设置为false,这样容器在查找自动装配对象时,
   * 将不考虑该bean,即它不会被考虑作为其他bean自动装配的候选者,
   * 但是该bean本身还是可以使用自动装配来注入其他bean的
   */
  private boolean autowireCandidate = true;
  
  /**
   * 自动装配时出现多个bean候选者时,将作为首选者,对应bean属性primary,默认不是首选的
   * @Primary
   */
  private boolean primary = false;
  
  /**
   * 用于记录Qualifier,对应子元素qualifier <bean><qualifier></qualifier></bean>
   * 如果容器中有多个相同类型的 bean,
   这时我们就可以使用qualifier属性来设置加载指定Bean名称的bean
   * @Qualifier
   */
  private final Map < String, AutowireCandidateQualifier > qualifiers = 
  new LinkedHashMap <>();
  
  //java8的函数式接口,创建bean实例的方式之一
  @Nullable
  private Supplier <? > instanceSupplier;
  
  //是否允许访问非public方法和属性, 默认是true
  private boolean nonPublicAccessAllowed = true;
  
  /**
   * 是否以一种宽松的模式解析构造函数,默认为true,
   * 如果为false,则在以下情况
   * interface ITest{}
   * class ITestImpl implements ITest{};
   * class Main {
   *     Main(ITest i) {}
   *     Main(ITestImpl i) {}
   * }
   * 抛出异常,因为Spring无法准确定位哪个构造函数程序设置
   */
  private boolean lenientConstructorResolution = true;
  
  //工厂类名,对应bean属性factory-bean
  @Nullable
  private String factoryBeanName;
  
  //工厂方法名,对应bean属性factory-method
  @Nullable
  private String factoryMethodName;
  
  //记录构造函数注入属性,对应bean属性constructor-arg
  @Nullable
  private ConstructorArgumentValues constructorArgumentValues;
  
  //Bean属性的名称以及对应的值,这里不会存放构造函数相关的参数值,只会存放通过setter注入的值
  @Nullable
  private MutablePropertyValues propertyValues;
  
  //方法重写的持有者,记录lookup-method、replaced-method元素  @Lookup
  private MethodOverrides methodOverrides = new MethodOverrides();
  
  //初始化方法,对应bean属性init-method
  @Nullable
  private String initMethodName;
  
  //销毁方法,对应bean属性destroy-method
  @Nullable
  private String destroyMethodName;
  
  //是否执行init-method,默认为true
  private boolean enforceInitMethod = true;
  
  //是否执行destroy-method,默认为true
  private boolean enforceDestroyMethod = true;
  
  //是否是用户定义的而不是应用程序本身定义的,创建AOP时候为true
  private boolean synthetic = false;
  
  //Bean的角色,为用户自定义Bean
  private int role = BeanDefinition.ROLE_APPLICATION;
  
  //Bean的描述信息
  @Nullable
  private String description;
  
  //这个bean定义的资源
  @Nullable
  private Resource resource;
  //...
}

2、AbstractBeanDefinition的三个子类:

  • GenericBeanDefinition: GenericBeanDefinition 是从 Spring2.5 以后新加入的 bean 文件配置属性定义类,是一站式服务类。GenericBeanDefinition 可以动态设置父 Bean,同时兼具 RootBeanDefinition 和 ChildBeanDefinition 的功能。 GenericBeanDefinition 的实现比较简单,在 AbstractBeanDefinition 的基础上只增加了parentName的功能,其余的实现都在父类 AbstractBeanDefinition 里。 注:若你是xml配置,会解析所有属性并统一封装至 GenericBeanDefinition 类型的实例中,之后再逐渐解析的。

  • RootBeanDefinition:

    • 源码:

public class RootBeanDefinition extends AbstractBeanDefinition {
  // BeanDefinitionHolder 存储 Bean 的名称、别名、BeanDefinition
  @Nullable
  private BeanDefinitionHolder decoratedDefinition;
  // AnnotatedElement 是java反射包的接口,通过它可以查看 Bean 的注解信息
  @Nullable
  private AnnotatedElement qualifiedElement;
  // 决定了什么时候 BeanDefinition 需要重新合并
  volatile Boolean stale;
  // 允许缓存
  Boolean allowCaching = true;
  // 工厂方法是否唯一
  Boolean isFactoryMethodUnique = false;
  //封装了 java.lang.reflect.Type,提供了泛型相关的操作
  @Nullable
  volatile ResolvableType targetType;
  //用于缓存给定bean定义中确定的类
  // 表示 RootBeanDefinition 存储哪个类的信息
  @Nullable
  volatile Class<?> resolvedTargetType;
  //如果bean是FactoryBean,则用于缓存
  @Nullable
  volatile Boolean isFactoryBean;
  //用于缓存泛型类型工厂方法的返回类型
  @Nullable
  volatile ResolvableType factoryMethodReturnType;
  //用于缓存唯一的工厂方法
  @Nullable
  volatile Method factoryMethodToIntrospect;
  
  //下面四个构造函数字段的公共锁
  final Object constructorArgumentLock = new Object();
  // 用用于缓存已解析的构造函数或工厂方法
  @Nullable
  Executable resolvedConstructorOrFactoryMethod;
  //将构造函数参数标记为已解析
  Boolean constructorArgumentsResolved = false;
  //用于缓存完全解析的构造函数参数
  @Nullable
  Object[] resolvedConstructorArguments;
  //用于缓存部分准备好的构造函数参数
  @Nullable
  Object[] preparedConstructorArguments;
  
  //下面两个后处理字段的通用锁
  final Object postProcessingLock = new Object();
  //这表明已经应用了MergedBeanDefinitionPostProcessor
  Boolean postProcessed = false;
  //表明一个实例化前的后处理器已经启动
  @Nullable
  volatile Boolean beforeInstantiationResolved;
  //实际缓存的类型是 Constructor、Field、Method 类型
  @Nullable
  private Set<Member> externallyManagedConfigMembers;
  // InitializingBean中 的 init 回调函数名 afterPropertiesSet 会在这里记录,
  //以便进行生命周期回调
  @Nullable
  private Set<String> externallyManagedInitMethods;
  // DisposableBean 的 destroy 回调函数名 destroy 会在这里记录,以便进生命周期回调
  @Nullable
  private Set<String> externallyManagedDestroyMethods;
  
  //===========贴一个方法
  // 很明显,RootBeanDefiniiton是没有父BeanDefinition
  @Override
  public String getParentName() {
    return null;
  }
  // 并且还不能进行set
  @Override
  public void setParentName(@Nullable String parentName) {
    if (parentName != null) {
      throw new IllegalArgumentException("Root bean cannot be changed into a 
                                         child bean with parent reference");
    }
  }
}

    Spring创建Bean的时候就是基于RootBeanDefinition来创建的,并且RootBeanDefinition是没 有父BeanDefinition的(可以单独存在,不需要依赖父BeanDefinition)

ChildBeanDefinition: 继承自 AbstractBeanDefinition。其相当于一个子类,不可以单独存在,必须依赖一个父 BeanDetintion,构造 ChildBeanDefinition 时,通过构造方法传入父 BeanDetintion 的名称或通过 setParentName 设置父名称。它可以从父类继承方法参数、属性值,并可以重写父类的方法,同时也可以增加新的属性或者方法。(从 Spring 2.5 开始,以编程方式注册 Bean 定义的首选方法是 GenericBeanDefinition,GenericBeanDefinition 可以有效替代 ChildBeanDefinition 的绝大分部使用场合。)

  • 二、再说BeanDefinition

    • BeanDefinition的子接口

      • AnnotatedBeanDefinition源码:

        //关于其bean类-无需加载该类。
        public interface AnnotatedBeanDefinition extends BeanDefinition {
            //获取此bean定义注解的元数据
          **AnnotationMetadata** getMetadata();
        
        //获取此bean定义的工厂方法的元数据,如果没有,则为null
          @Nullable
          **MethodMetadata** getFactoryMethodMetadata();
        }

AnnotatedBeanDefinition可以返回两个元数据的类: AnnotationMetadata : 主要对 Bean 的注解信息进行操作,如:获取当前 Bean 标注的所有注解、判断是否包含指定注解。

  • 源码:

    public interface AnnotationMetadata extends ClassMetadata, AnnotatedTypeMetadata {
    
      //获取所有注解完全限定类名
      default Set<String> getAnnotationTypes() {
        return getAnnotations().stream()
            .filter(MergedAnnotation::isDirectlyPresent)
            .map(annotation -> annotation.getType().getName())
            .collect(Collectors.toCollection(LinkedHashSet::new));
      }
    
      //获得annottationName对应的元注解的类全限定名
      default Set<String> getMetaAnnotationTypes(String annotationName) {
        MergedAnnotation<?> annotation = getAnnotations().get(annotationName, MergedAnnotation::isDirectlyPresent);
        if (!annotation.isPresent()) {
          return Collections.emptySet();
        }
        return MergedAnnotations.from(annotation.getType(), SearchStrategy.INHERITED_ANNOTATIONS).stream()
            .map(mergedAnnotation -> mergedAnnotation.getType().getName())
            .collect(Collectors.toCollection(LinkedHashSet::new));
      }
    
      //是否包含指定注解 
      default boolean hasAnnotation(String annotationName) {
        return getAnnotations().isDirectlyPresent(annotationName);
      }
    
      //确定是否含有某个元注解
      default boolean hasMetaAnnotation(String metaAnnotationName) {
        return getAnnotations().get(metaAnnotationName,
            MergedAnnotation::isMetaPresent).isPresent();
      }
    
      //类里面只要有一个方法标注有指定注解,就返回true
      default boolean hasAnnotatedMethods(String annotationName) {
        return !getAnnotatedMethods(annotationName).isEmpty();
      }
          // 返回所有的标注有指定注解的方法元信息
      Set<MethodMetadata> getAnnotatedMethods(String annotationName);
    
      //工厂方法来使用标准反射为给定的类创建一个新的AnnotationMetadata实例
      static AnnotationMetadata introspect(Class<?> type) {
        return StandardAnnotationMetadata.from(type);
      }
    }
    

    MethodMetadata : 方法的元数据类。提供获取方法名称、此方法所属类的全类名、是否是抽象方法、判断是否是静态方法、判断是否是final方法等。

  • 源码:

    public interface MethodMetadata extends AnnotatedTypeMetadata {
    
      //返回方法的名字
      String getMethodName();
    
      //返回该方法所属的类的全限定名
      String getDeclaringClassName();
    
      //返回该方法返回类型的全限定名
      String getReturnTypeName();
    
      //方法是否是有效的抽象方法:即在类上标记为抽象的或声明为规则的,
      //接口中的非默认方法。
      boolean isAbstract();
    
      //方法是否声明为'static'。
      boolean isStatic();
    
      //方法是否标记为'final'。
      boolean isFinal();
    
      //方法是否可重写:即没有标记为static、final或private。
      boolean isOverridable();
    }
    

    AnnotatedBeanDefinition下面的三个子类:

  • ScannedGenericBeanDefinition: 实现了 AnnotatedBeanDefinition 也继承了 GenericBeanDefinition。这个 BeanDefinition 用来描述标注@Component、@Service、@Controller等注解标记的类会解析为 ScannedGenericBeanDefinition。

    • 源码 多了一个属性:metadata 用来存储扫描进来的Bean的一些注解信息。

      public class ScannedGenericBeanDefinition extends GenericBeanDefinition implements AnnotatedBeanDefinition {
      
        private final AnnotationMetadata metadata;
      
          /**
         * 鉴于MetadataReader描述,为类创建一个新的ScannedGenericBeanDefinition
         */
        public ScannedGenericBeanDefinition(MetadataReader metadataReader) {
          Assert.notNull(metadataReader, "MetadataReader must not be null");
          this.metadata = metadataReader.getAnnotationMetadata();
          setBeanClassName(this.metadata.getClassName());
        }
      
      
        @Override
        public final AnnotationMetadata getMetadata() {
          return this.metadata;
        }
      
        @Override
        @Nullable
        public MethodMetadata getFactoryMethodMetadata() {
          return null;
        }
      }
      

    • ConfigurationClassBeanDefinition: 它是ConfigurationClassBeanDefinitionReader的一个私有的静态内部类:这个类负责将@Bean注解的方法转换为对应的ConfigurationClassBeanDefinition 类,源码就不过多解释了,和之前几个BeanDefinition差不多。 其功能特点如下: 1、如果 @Bean 注解没有指定 Bean 的名字,默认会用方法的名字作为Bean的名称。 2、标注 @Configuration、@Component、@Service 注解的类会成为一个工厂类,而标注 @Bean 注解的方法会成为工厂方法,通过工厂方法实例化 Bean。

    • AnnotatedGenericBeanDefinition: 该类继承自 GenericBeanDefinition ,并实现了AnnotatedBeanDefinition 接口。这个 BeanDefinition 用来描述标注使用了 @Configuration 注解标记配置类会解析为 AnnotatedGenericBeanDefinition。

      • 源码

        public class AnnotatedGenericBeanDefinition extends 
        GenericBeanDefinition implements AnnotatedBeanDefinition {
        
          // 注解元数据
          private final AnnotationMetadata metadata;
        
          @Nullable
          private MethodMetadata factoryMethodMetadata;
        
        
          /**
           * 为给定的bean类创建一个新的AnnotatedGenericBeanDefinition
           * @param beanClass the loaded bean class:加载的bean类
           */
          public AnnotatedGenericBeanDefinition(Class<?> beanClass) {
            setBeanClass(beanClass);
            // 当前类上有哪些注解
            this.metadata = AnnotationMetadata.introspect(beanClass);
          }
        
          /**
           * 
           * 为给定的注释元数据创建一个新AnnotatedGenericBeanDefinition,
           传入AnnotationMetadata
           */
          public AnnotatedGenericBeanDefinition(AnnotationMetadata metadata) {
            Assert.notNull(metadata, "AnnotationMetadata must not be null");
            if (metadata instanceof StandardAnnotationMetadata) {
              setBeanClass(((StandardAnnotationMetadata) metadata).
              getIntrospectedClass());
            }
            else {
              setBeanClassName(metadata.getClassName());
            }
            this.metadata = metadata;
          }
        
          /**
           * 
           * 基于一个带注解的类和该类上的工厂方法。,为给定的注释元数据创建一个
           新的AnnotatedGenericBeanDefinition,
           */
          public AnnotatedGenericBeanDefinition(AnnotationMetadata metadata,
           MethodMetadata factoryMethodMetadata) {
            this(metadata);
            Assert.notNull(factoryMethodMetadata, 
            "MethodMetadata must not be null");
            setFactoryMethodName(factoryMethodMetadata.getMethodName());
            this.factoryMethodMetadata = factoryMethodMetadata;
          }
        
        
          @Override
          public final AnnotationMetadata getMetadata() {
            return this.metadata;
          }
        
          @Override
          @Nullable
          public final MethodMetadata getFactoryMethodMetadata() {
            return this.factoryMethodMetadata;
          }
        
        }
        

二、扫描过程/收集过程(一)

   基本流程

 Spring单独使用类扫描器ClassPathBeanDefinitionScanner进行扫描处理

 源码上的注释:

 A bean definition scanner that detects bean candidates on the classpath,
 registering corresponding bean definitions with a  
 given registry ({@code BeanFactory}
 

 * {@link org.springframework.stereotype.Component @Component},
 * {@link org.springframework.stereotype.Repository @Repository},
 * {@link org.springframework.stereotype.Service @Service}, or
 * {@link org.springframework.stereotype.Controller @Controller} stereotype.
  • bean定义扫描器会在类的路径上检测以上注解,如果存在,就在给定的BeanFactory中注册相应的BeanDefinition,这里就又牵扯出BeanFactory,他是个很重要的接口,DefaultListableBeanFactory就实现了他,这个接口定义了获取bean以及bean的各种属性。

  • 主要的方法: Spring中所有do开头的方法,都是做实事的方法,所以必须看doScan() 位于ClassPathBeanDefinitionScanner类扫描器里

public int scan(String... basePackages) {
    //开始时候的bean 定义的数量
   int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
   
   //要开始做实事了,进行扫描
   doScan(basePackages);
   //添加一些后置处理器
   if (this.includeAnnotationConfig) {
      AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
   }
   //返回新增了多少个
   return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}

doScan详解 同样位于ClassPathBeanDefinitionScanner类扫描器里: Spring会扫描目标包和他的子包,doScan方法接受多个包名,通常这里只传递项目的根路径,这个方法其中最重要的还是findCandidateComponents,他会找到符合这个包路径的所有类,从中挑选出需要被管理的。

  • 1、开始时加载doScan源码:

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
   Assert.notEmpty(basePackages, "At least one base package must be specified");
   /**
    * 保存扫描到的BeanDefinition
    */
   Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
   /**
    * 遍历目标包名
    */
   for (String basePackage : basePackages) {
      /**
       * 根据包名找到带有指定注解的类的所有BeanDefinition对象
       */
      Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
      /**
       * 遍历BeanDefinition
       */
      for (BeanDefinition candidate : candidates) {
         ScopeMetadata scopeMetadata = this.scopeMetadataResolver.
           resolveScopeMetadata(candidate);
         candidate.setScope(scopeMetadata.getScopeName());
         String beanName = this.beanNameGenerator.generateBeanName(candidate,
          this.registry);

         if (candidate instanceof AbstractBeanDefinition) {
            postProcessBeanDefinition((AbstractBeanDefinition) candidate, 
               beanName);
         }
         /**
          * 根据其他注解设置BeanDefinition对应字段值
          */
         if (candidate instanceof AnnotatedBeanDefinition) {
            AnnotationConfigUtils.processCommonDefinitionAnnotations(
                                         (AnnotatedBeanDefinition) candidate);
         }
         /**
          * 验证这个bean,比如是否存在
          */
         if (checkCandidate(beanName, candidate)) {
            /**
             * 使用BeanDefinitionHolder包装BeanDefinition
             */
            BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder
                                                        (candidate, beanName);
            definitionHolder =
                  AnnotationConfigUtils.applyScopedProxyMode
                             (scopeMetadata, definitionHolder, this.registry);
            beanDefinitions.add(definitionHolder);
            /**
             * 向容器注册这个BeanDefinition
             */
            registerBeanDefinition(definitionHolder, this.registry);
         }
      }
   }
   return beanDefinitions;
}

2、doScan中的findCandidateComponents详解 findCandidateComponents中的核心是scanCandidateComponents,他首先会根据传递的包名,拼接成完整的通配符路径,比如包名是com.xxx,那么最后完整的通配路径就是classpath*:com/xxx/**/*.class,这个通配路径中也包含子包。

  • 源码:

     private Set<BeanDefinition> scanCandidateComponents(String basePackage) {
       Set<BeanDefinition> candidates = new LinkedHashSet<>();
       try {
          String packageSearchPath = ResourcePatternResolver.
                 CLASSPATH_ALL_URL_PREFIX +
                 resolveBasePackage(basePackage) + '/' + 
                 this.resourcePattern;
          /**
           * 扫描出所有符合指定通配符的所有class
           * 会收集所有符合这个通配路径的Resource对象,
           * Resource中包含这具体这个类的位置
           */
          Resource[] resources = getResourcePatternResolver().
                                           getResources(packageSearchPath);
    
          /**
           * 过滤不需要的class
           */
          for (Resource resource : resources) {
             if (traceEnabled) {
                logger.trace("Scanning " + resource);
             }
             try {
                /**
                 * 真正读取的Class的Metadata信息的是SimpleMetadataReader,
                   但是默认实现是CachingMetadataReaderFactory,只不过在他的基础
                 * 上增加了缓存功能
    
                 */
                MetadataReaderFactory **metadataReaderFactory** = 
                                                getMetadataReaderFactory();
                /**
                 * 取出访问权限、父类名、注解等信息,
                 * 最终返回成MetadataReader对象,
                 * MetadataReader就包含这这个类上有哪些注解。
                */
                MetadataReader **metadataReader** = 
                         metadataReaderFactory.getMetadataReader(resource);
                /**
                 * 如果这个类标有Component注解或者他的子类,
                   那么进行BeanDefinition注册
                 */
                if (**isCandidateComponent**(metadataReader)) {
                   ScannedGenericBeanDefinition sbd = 
                          new ScannedGenericBeanDefinition(metadataReader);
                   sbd.setSource(resource);
                   if (isCandidateComponent(sbd)) {
                      candidates.add(sbd);
                   }
                } 
             } catch (FileNotFoundException ex) {
    
             } catch (Throwable ex) {
                throw new BeanDefinitionStoreException(
                      "Failed to read candidate component class: " + 
                          resource, ex);
             }
          }
       } catch (IOException ex) {
          throw new BeanDefinitionStoreException("I/O failure during 
                                                   classpath scanning", ex);
       }
       return candidates;
    }     

    3、findCandidateComponents中的isCandidateComponent 判断有没有指定注解

    if (isCandidateComponent(metadataReader)) {
                   ScannedGenericBeanDefinition sbd = 
                          new ScannedGenericBeanDefinition(metadataReader);
                   sbd.setSource(resource);
                   if (isCandidateComponent(sbd)) {
                      candidates.add(sbd);
                   }
                } 
             } catch (FileNotFoundException ex) {
    
             } catch (Throwable ex) {
                throw new BeanDefinitionStoreException(
                      "Failed to read candidate component class: " + 
                          resource, ex);
             }

    源码,用来判断有没有指定的注解:

    protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
       for (TypeFilter tf : this.excludeFilters) {
          if (tf.match(metadataReader, getMetadataReaderFactory())) {
             return false;
          }
       }
       /**
       includeFilters字段里保存的就是一些注解列表,
       在默认的时候里面含有Component、ManagedBean、Named这三个,
       所以,类上只要标有这三个注解,就可以让Spring管理,
       而@Service这些注解上都又标有Component注解,
       简单可以理解成Service继承Component,
       所以,标有@Service也可以让Spring管理,同样我们自定义一个注解,
       注解上加入@Component,同样可以。
       */
       for (TypeFilter tf : this.**includeFilters**) {
          if (tf.match(metadataReader, getMetadataReaderFactory())) {
             return isConditionMatch(metadataReader);
          }
       }
       return false;
    }

    4、doScan最后的方法返回说有的注解类 最后这个方法返回所有带有这些注解的类,在回到doScan,剩下的就是遍历上一步返回的结果,注册到容器里,除此之外,还有下面这段代码,首先这个条件是成立的,因为在扫描过程中,返回的是ScannedGenericBeanDefinition,而他是继承AnnotatedBeanDefinition

    if (candidate instanceof AnnotatedBeanDefinition) {
       AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
    }
    

    5、doScan的AnnotationConfigUtils调用processCommonDefinitionAnnotations加载其余的注解 其余注解如Primary用来设置当有众多相同的Bean中,优先使用@Primary注解的Bean。 所以下面代码,只是根据其他注解的值填充到BeanDefinition

    static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
       AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
       if (lazy != null) {
          abd.setLazyInit(lazy.getBoolean("value"));
       }
       else if (abd.getMetadata() != metadata) {
          lazy = attributesFor(abd.getMetadata(), Lazy.class);
          if (lazy != null) {
             abd.setLazyInit(lazy.getBoolean("value"));
          }
       }
       if (metadata.isAnnotated(Primary.class.getName())) {
          abd.setPrimary(true);
       }
       AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
       if (dependsOn != null) {
          abd.setDependsOn(dependsOn.getStringArray("value"));
       }
       AnnotationAttributes role = attributesFor(metadata, Role.class);
       if (role != null) {
          abd.setRole(role.getNumber("value").intValue());
       }
       AnnotationAttributes description = attributesFor(metadata, Description.class);
       if (description != null) {
          abd.setDescription(description.getString("value"));
       }
    }
    

    6、doScan的注册 封装成BeanDefinitionHolder,这个对象里面含有BeanDefinition,调用registerBeanDefinition添加到容器中,容器就是DefaultListableBeanFactory。

    registerBeanDefinition(definitionHolder, this.registry);

    DefaultListableBeanFactory关系图

     然后调用registerBeanDefinition方法,位于DefaultListableBeanFactory,把BeanDefinitionHolder对象添加到beanDefinitionMap中,这个过程中处理别名。

三、扫描过程/收集过程(二)二次收集

 1、从AnnotationConfigApplicationContext中的scan和refresh开始 ** scan是第一次收集的时候位于ClassPathBeanDefinitionScanner类扫描器** 下面是 AnnotationConfigApplicationContext的构造方法

public AnnotationConfigApplicationContext(String... basePackages) {
   this();
   scan(basePackages);
   refresh();
}

2、点击refresh方法进入AbstractApplicationContext中的refresh方法:

@Override
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) {
      StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
      /**
       * 不需要看
       */
      prepareRefresh();
      /**
       * 获取在本类的构造方法执行阶段实例化的DefaultListableBeanFactory,
                                  所有阶段都围绕这他
       */
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
      /**
       * 向ConfigurableListableBeanFactory中添加一些其他辅助类,如后处理器
       */
      prepareBeanFactory(beanFactory);
      try {
         /**
          * 这个方法用来扩展,这个过程没有子类重写他,不需要看
          */
         postProcessBeanFactory(beanFactory);
         StartupStep beanPostProcess = this.applicationStartup.
                              start("spring.context.beans.post-process")
         /**
          * 这里也实现了Bean的收集,主要会执行ConfigurationClassPostProcessor
          * 这里是个循环收集过程
          */
        ** invokeBeanFactoryPostProcessors(beanFactory);**
         /**
          * 收集所有BeanPostProcessors
          */
         registerBeanPostProcessors(beanFactory);
         beanPostProcess.end();
         initMessageSource();
         initApplicationEventMulticaster();
         onRefresh();
         registerListeners();
         //实例化剩余的Bean
         finishBeanFactoryInitialization(beanFactory);
         finishRefresh();
      } catch (BeansException ex) {
         if (logger.isWarnEnabled()) {
            logger.warn("Exception encountered during context 
                              initialization - " +
                                   "cancelling refresh attempt: " + ex);
         }
         // Destroy already created singletons to avoid dangling resources.
         destroyBeans();
         // Reset 'active' flag.
         cancelRefresh(ex);
         // Propagate exception to caller.
         throw ex;
      } finally {
         // Reset common introspection caches in Spring's core, since we
         // might not ever need metadata for singleton beans anymore...
         resetCommonCaches();
         contextRefresh.end();
      }
   }
}

(一)执行所有——invokeBeanFactoryPostProcessors(beanFactory); 他会调用所有实现了BeanDefinitionRegistryPostProcessor接口的类的postProcessBeanDefinitionRegistry()方法,其中最核心的一个实现类是ConfigurationClassPostProcessor,他可能会向容器添加新的bean,因为类中可能有@Import、@Bean这样的注解,负责这些注解的解析 。

  • 点击进入方法invokeBeanFactoryPostProcessors(beanFactory);(依旧位于AbstractApplicationContext

protected void invokeBeanFactoryPostProcessors( ConfigurableListableBeanFactory beanFactory) {
** //重点**
 ** *****PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(
                                    beanFactory, 
                                      this.getBeanFactoryPostProcessors());***
   if (beanFactory.getTempClassLoader() == null && 
                           beanFactory.containsBean("loadTimeWeaver")) {
         beanFactory.addBeanPostProcessor(
                           new LoadTimeWeaverAwareProcessor(beanFactory));
          beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(
                           beanFactory.getBeanClassLoader()));
        }

    }

重要的一句话:

**PostProcessorRegistrationDelegate**.
       invokeBeanFactoryPostProcessors(
                                     beanFactory, 
                                      this.getBeanFactoryPostProcessors());

1、从现阶段收集到的bean列表中找到实现了BeanDefinitionRegistryPostProcessor接口的bean,
并且还实现了PriorityOrdered接口(用来排序),
唯一一个符合这个条件的就是ConfigurationClassPostProcessor,
那么会调用getBean()实例化他,
实例化后调用postProcessBeanDefinitionRegistry进行新的bean收集。
  
2、收集过后,容器中可能会增加同样实现了BeanDefinitionRegistryPostProcessor接口的类,
那么Spring还要判断,如果这些类中有实现Ordered(用来排序)接口的,
那么做同样的事,实例化他,并调用postProcessBeanDefinitionRegistry。                                        

点击进入PostProcessorRegistrationDelegate类中,为了新的类可以添加进容器,所有Spring设置了一个while来不断收集

boolean reiterate = true;
while (reiterate) {
   reiterate = false;
   /**
    * 再次获取实现了BeanDefinitionRegistryPostProcessor接口的类,并且实例化
    * 这里也是个循环调用,直到所有bean中都收集完成了
    */
   postProcessorNames = beanFactory.getBeanNamesForType(
       BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
          if (!processedBeans.contains(ppName)) {
           currentRegistryProcessors.add(beanFactory.
            getBean(ppName, BeanDefinitionRegistryPostProcessor.
             class));
              processedBeans.add(ppName);
              reiterate = true;
      }
   }
   //排序
   sortPostProcessors(currentRegistryProcessors, beanFactory);
   registryProcessors.addAll(currentRegistryProcessors);
   //调用postProcessBeanDefinitionRegistry进行新的bean收集。
   invokeBeanDefinitionRegistryPostProcessors(
       currentRegistryProcessors, registry, 
         beanFactory.getApplicationStartup());
   currentRegistryProcessors.clear();
}

收集过后,会获取所有实现了BeanFactoryPostProcessor接口的类,会按照实现了PriorityOrdered、Ordered接口的优先级,依次调用他们的postProcessBeanFactory方法,这个方法位于BeanFactoryPostProcessor接口下,而BeanDefinitionRegistryPostProcessor又继承他。

@FunctionalInterface
public interface BeanFactoryPostProcessor {   void postProcess BeanFactory(
    //重点
    //参数ConfigurableListableBeanFactory唯一的
    //实现类是DefaultListableBeanFactory
    //DefaultListableBeanFactory是一个核心类,
    //同样也可以注册Bean
        **   ConfigurableListableBeanFactory** var1) 
            throws BeansException;
}
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
    //重点
      void **postProcessBeanDefinitionRegistry**(
        BeanDefinitionRegistry var1) throws BeansException;
}

(二)收集可能存在新Bean的类——点进去发现postProcessBeanDefinitionRegistry这个方法来源于ConfigurationClassPostProcessor

  • ConfigurationClassPostProcessor类的描述 ConfigurationClassPostProcessor是一个BeanFactory的后置处理器,因此它的主要功能是参与BeanFactory的建造,在这个类中,会解析加了@Configuration的配置类,还会解析@ComponentScan、@ComponentScans注解扫描的包,以及解析@Import等注解。 ConfigurationClassPostProcessor 实现了 BeanDefinitionRegistryPostProcessor 接口,而 BeanDefinitionRegistryPostProcessor 接口继承了 BeanFactoryPostProcessor 接口,所以 ConfigurationClassPostProcessor 中需要重写 postProcessBeanDefinitionRegistry() 方法和 postProcessBeanFactory() 方法。而ConfigurationClassPostProcessor类的作用就是通过这两个方法去实现的。

  • ConfigurationClassPostProcessor类的关系图

     ConfigurationClassPostProcessor的工作:

  •     1、遍历完现阶段的所有bean

    遍历现阶段容器中所有bean,检测这个bean类上是否标有Configuration、
    Component、ComponentScan、Import、ImportResource注解,
    标有的话,把这个bean放入一个集合中,
    如果没有的话,还会检测类中方法上是不是标有@Bean注解,
    有的话,同样放到这个集合中。
    
    还有个知识点是如果标有Configuration注解,
    并且proxyBeanMethods是true,那么未来会进行增强,
    也就是需要进行动态代理。
    
    

    2、然后解析遍历出来的内部类,然后进行处理。ConfigurationClassParser类进行解析

  •      1、判断是不是标有Component注解和Component的子注解,如果标有的话,会先处理他的内部类,如果内部类上同样标有@Component或者他的"子注解",那么这个类最终也会被Spring收录到容器,同样内部类中还有内部类,Spring做好了递归处理

    @Nullable
    protected final ConfigurationClassParser.SourceClass doProcessConfigurationClass(
     ConfigurationClass configClass, ConfigurationClassParser.SourceClass sourceClass, 
      Predicate<String> filter) throws IOException {
       if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
         this.processMemberClasses(configClass, sourceClass, filter);
            }

  • 2、收集属性,判断有没有PropertySources注解,有的话封装成PropertySource添加到上下文的environment中,PropertySource就保存着如application.properties文件中的值,最后用于依赖注入。

  • 3、扫描新路径,接着会处理ComponentScans、ComponentScan注解,Spring拿到里面的值后,会重新使用上一章的方法,进如doScan进行扫描,扫描后会把扫描到的新Bean在走一遍这些流程。

  • 4、处理Import 处理@Import注解,这部分还是比较多的,因为@Import中的class可能分为以下三种情况。

    • 1、实现了ImportSelector(先放入集合)

    • 2、实现了ImportBeanDefinitionRegistrar(暂时先实例化后放入到一个集合中,并不会调用其中任何方法,将来才会调用)

    •   3、独立类(先放入集合)

  • 新的bean名称就是他的完整路径,比如com.xxx.TestA,同样这个过程也是个递归收集过程

    5、获取带有@Bean注解的方法,将带有@Baen注解的方法封装成BeanMethod对象添加到集合中,在调用的时候把返回值放入到容器

    while(var18.hasNext()) {
        MethodMetadata methodMetadata = (MethodMetadata)var18.next();
        configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
                             }
    
        this.processInterfaces(configClass, sourceClass);
         if (sourceClass.getMetadata().hasSuperClass()) {
                String superclass = sourceClass.getMetadata().getSuperClassName();
           if (superclass != null && !superclass.startsWith("java") && 
                    !this.knownSuperclasses.containsKey(superclass)) {
                         this.knownSuperclasses.put(superclass, configClass);
                             return sourceClass.getSuperClass();
                }
            }

    6、收集接口中的default方法,如果这个类实现了某个接口,并且这个接口中有标有@Bean注解的的default方法,那么Spring还是要收集,并且这也是个递归过程,也就是接口继承接口的时候,会一头钻到底

    6、收集接口中的default方法,如果这个类实现了某个接口,并且这个接口中有标有@Bean注解的的default方法,那么Spring还是要收集,并且这也是个递归过程,也就是接口继承接口的时候,会一头钻到底

         源码

    /**
     * 获取接口上含有@Bean注解的方法
     */
    private void processInterfaces(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
      /**
       * 获取父级接口,遍历
       */
      for (SourceClass ifc : sourceClass.getInterfaces()) {
        /**
         * 获取接口中含有@Bean注解的方法元信息,然后遍历
         */
        Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(ifc);
        for (MethodMetadata methodMetadata : beanMethods) {
          /**
           * 只要此方法不是抽象类型的,则可以放入集合中待后续处理
           */
          if (!methodMetadata.isAbstract()) {
            // A default method or other concrete method on a Java 8+ interface...
            configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
          }
        }
        /**
         * 这里使用了递归,用来处理父级接口的父接口
         */
        processInterfaces(configClass, ifc);
      }
    }
    

    7、处理父类,当本类处理完后,可能他的父类中同样有上面这些需求,Spring也要处理。但这不是递归过程,是个while过程,doProcessConfigurationClass就是上面说的所有过程,返回值是他的父类,没有的话会返回null。

      ConfigurationClassParser.SourceClass sourceClass = this.asSourceClass(configClass, filter);
          do {
               sourceClass = this.doProcessConfigurationClass(configClass, sourceClass, filter);
                   } 
           while(sourceClass != null);
    
       this.configurationClasses.put(configClass, configClass);
            

3、向容器里面添加新的bean,ConfigurationClassParser类进行解析完成后,类中所有标有@Bean的方法还有其他信息都已经提取好后封装成了ConfigurationClass,下一步就是读取这些信息,把能放进容器的都放进容器。加载BeanDefinitions从ConfigurationClass,这里注意有s,表明一个配置类中可能有很多个BeanDefinition准备要添加到容器。

private void loadBeanDefinitionsForConfigurationClass(ConfigurationClass configClass, ConfigurationClassBeanDefinitionReader.TrackedConditionEvaluator trackedConditionEvaluator) {
  //判断是否跳过
  if (trackedConditionEvaluator.shouldSkip(configClass)) {
        String beanName = configClass.getBeanName();
     if (StringUtils.hasLength(beanName) && this.registry.containsBeanDefinition(beanName)) {
             this.registry.removeBeanDefinition(beanName);
            }
         this.importRegistry.removeImportingClass(configClass.getMetadata().getClassName());
        } else 
        {//判断这个类是不是被@Import导入的,
         // 如果是,那么会把他封装成BeanDefinitionHolder,添加到容器
            if (configClass.isImported()) {
                this.registerBeanDefinitionForImportedConfigurationClass(configClass);
            }

            Iterator var3 = configClass.getBeanMethods().iterator();
             //遍历这个类所有加了@Bean注解的方法
            while(var3.hasNext()) {
                BeanMethod beanMethod = (BeanMethod)var3.next();
                this.loadBeanDefinitionsForBeanMethod(beanMethod);
            }

            this.loadBeanDefinitionsFromImportedResources(configClass.getImportedResources());
             //调用ImportBeanDefinitionRegistrar
            this.loadBeanDefinitionsFromRegistrars(configClass.getImportBeanDefinitionRegistrars());
        }
    }

 @Import的class如果实现了ImportBeanDefinitionRegistrar接口,那么暂时会把他实例化后放入集合,未来会调用,那么这里就是。

private void loadBeanDefinitionsFromRegistrars(Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> registrars) {
   registrars.forEach((registrar, metadata) -> {
      registrar.registerBeanDefinitions(metadata, this.registry, this.importBeanNameGenerator);
        });
    }

(三)收集所有实现了BeanPostProcessor接口的类,在refresh()下面registerBeanPostProcessors()方法就是收集所有实现了BeanPostProcessor接口的类,也就是收集所有钩子,未来在创建对象前后会调用。

BeanPostProcessor接口源码
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;
    }
}
   在所有bean中获取实现了BeanPostProcessor接口的类

String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

(四)遍历所有Bean名称,判断这个Bean是否有实例化的资格,初始化—— finishBeanFactoryInitialization 这基本上是最后一步了,这里面会调用下面这段,注释的意思是实例化剩余的非懒加载的bean,为什么说剩余呢?因为在前面已经有一部分逻辑需要已经实例化过了,比如这个Bean实现了一个Spring必须要用的接口,在前面实例化了,懒加载的bean指的是当需要的时候才实例化。

// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值