Spring-AnnotationConfigApplicationContext

Hi.PrimaryC / 2024-08-23 / 原文

1. 简介

使用 AnnotationConfigApplicationContext 创建 Spring 应用上下文时,需要指定一个或多个配置类。,开发者可以直接在 Java 类中使用注解如 @Configuration、@Bean 等来声明和配置 Bean。

AnnotationConfigApplicationContext 属于 Spring 的 Java 配置支持模块,用于以纯 Java 注解的方式来替代 XML 配置文件来创建和管理 Spring 容器上下文。

ApplicationContext的三种加载应用上下文的方式:

  • AnnotationConfigApplicationContext

  • ClassPathXmlApplicationContext

  • FileSystemXmlApplicationContext

2. 构造方法

AnnotationConfigApplicationContext 共提供四个构造方法:

  • public AnnotationConfigApplicationContext()

    无参构造
    //就是初始化两个全局变量
    public AnnotationConfigApplicationContext() {
    	this.reader = new AnnotatedBeanDefinitionReader(this);
    	this.scanner = new ClassPathBeanDefinitionScanner(this);
    }
    
    	private static void test1(){
    		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    		context.register(TestBean.class, DogBean.class);
    		context.refresh();
    
    		TestBean bean = context.getBean(TestBean.class);
    		bean.helloSpring();
    	}
    

    无参构造,需要手动调用 register() 或者 scan() 和 refresh() 方法

  • public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory)

    以 beanFactory 为参数
        public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) {
    		super(beanFactory);
    		this.reader = new AnnotatedBeanDefinitionReader(this);
    		this.scanner = new ClassPathBeanDefinitionScanner(this);
    	}
    
    private static void test2(){
      	AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(new DefaultListableBeanFactory());
      	context.register(TestBean.class, DogBean.class);
      	context.refresh();
    
      	TestBean bean = context.getBean(TestBean.class);
      	bean.helloSpring();
    }
    

    相比无参构造,多了一个 super(beanFactory),看看 super(beanFactory) 做了什么事情:

    GenericApplicationContext.super()
    public GenericApplicationContext() {
      	this.beanFactory = new DefaultListableBeanFactory();
      }
    
      /**
       * Create a new GenericApplicationContext with the given DefaultListableBeanFactory.
       * @param beanFactory the DefaultListableBeanFactory instance to use for this context
       * @see #registerBeanDefinition
       * @see #refresh
       */
      public GenericApplicationContext(DefaultListableBeanFactory beanFactory) {
      	Assert.notNull(beanFactory, "BeanFactory must not be null");
      	this.beanFactory = beanFactory;
      }
    

    可以发现,是在父类将 this.beanFactory 赋值,不用这个构造就是直接 new 一个默认的。

  • public AnnotationConfigApplicationContext(Class<?>... componentClasses)

    以多个 class 为参数
    public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
      	this();
      	register(componentClasses);
      	refresh();
      }
    
    private static void test3(){
      	ApplicationContext context = new AnnotationConfigApplicationContext(TestBean.class, DogBean.class);
    
      	TestBean bean = context.getBean(TestBean.class);
      	bean.helloSpring();
    
      	DogBean dog = context.getBean(DogBean.class);
      	dog.say();
    }
    

    相当于无参构造 + register() + refresh(),这里参数 TestBean,可以是普通的 pojo 类,无需有 @Component 注解

  • public AnnotationConfigApplicationContext(String... basePackages)

    以多个包路径为参数
    public AnnotationConfigApplicationContext(String... basePackages) {
    		this();
    		scan(basePackages);
    		refresh();
    	}
    
    private static void test4(){
      	ApplicationContext context = new AnnotationConfigApplicationContext("org.springframework.component");
    
      	TestBean bean = context.getBean(TestBean.class);
      	bean.helloSpring();
    
      	DogBean dog = context.getBean(DogBean.class);
      	dog.say();
    }
    

    相当于无参构造 + scan() + refresh()

3. 过程解析

通过对构造方法的解析,可以确定有以下几个过程:

    1. super(beanFactory) 父类的构造方法
    1. new AnnotationConfigApplicationContext() 初始化容器
    1. register() todo 注册 benn 类
    1. scan() 扫描类路径
    1. refresh() 刷新容器

1. 父类构造方法

