Springboot的自动装配 @SpringBootApplication 在启动类中有@SpringBootApplication注解,点开@SpringBootApplication的源码我们发现 它是由多个注解组合成的一个注解,其中@SpringBootConfiguration也是个组合注解,表示该类为配置类 而@EnableAutoConfiguratio才是自动配置的核心注解
1 2 3 4 5 6 7 8 9 10 11 12 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), 		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public  @interface  SpringBootApplication {     } 
 
@EnableAutoConfiguratio 点开@EnableAutoConfiguration可以发现一个@Import注解,也就是说这里可以导入一个或多个配置类 接着在查看AutoConfigurationImportSelector.class
1 2 3 4 5 6 7 8 9 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public  @interface  EnableAutoConfiguration {      } 
 
AutoConfigurationImportSelector 可以发现他实现了一个DeferredImportSelector接口,而DeferredImportSelector接口继承了ImportSelector接口 这说明AutoConfigurationImportSelector是实现ImportSelector接口的类 也就是AutoConfigurationImportSelector可以通过selectImports方法返回多个配置类到@EnableAutoConfiguratio的@import注解中 在以下代码中可以看出返回值的数据源是通过getAutoConfigurationEntry方法获取的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public  class  AutoConfigurationImportSelector  implements  DeferredImportSelector , BeanClassLoaderAware,		ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {          @Override  	public  String[] selectImports(AnnotationMetadata annotationMetadata) { 		if  (!isEnabled(annotationMetadata)) { 			return  NO_IMPORTS; 		} 		AutoConfigurationEntry  autoConfigurationEntry  =  getAutoConfigurationEntry(annotationMetadata); 		return  StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); 	}      } 
 
点开getAutoConfigurationEntry方法 getAutoConfigurationEntry是AutoConfigurationImportSelector中的方法 点开getCandidateConfigurations方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 protected  AutoConfigurationEntry getAutoConfigurationEntry (AnnotationMetadata annotationMetadata)  {		if  (!isEnabled(annotationMetadata)) { 			return  EMPTY_ENTRY; 		} 		AnnotationAttributes  attributes  =  getAttributes(annotationMetadata); 		List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes); 		configurations = removeDuplicates(configurations); 		Set<String> exclusions = getExclusions(annotationMetadata, attributes); 		checkExcludedClasses(configurations, exclusions); 		configurations.removeAll(exclusions); 		configurations = getConfigurationClassFilter().filter(configurations); 		fireAutoConfigurationImportEvents(configurations, exclusions); 		return  new  AutoConfigurationEntry (configurations, exclusions); 	} 
 
getCandidateConfigurations方法 getCandidateConfigurations是AutoConfigurationImportSelector中的方法 我们可以发现META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports的路径 也就是说selectImports方法返回值中的数据是来自AutoConfiguration.imports这个文件
1 2 3 4 5 6 7 8 9 protected  List<String> getCandidateConfigurations (AnnotationMetadata metadata, AnnotationAttributes attributes)  {		List<String> configurations = new  ArrayList <>( 				SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader())); 		ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()).forEach(configurations::add); 		Assert.notEmpty(configurations, 				"No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "  						+ "are using a custom packaging, make sure that file is correct." ); 		return  configurations; 	} 
 
AutoConfiguration.imports 在AutoConfiguration.imports有许多自动配置类的全类名 我们拿DispatcherServletAutoConfiguration举例 DispatcherServletAutoConfiguration中通过注解可以发现他是个配置类,其中有一个注解是@ConditionalOnClass(DispatcherServlet.Class)也就是在当前环境中有DispatcherServlet的类该配置类生效 DispatcherServletAutoConfiguration中有个DispatcherServletConfiguration配置类,且该配置类中有一个dispatcherServlet方法,返回了一个dispatcherServlet类,并且该方法添加了@Bean从而生成了DispatcherServlet做到了自动配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) @AutoConfiguration(after = ServletWebServerFactoryAutoConfiguration.class) @ConditionalOnWebApplication(type = Type.SERVLET) @ConditionalOnClass(DispatcherServlet.class) public  class  DispatcherServletAutoConfiguration  {         @Configuration(proxyBeanMethods = false)  	@Conditional(DefaultDispatcherServletCondition.class)  	@ConditionalOnClass(ServletRegistration.class)  	@EnableConfigurationProperties(WebMvcProperties.class)  	protected  static  class  DispatcherServletConfiguration  { 		@Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)  		public  DispatcherServlet dispatcherServlet (WebMvcProperties webMvcProperties)  { 			DispatcherServlet  dispatcherServlet  =  new  DispatcherServlet (); 			dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest()); 			dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest()); 			dispatcherServlet.setThrowExceptionIfNoHandlerFound(webMvcProperties.isThrowExceptionIfNoHandlerFound()); 			dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents()); 			dispatcherServlet.setEnableLoggingRequestDetails(webMvcProperties.isLogRequestDetails()); 			return  dispatcherServlet; 		}          } } 
 
总结 
1.在主启动类上添加了SpringBootApplication注解,这个注解组合了EnableAutoConfiguration注解 2.EnableAutoConfiguration注解又组合了Import注解,导入了AutoConfigurationImportSelector类 3.实现selectImports方法,这个方法经过层层调用,最终会读取META-INF目录下的后缀名为Imports的文件,当然了,boot2.7以前的版本,读取的是spring.factories文件, 4.读取到全类名了之后,会解析注册条件,也就是@Conditional以及其衍生注解,把满足注册条件的Bean对象自动注入到Ioc容器中
自动装配的案例 准备一个jar包 
准备一个带@Bean的配置类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Configuration public  class  MyConfig  {    @Bean      @ConditionalOnClass(name="org.springframework.web.servlet.DispatcherServlet")      public  Teacher getTeacher () {         return  new  Teacher ();     }     @Bean      @ConditionalOnMissingBean(Teacher.class)      @ConfigurationProperties(prefix = "student")      public  Student getStudent () {         return  new  Student ();     } } 
 
准备一个自动配置类 1 2 3 4 5 6 @AutoConfiguration @Import(MyConfig.class) public  class  MyAutoConfig  {    public  MyAutoConfig () {     } } 
 
实体类 省略
将自动配置类的全类名添加到org.springframework.boot.autoconfigure.AutoConfiguration.imports中
打包成jar包 省略
将jar包保存到maven本地仓库 打开cmd输入 mvn install:install-file “-Dfile=C:\Users\23224\Desktop\demo16-0.0.1-SNAPSHOT.jar” “-DgroupId=demo16” “-DartifactId=reggie-demo16” “-Dversion=1.0” “-Dpackaging=jar”
导入依赖 1 2 3 4 5 <dependency >     <groupId > demo16</groupId >      <artifactId > reggie-demo16</artifactId >      <version > 1.0</version >  </dependency > 
 
在启动类中测试 1 2 3 4 5 6 7 8 @SpringBootApplication public  class  Demo15Application  {    public  static  void  main (String[] args)  {         ApplicationContext  run  =  SpringApplication.run(Demo15Application.class, args);         Teacher  bean  =  run.getBean(Teacher.class);         System.out.println(bean);     } }