Spring boot web 应用 Bean介绍 : AutoConfigurationPackages

概述

Storing auto-configuration packages for reference later (e.g. by JPA entity scanner).
保存自动配置类以供之后的使用,比如给JPA entity扫描器用来扫描开发人员通过注解@Entity定义的entity类。
具体来讲,是注册如下bean定义到容器 :

  • bean名称 : org.springframework.boot.autoconfigure.AutoConfigurationPackages
  • bean类 : AutoConfigurationPackages$BasePackages
  • bean 角色 : 基础设施
  • bean实例构造函数第一个参数 : 被使用类所在包名 (比如@SpringBootApplication注解所在类的包名)

Bean的注册主要是由如下在应用程序入口类上的注解@SpringBootApplication引入的 :

@SpringBootApplication
  => @EnableAutoConfiguration
    =>  @AutoConfigurationPackage
     => @Import(AutoConfigurationPackages.Registrar.class)

源代码分析

1. 注册时机

Bean的注册发生在Spring boot应用的启动过程中的如下位置 :

SpringApplication.run()
  => refreshContext()
    => EmbeddedWebApplicationContext.refresh()
      => AbstractApplicationContext.invokeBeanFactoryPostProcessors()
        => PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()
          => ConfigurationClassPostProcessor.processConfigBeanDefinitions()
            => ConfigurationClassBeanDefinitionReader.loadBeanDefinitions()
              => loadBeanDefinitionsFromRegistrars()
                => AutoConfigurationPackages$Registrar.registerBeanDefinitions()
                  => AutoConfigurationPackages.register()

2. 注册逻辑

Bean的注册逻辑如下

	// AutoConfigurationPackages 类
	// 定义Bean的名称
	// org.springframework.boot.autoconfigure.AutoConfigurationPackages
	private static final String BEAN = AutoConfigurationPackages.class.getName();
	/**
	 * Programmatically registers the auto-configuration package names. 
	 * 程序方式注册自动配置包的名称。
	 * Subsequent invocations will add the given package names to those that have 
	 * already been registered. You can use this method to manually define the base 
	 * packages that will be used for a given BeanDefinitionRegistry. Generally it's 
	 * recommended that you don't call this method directly, but instead rely on the 
	 * default convention where the package name is set from your @EnableAutoConfiguration 
	 * configuration class or classes.
	 * @param registry the bean definition registry
	 * @param packageNames the package names to set , 缺省配置spring boot web应用的情况下,
	 * 这里是应用程序入口类所在的包
	 */
	public static void register(BeanDefinitionRegistry registry, String... packageNames) {
		// 这里参数 packageNames 缺省情况下就是一个字符串,是使用了注解
		// @SpringBootApplication 的 Spring Boot 应用程序入口类所在的包
		
		if (registry.containsBeanDefinition(BEAN)) {
			// 如果该bean已经注册,则将要注册包名称添加进去
			BeanDefinition beanDefinition = registry.getBeanDefinition(BEAN);
			ConstructorArgumentValues constructorArguments = beanDefinition
					.getConstructorArgumentValues();
			constructorArguments.addIndexedArgumentValue(0,
					addBasePackages(constructorArguments, packageNames));
		}
		else {
			//如果该bean尚未注册,则注册该bean,参数中提供的包名称会被设置到bean定义中去
			GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
			beanDefinition.setBeanClass(BasePackages.class);
			beanDefinition.getConstructorArgumentValues().addIndexedArgumentValue(0,
					packageNames);
			beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
			registry.registerBeanDefinition(BEAN, beanDefinition);
		}
	}

你可能感兴趣的:(Spring,Boot)