执行子类构造方法时,会先执行父类构造方法,也就是this()方法的执行会先去执行父类的构造方法,那么就先从父类构造方法看起

AnnotationConfigApplicationContext继承自GenericApplicationContext

public GenericApplicationContext() {
	/**
	 * 初始化一个工厂类,用于创建bean对象
	 * @reviewer wangcongming
	 */
	this.beanFactory = new DefaultListableBeanFactory();
}

public GenericApplicationContext(DefaultListableBeanFactory beanFactory) {
	Assert.notNull(beanFactory, "BeanFactory must not be null");
    //直接赋值工厂类
	this.beanFactory = beanFactory;
}

初始化了一个工厂类 DefaultListableBeanFactory,几个重要属性:

/**
 * 用于排序
 * @reviewer wangcongming
 */
@Nullable
private Comparator<Object> dependencyComparator;
 
/**
 * 自动注入解析器
 * @reviewer wangcongming
 */
private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver();
 
/**
 * 依赖
 * @reviewer wangcongming
 */
private final Map<Class<?>, Object> resolvableDependencies = new ConcurrentHashMap<>(16);
 
/**
 * spring核心,用于存放BeanDefinition(描述bean的类)
 * @reviewer wangcongming
 */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
 
/**
 * class与bean name映射关系
 * @reviewer wangcongming
 */
private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<>(64);
 
/**
 * 单例 class与bean name映射关系
 * @reviewer wangcongming
 */
private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<>(64);
 
/**
 * 用于存放bean name
 * @reviewer wangcongming
 */
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);

总之这一步的作用就是,AnnotationConfigApplicationContext 示例持有一个 DefaultListableBeanFactory 实例

2. AnnotationConfigApplicationContext 初始行

public AnnotationConfigApplicationContext() {
	/**
	 * 初始化一个AnnotatedBeanDefinition读取器,用于读取被注解标注的bean,
	 * 读取的信息存放入AnnotatedBeanDefinition
	 */
	this.reader = new AnnotatedBeanDefinitionReader(this);
	/**
	 * 初始化一个扫描器,用于扫描类或者包下的所有类,将被注解标注的bean生成对应的AnnotatedBeanDefinition
	 */
	 this.scanner = new ClassPathBeanDefinitionScanner(this);
}

