Spring Boot 启动初探@SpringBootApplication秘密

首先Spring Boot为我们在JavaEE的开发提供了很大的便利,减少了我们使用Spring的时候对需要的组件整合相关的配置,Spring Boot帮我们做了很多的自动配置。要想用好这个Spring Boot我们就需要对它非常熟悉,这次我们就来了解一下启动类标记的@SpringBootApplication

演示环境

  • IntelliJ IDEA 2018.2.5 (Ultimate Edition)
  • JDK 1.8
  • Spring Boot 2.1.1.RELEASE
  • Maven 3.5.4

初始化一个Spring Boot项目

初始化项目的方式有很多,这里我就选用了使用IDEA来初始化项目,这样初始完项目后方便我们看源码,初始化Spring Boot项目的方式:

  • 动手能力强的,创建Maven工程手动引入spring-boot-starter-parent依赖以及其它依赖。
  • 使用Spring官方提供的Spring Initializr,初始化我们的Spring Boot项目。
  • 使用旗舰版的IDEA,来初始化项目。

初探Spring Boot项目的启动

在启动Spring Boot项目的时候,都会有一个被@SpringBootApplication标注的启动类。例如下面:

@SpringBootApplication
public class JeromeApplication {

    public static void main(String[] args) {
        SpringApplication.run(JeromeApplication.class, args);
    }
}

探究@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

进入@SpringBootConfiguration

我们使用工具进入到这个注解后,发现其实这个注解就只是被@Configuration标记了,也会作为组件在包扫描的时候注册到容器中。而@Configuration我们在项目中会经常用到,比如写一些定义配置的Bean。

@Configuration
public class JeromeConfiguration{
    @Bean
    public Entity entity(){
        return new Entity();
    }
}

在这里任何一个标注了@Bean的方法,其返回值将作为一个bean定义注册到Spring的IOC容器,方法名将默认成该bean定义的id。

进入@ComponentScan

其实@ComponentScan这个注解大家也是不会陌生的,@ComponentScan的功能其实就是自动扫描并加载符合条件的组件(比如@Component@Repository等)或者bean定义,将这些bean定义加载到Spring的IOC容器中。当然我们可以通过basePackages等属性来细粒度的指定@ComponentScan自动扫描的范围,如果不指定,则默认Spring框架实现会从声明@ComponentScan所在类的package进行扫描。

因为我们在使用Spring Boot的时候并没有指定扫描路径,所以我们的启动类需要和根目录同级

进入@EnableAutoConfiguration

把这个放到最后,也说明了这个注解的重要性。从这个注解的字面意思就不难看出,这个注解是用来激活自动配置的,我们进入看看到底做了什么。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
    ...
}

这里@EnableAutoConfiguration又是由两个注解组成,这里使用了@Import来完成条件装配:

  • @AutoConfigurationPackage
  • @Import(AutoConfigurationImportSelector.class)

了解@AutoConfigurationPackage

其中@AutoConfigurationPackage的作用就是加载我们项目中自定义的 一些组件,比如(@Controller@Service等),将这些组件注册到Spring的IOC容器。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(AutoConfigurationPackages.Registrar.class)
public @interface AutoConfigurationPackage {
}

我们进入到AutoConfigurationPackages.Registrar.class的源码中再124行会发现这个类:

	/**
	 * {@link ImportBeanDefinitionRegistrar} to store the base package from the importing
	 * configuration.
	 */
	static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

		@Override
		public void registerBeanDefinitions(AnnotationMetadata metadata,
				BeanDefinitionRegistry registry) {
			register(registry, new PackageImport(metadata).getPackageName());
		}
        
		...
	}

当我们在上面代码的第10行打个断点,以DEBUG的方式运行项目,当项目执行到我们打的断点的地方。就会发现new PackageImport(metadata).getPackageName()返回的是我们@SpringBootApplication标注的这个启动类的包路径,接下来将启动类(@SpringBootApplication标注的类)的所在包及下面所有子包里面的所有组件扫描到Spring容器中。

了解@Import(AutoConfigurationImportSelector.class)

到这里就可以看出@EnableAutoConfiguration借助了@ImportAutoConfigurationImportSelector.class来完成条件装配。帮助SpringBoot应用将所有符合条件的@Configuration配置都加载到当前应用容器中。

进入到AutoConfigurationImportSelector.class的源码中,我们能找到一个selectImports方法中调用getAutoConfigurationEntry方法:

	protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
			AnnotationAttributes attributes) {
		List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
				getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader());
		Assert.notEmpty(configurations,
				"No auto configuration classes found in META-INF/spring.factories. If you "
						+ "are using a custom packaging, make sure that file is correct.");
		return configurations;
	}

从这个方法中看出,使用了SpringFactoriesLoader的支持,而这个SpringFactoriesLoader类的主要功能就是从类路径下指定的配置文件META-INF/spring.factories加载配置。配置的key就是@EnableAutoConfiguration这个注解的全路径。在spring-boot-autoconfigure-2.1.1.RELEASE.jarMETA-INF/spring.factories文件中,我们能看到Spring Boot帮我们做好了很多的自动配置:

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
.......

然后我们在使用Spring Boot开发项目的时候,只需要引入spring-boot-starter-xxx,使用Spring Boot的默认配置就能完成我们的基本开发需求。

总结

通过我们上面的对Spring Boot应用启动的初探,发现Spring Boot默认的为我们做了好多的配置。通过EnableAutoConfiguration进行自动装配,降低了我们上手Spring框架的难度,简化了我们的开发,让我们更专注于业务的开发。

原文链接:Spring Boot 启动初探@SpringBootApplication秘密

转载于:https://my.oschina.net/JeromeZhu/blog/3005465

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值