Spring Boot 启动过程分析(一)

1. Spring Boot 入口——main方法

@SpringBootApplication public class Application { public static void main(String[] args) throws Exception { SpringApplication.run(Application.class, args); } } 

从上面代码可以看出,Annotation定义(@SpringBootApplication)和类定义(SpringApplication.run)最为耀眼,所以分析 Spring Boot 启动过程,我们就从这两位开始。

2. 核心注解

2.1 @SpringBootApplication

@SpringBootApplication 是最常用也几乎是必用的注解,源码如下:

/** * Indicates a {@link Configuration configuration} class that declares one or more * {@link Bean @Bean} methods and also triggers {@link EnableAutoConfiguration * auto-configuration} and {@link ComponentScan component scanning}. This is a convenience * annotation that is equivalent to declaring {@code @Configuration}, * {@code @EnableAutoConfiguration} and {@code @ComponentScan}. * 标示一个声明有一个或多个的@Bean方法的Configuration类并且触发自动配置(EnableAutoConfiguration) * 和组建扫描(ComponentScan)。 * 这是一个相当于@Configuration@EnableAutoConfiguration@ComponentScan 三合一的组合注解。 */ @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 { @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "exclude") Class<?>[] exclude() default {}; @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "excludeName") String[] excludeName() default {}; @AliasFor(annotation = ComponentScan.class, attribute = "basePackages") String[] scanBasePackages() default {}; @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses") Class<?>[] scanBasePackageClasses() default {}; } 

从源码声明可以看出,@SpringBootApplication相当于 @SpringBootConfiguration + @EnableAutoConfiguration + @ComponentScan ,因此我们直接拆开来分析。

2.2 @SpringBootConfiguration

@SpringBootConfiguration 是继承自Spring的 @Configuration 注解,@SpringBootConfiguration 作用相当于 @Configuration

@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Configuration public @interface SpringBootConfiguration { } 

spring 3.0中增加了@Configuration,@Bean。可基于JavaConfig形式对 Spring 容器中的bean进行更直观的配置。SpringBoot推荐使用基于JavaConfig的配置形式。

基于xml配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd" default-lazy-init="true">
    <bean id="mockService" class="..MockServiceImpl">
    ...
    </bean>
</beans>

基于JavaConfig配置:

@Configuration public class MockConfiguration{ @Bean public MockService mockService(){ return new MockServiceImpl(); } } 

总结,@Configuration相当于一个spring的xml文件,配合@Bean注解,可以在里面配置需要Spring容器管理的bean。

2.3 @ComponentScan

@ComponentScan源码:

@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @Repeatable(ComponentScans.class) public @interface ComponentScan { /** * 对应的包扫描路径 可以是单个路径,也可以是扫描的路径数组 * @return */ @AliasFor("basePackages") String[] value() default {}; /** * 和value一样是对应的包扫描路径 可以是单个路径,也可以是扫描的路径数组 * @return */ @AliasFor("value") String[] basePackages() default {}; /** * 指定具体的扫描类 * @return */ Class<?>[] basePackageClasses() default {}; /** * 对应的bean名称的生成器 默认的是BeanNameGenerator * @return */ Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class; /** * 处理检测到的bean的scope范围 */ Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class; /** * 是否为检测到的组件生成代理 */ ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT; /** * 控制符合组件检测条件的类文件 默认是包扫描下的 * @return */ String resourcePattern() default ClassPathScanningCandidateComponentProvider.DEFAULT_RESOURCE_PATTERN; /** * 是否对带有@Component @Repository @Service @Controller注解的类开启检测,默认是开启的 * @return */ boolean useDefaultFilters() default true; /** * 指定某些定义Filter满足条件的组件 * @return */ Filter[] includeFilters() default {}; /** * 排除某些过来器扫描到的类 * @return */ Filter[] excludeFilters() default {}; /** * 扫描到的类是都开启懒加载 ,默认是不开启的 * @return */ boolean lazyInit() default false; } 

基于xml配置:

<context:component-scan base-package="com.youzan" use-default-filters="false">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

基于JavaConfig配置:

@Configuration @ComponentScan(value = "com.youzan", excludeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class}) }) public class ScanConfig { } 

总结:@ComponentScan通常与@Configuration一起配合使用,相当于xml里面的<context:component-scan>,用来告诉Spring需要扫描哪些包或类。如果不设值的话默认扫描@ComponentScan注解所在类的同级类和同级目录下的所有类,所以对于一个Spring Boot项目,一般会把入口类放在顶层目录中,这样就能够保证源码目录下的所有类都能够被扫描到。

2.4 @EnableAutoConfiguration

    原文作者:Spring Boot
    原文地址: https://blog.csdn.net/zhang_yinan/article/details/80743585
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