无参构造中只做了两件事,初始化一个读取器(AnnotatedBeanDefinitionReader)和一个扫描器(ClassPathBeanDefinitionScanner)

    1. 先看 new AnnotatedBeanDefinitionReader(this)

    AnnotatedBeanDefinitionReader 类构造方法

    public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
    	this(registry, getOrCreateEnvironment(registry));
    }
    
    public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
    	Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    	Assert.notNull(environment, "Environment must not be null");
        //设置属性
    	this.registry = registry;
    	this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
    	AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }
    

    AnnotationConfigUtils.registerAnnotationConfigProcessors() 最终调用:

    public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
      		BeanDefinitionRegistry registry, @Nullable Object source) {
    
      	/**
      	 * 从registry中获取DefaultListableBeanFactory
      	 * */
      	DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
      	if (beanFactory != null) {
      		/**
      		 * 初始化一个比较器
      		 * */
      		if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
      			beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
      		}
      		/**
      		 * 像是 Autowire 解析器
      		 * */
      		if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
      			beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
      		}
      	}
    
      	/**
      	 * 创建一个 Set,用于加入一些spring自己定义的bean,以便于后面初始化使用,完成一些功能。实际上在这里是没用用的,因为这个 set 返回了之后没用
      	 */
      	Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
    
      	/**
      	 * ConfigurationClassPostProcessor用于读取配置类的
      	 */
      	if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
    
      		//创建一个 BeanDefinition
      		RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
      		def.setSource(source);
    
      		/**
      		 * new AnnotationConfigApplicationContext 这个分析中,其实用 registerPostProcessor 起作用的,beanDefs.add 没用
      		 */
      		beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
      	}
    
      	/**
      	 * AutowiredAnnotationBeanPostProcessor 用于处理依赖注入的
      	 * */
      	if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
      		RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
      		def.setSource(source);
      		beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
      	}
    
      	/**
      	 * 用于处理JSR-250支持
      	 * */
      	// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
      	if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
      		RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
      		def.setSource(source);
      		beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
      	}
    
      	/**
      	 * 用于支持jpa的
      	 * */
      	// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
      	if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
      		RootBeanDefinition def = new RootBeanDefinition();
      		try {
      			def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
      					AnnotationConfigUtils.class.getClassLoader()));
      		}
      		catch (ClassNotFoundException ex) {
      			throw new IllegalStateException(
      					"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
      		}
      		def.setSource(source);
      		beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
      	}
    
      	/**
      	 * 像是事件监听器
      	 * */
      	if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
      		RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
      		def.setSource(source);
      		beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
      	}
      	/**
      	 * 像是事件监听工厂
      	 * */
      	if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
      		RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
      		def.setSource(source);
      		beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
      	}
    
      	return beanDefs;
      }
    

    (1)初始化 DependencyComparator 比较器
    (2)应该是 Autowired 解析器
    (3)注册了一些默认的 BeanDefinition 到 AnnotationConfigApplicationContext 持有的 registry 中。

    AnnotationConfigUtils.registerPostProcessor() 注册 beanDefinition

    private static BeanDefinitionHolder registerPostProcessor(
      	BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {
    
      	definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    
      	//通过 AnnotationConfigApplicationContext 的方法注入 beanDefinition
      	registry.registerBeanDefinition(beanName, definition);
      	return new BeanDefinitionHolder(definition, beanName);
    }
    

    DefaultListableBeanFactory.registerBeanDefinition():将 beanDefinition 注册到自己的 beanDefinitionMap 中

    /**
       * this.beanDefinitionMap.put(beanName, beanDefinition)
       * this.beanDefinitionNames.add(beanName)
       * */
      @Override
      public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
      		throws BeanDefinitionStoreException {
    
      	Assert.hasText(beanName, "Bean name must not be empty");
      	Assert.notNull(beanDefinition, "BeanDefinition must not be null");
    
      	if (beanDefinition instanceof AbstractBeanDefinition) {
      		try {
      			((AbstractBeanDefinition) beanDefinition).validate();
      		}
      		catch (BeanDefinitionValidationException ex) {
      			throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
      					"Validation of bean definition failed", ex);
      		}
      	}
    
      	BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
      	if (existingDefinition != null) {
      		if (!isAllowBeanDefinitionOverriding()) {
      			throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
      		}
      		else if (existingDefinition.getRole() < beanDefinition.getRole()) {
      			// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
      			if (logger.isInfoEnabled()) {
      				logger.info("Overriding user-defined bean definition for bean '" + beanName +
      						"' with a framework-generated bean definition: replacing [" +
      						existingDefinition + "] with [" + beanDefinition + "]");
      			}
      		}
      		else if (!beanDefinition.equals(existingDefinition)) {
      			if (logger.isDebugEnabled()) {
      				logger.debug("Overriding bean definition for bean '" + beanName +
      						"' with a different definition: replacing [" + existingDefinition +
      						"] with [" + beanDefinition + "]");
      			}
      		}
      		else {
      			if (logger.isTraceEnabled()) {
      				logger.trace("Overriding bean definition for bean '" + beanName +
      						"' with an equivalent definition: replacing [" + existingDefinition +
      						"] with [" + beanDefinition + "]");
      			}
      		}
      		this.beanDefinitionMap.put(beanName, beanDefinition);
      	}
      	else {
      		if (hasBeanCreationStarted()) {
      			// Cannot modify startup-time collection elements anymore (for stable iteration)
      			synchronized (this.beanDefinitionMap) {
      				this.beanDefinitionMap.put(beanName, beanDefinition);
      				List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
      				updatedDefinitions.addAll(this.beanDefinitionNames);
      				updatedDefinitions.add(beanName);
      				this.beanDefinitionNames = updatedDefinitions;
      				removeManualSingletonName(beanName);
      			}
      		}
      		else {
      			// Still in startup registration phase
      			this.beanDefinitionMap.put(beanName, beanDefinition);
      			this.beanDefinitionNames.add(beanName);
      			removeManualSingletonName(beanName);
      		}
      		this.frozenBeanDefinitionNames = null;
      	}
    
      	if (existingDefinition != null || containsSingleton(beanName)) {
      		resetBeanDefinition(beanName);
      	}
      	else if (isConfigurationFrozen()) {
      		clearByTypeCache();
      	}
      }
    

    1. 再看 new ClassPathBeanDefinitionScanner(this)