美文网首页Java
Spring-Boot 自动配置

Spring-Boot 自动配置

作者: ironf | 来源:发表于2020-03-15 20:47 被阅读0次

@[toc]

Spring-Boot 自动配置

1.1~1.4为Spring-Boot自动配置源码分析,包含了自定义启动类,1.5为个人理解

1.1继承Spring-Boot 父工程依赖

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.5.RELEASE</version>
</parent>

父工程作用:版本控制和依赖管理,保证所用依赖是最优选

1.2启动器(web启动器为例)

1.引入web启动器
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

    spring-boot-starter-web:spring-boot-starter
                           web模块正常运行依赖的模块:DispatcherServlet、内置tomcat容器等等
                           (tomcat、json、spring-web、spring-webmvc等依赖)
    spring-boot-starter:springboot的基础依赖,基本所有的启动器都依赖于spring-boot-starter。
                       其依赖内容包括自动配置,日志,注解,spring核心,yaml等。
2.导入了相应的starter后,springboot就会自动配置其运行组件
3.启动器定义规则:
    官方:spring-boot-starter-xxx
    其他:Xxx-spring-boot-starter eg:mybatis-spring-boot-starter

1.3自定义启动器(redis为例)

1 . 某些组件官方未定义,需要我们自己定义启动器;
    redis为例,导入redis坐标时,SpringBoot自动创建Jedis的Bean
2.实现步骤
    ① 创建 redis-spring-boot-autoconfigure 模块
         创建RedisProperties配置文件参数绑定类 
         创建RedisAutoConfiguration自动配置类          
    ③ 在 redis-spring-boot-autoconfigure 模块中初始化 Jedis 的 Bean。
        并定义META-INF/spring.factories 文件
            org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
            com.itheima.redis.config.RedisAutoConfiguration
    ② 创建 redis-spring-boot-starter 模块,依赖 redis-spring-boot-autoconfigure的模块
    ④ 在测试模块中引入自定义的 redis-starter 依赖,测试获取 Jedis 的Bean,操作 redis。
理解:自定义启动器,就是自定义一个工程创建配置模块引入自己所需的组件及其默认配置,
     参考其他启动类在resources目录下创建META-INF文件夹并创建spring.factories等;
     然后在定义一个模块引入配置模块用于作为启动器。

1.4@SpringBootApplication

1.标记当前是一个启动引导类,是springboot应用的入口。
2.本身是一个组合注解。
    @SpringBootConfiguration  //表示该注解是一个配置类注解,并且自己是容器中的一个组件
    @EnableAutoConfiguration    //开启自动配置
    @ComponentScan(excludeFilters = {  //包扫描器,excludeFilters:不包括以下过滤注解
            @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
            @Filter(type = FilterType.CUSTOM,
                    classes = AutoConfigurationExcludeFilter.class) })
    public @interface SpringBootApplication {
        //...............
    }
@SpringBootConfiguration
    @Configuration
        @Component
@EnableAutoConfiguration
    @AutoConfigurationPackage
        @Import({Registrar.class})
            AutoConfigurationPackages.register
                getPackageName()
                //包名:Spring容器需要去扫描能够识别的注解。其实就是启动引导类所在的包及其子包
                
3.SpringApplication.run(Application.class, args);  
    ① 返回一个spring容器
    ② 创建SpringApplication对象
    ③ 运行run方法
     
return run(new Class<?>[] { primarySource }, args); 
return new SpringApplication(primarySources).run(args);  
//创建SpringApplication对象
    //判断是否为web容器
    this.webApplicationType = WebApplicationType.deduceFromClasspath();

    //从类路径下找到META‐INF/spring.factories配置的所有ApplicationContextInitializer;
    //然后封装成一个Map,转成Set,遍历Set,通过反射创建对象,赋值给SpringApplication的initializers属性
    setInitializers((Collection)getSpringFactoriesInstances(ApplicationContextInitializer.class));

    //从类路径下找到META‐INF/spring.factories配置的所有ApplicationListener;
    //然后封装成一个Map,转成Set,遍历Set,通过反射创建对象,赋值给SpringApplication的listeners属性
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));

    //从多个配置类中找到有main方法的主配置类,即启动引导类类
    this.mainApplicationClass = deduceMainApplicationClass();   

    ========================================================================================
        
