Spring Boot版本2.2.6.RELEASE
代码:
@SpringBootApplication
public class HelloWorldMainApplication {
/**
* spring应用启动起来
* @param args
*/
public static void main(String[] args) {
SpringApplication.run(HelloWorldMainApplication.class, args);
}
}
@Controller
public class HelloController {
@GetMapping("/hello")
@ResponseBody
public String hello() {
return "Hello Spring Boot For Maven!";
}
}
进入主程序类
自动装配的主要启动类上的注解@SpringBootApplication
@SpringBootApplication部分源码
@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 { ... }
可知@SpringBootApplication注解是一个组合注解,它由三个重要的注解组成。
分别是:
@SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class), @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
@SpringBootConfiguration
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Configuration public @interface SpringBootConfiguration { @AliasFor(annotation = Configuration.class) boolean proxyBeanMethods() default true; }
和@Configuration的作用一致。
@Configuration:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Configuration { @AliasFor(annotation = Component.class) String value() default ""; boolean proxyBeanMethods() default true; }
@Configuration注解也是一个@Component,被注入到Spring容器中。
@EnableAutoConfiguration
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration"; Class<?>[] exclude() default {}; String[] excludeName() default {}; }
自动装配注解
其中@AutoConfigurationPackage就是自动配置的包,进入该注解。
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @Import(AutoConfigurationPackages.Registrar.class) public @interface AutoConfigurationPackage { }
该注解使用一个@Import注解注入了一个AutoConfigurationPackages.Registrar.class类,进入此类。
该类中有方法registerBeanDefinitions注册Bean信息,使用方法register注册方法传入一个meadata元信息,和Bean信息注册。打上断点,运行程序。
new PackageImport(metadata).getPackageName()
拿到一个包名。
debug程序

这个注解的含义就是将这个主配置类所在的包以及所有子包里面的所有组件都扫描进spring容器中。
所以如果Spring Boot应用没有扫描到组件,查看主配置类的位置,是否标注了@SpringBootApplication注解,项目结构是否正确。
3.@Import(AutoConfigurationImportSelector.class)
给容器中导入组件:导入哪些组件的选择器。进入源码:
该类中核心方法是selectImports。
导入选择器,返回一个String的数组。将所有需要导入的组件以全类名的方式返回,
这些组件就会被添加到容器中。
该类使用到了AutoConfigurationEntry一个Entry节点,该方法在这个方法下面。
该方法主要使用到一个configurations对象,并最终将其返回。
会给容器中导入非常多的自动配置类(xxxAutoConfiguration);这个就是给容器中导入这个场景需要的所有组件,并配置好这些组件。xxxAutoConfiguration就是关于什么什么的自动配置。例如aop的自动配置,AopAutoConfiguration。
有了这些自动配置类,免去了我们手动编写配置注入功能组件等的工作。
主要使用这个方法来获取这些Configurations。进入该方法。
SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
获取两个参数:第一个参数为:
EnableAutoConfiguration.class
第二个参数就是一共类加载器。
进入 SpringFactoriesLoader.loadFactoryNames()方法。
这个方法主要是通过类加载器获取到一个资源,FACTORIES_RESOURCE_LOCATION。
进入FACTORIES_RESOURCE_LOCATION。
得到FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories"
找到该文件。
所以List
找到这个文件。
位于spring-boot-autoconfiguration中。在spring-boot中是没有的。
可查看到该文件中的内容。
就是我们导入的自动配置类。
==Spring Boot在启动的时候从类路径下的META-INF/spring.factories中获取EnableAutoConfiguration指定的值,将这些值作为自动配置类导入容器中,自动配置类就生效,帮我们进行自动配置工作。==
例如:web相关的自动配置。
进入该类。
例如其中有视图解析器的自动配置。
以前我们需要自己配置的东西,自动配置类都帮我们配置好了。这些配置都在spring-boot-autoconfiguration这个jar包下面。
J2EE的整体整合解决方案和自动配置都在spring-boot-autoconfiguration-xxx.xx.jar这个jar包下。