//运行run方法   
    public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        //开始计时
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
        configureHeadlessProperty();
        //从类路径下META‐INF/spring.factories中获取SpringApplicationRunListeners,
        //反射创建对象,并回调start方法;
        SpringApplicationRunListeners listeners = getRunListeners(args);
        listeners.starting();
        
        try {
            //准备命令行参数,就是传入的args
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            
            //准备环境,完成后,回调listener的environmentPrepared方法。
            ConfigurableEnvironment environment = 
                prepareEnvironment(listeners, applicationArguments);
            configureIgnoreBeanInfo(environment);
            
            //打印SpringBoot的logo:可替换
            Banner printedBanner = printBanner(environment);
            
            //创建Spring容器,通过判断,决定是web的Spring容器还是普通的Spring容器
            context = createApplicationContext();
            
            //处理异常的,学习一下
            exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
                    new Class[] { ConfigurableApplicationContext.class }, context);
            
            //准备上下文环境
            prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            
            //刷新容器,加载所有的组件【因为是web环境,会启动tomcat】
            refreshContext(context);
            afterRefresh(context, applicationArguments);
            
            //停止计时
            stopWatch.stop();
            if (this.logStartupInfo) {
                new StartupInfoLogger(this.mainApplicationClass).
                    logStarted(getApplicationLog(), stopWatch);
            }
            //回调所有的SpringApplicationRunListener的started();
            listeners.started(context);
            
            //从ioc容器中获取所有的ApplicationRunner和CommandLineRunner进行回调
            //【ApplicationRunner先回调,CommandLineRunner再回调】,可在此进行缓存预热
            callRunners(context, applicationArguments);
        }catch (Throwable ex) {
            handleRunFailure(context, ex, exceptionReporters, listeners);
            throw new IllegalStateException(ex);
        }
        try {
            listeners.running(context);
        }catch (Throwable ex) {
            handleRunFailure(context, ex, exceptionReporters, null);
            throw new IllegalStateException(ex);
        }
        return context;
    }

1.5自动配置

1.Spring-Boot是一个Spring启动框架;
2.有一个全局配置文件:application.properties或application.yml:
    各种属性都可以在这个文件中进行配置:server.port、logging.level等;
3.自动配置实现依赖于@SpringBootApplication注解:
    1.其中的关键功能由@Import提供,其导入的AutoConfigurationImportSelector中selectImports()方法通过     2.SpringFactoriesLoader.loadFactoryNames()扫描所有具有META-INF/spring.factories的jar包,将所有自动
      配置类加载到Spring容器中;
        1.spring.factories文件是一组一组的key=value的形式,
            其中一个key是EnableAutoConfiguration类的全类名,而它的value是一个xxxxAutoConfiguration的类
                名的列表;
            每一个XxxxAutoConfiguration自动配置类都是在某些条件之下才会生效的:
                @ConditionalOnBean:当容器里有指定的bean的条件下。
                @ConditionalOnMissingBean:当容器里不存在指定bean的条件下。
                @ConditionalOnClass:当类路径下有指定类的条件下。
                @ConditionalOnMissingClass:当类路径下不存在指定类的条件下。
                @ConditionalOnProperty:指定的属性是否有指定的值,比如                      
                    @ConditionalOnProperties(prefix=”xxx.xxx”, value=”enable”, matchIfMissing=true),
                    代表当xxx.xxx为enable时条件的布尔值为true,如果没有设置的情况下也为true。
在这里插入图片描述
配置类
    可以在全局配置文件中配置哪些属性的类就是这些XxxxProperties类,
    它与配置文件中定义的prefix关键字开头的一组属性是唯一对应的,自定义的时候prefix属性一定要有
        server.port等,通过@ConfigurationProperties注解,
        绑定到对应的XxxxProperties配置实体类上封装为一个bean,
        然后再通过@EnableConfigurationProperties注解导入到Spring容器中

相关文章

网友评论

    本文标题:Spring-Boot 自动配置

    本文链接:https://www.haomeiwen.com/subject/eapbehtx.html