zoukankan      html  css  js  c++  java
  • SpringBoot自动配置的实现原理

    SpringBoot自动配置的实现原理

     

    之前一直在用SpringBoot框架,一直感觉SpringBoot框架自动配置的功能很强大,但是并没有明白它是怎么实现自动配置的,现在有空研究了一下,大概明白了SpringBoot框架是怎么实现自动配置的功能,我们编写一个最简单的自动配置功能,大概的总结一下.

    一,配置属性类

    其实就是值对象注入的方式去配置一些Spring常用的配置,我们编写一个最简单的配置对象。

    复制代码
    @ConfigurationProperties(prefix = "hello")
    //@Component //如果这里添加了注解那么在自动配置类的时候就不用添加@enableConfigurationProperties(HelloProperties.class)注解.
    public class HelloProperties {
    
        private String msg="default";//现在我们在配置文件写hello.msg=world,因为简单就不再展示;如果那么默认为default.
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    }
    复制代码

    这是一个简单的属性值对象,那么相当于写死的字段就是SpringBoot为我们自动配置的配置,那么我们很多时候可以自己在application.properties中修改某些配置就是这样的道理,我们不设置就是默认的,设置了就是我们设置的属性。

    二,自动配置类

    上面已经构建了我们简单的属性对象,那么现在我们要通过属性对象得到相应的属性值将其注入到我们的Bean中,这些Bean也就是一些SpringBoot启动后为我们自动配置生成的Bean,当然SpringBoot优先使用我们配置的Bean这个功能是如何实现的,我们往下看一下就明白了。

    首先我们需要一个功能Bean,可以把这个Bean看做是SpringBoot框架启动后在容器里面生成的为我们服务的内置Bean,简单的写一个。

    复制代码
    //@Component   这里很重要,如果我们添加了这个注解那么,按照我们下面的设置SpringBoot会优先使用我们配置的这个Bean,这是符合SpringBoot框架优先使用自定义Bean的原则的。
    public class HelloService {
    
        private String msg = "service";//如果自动配置没有读入成功,那么为默认值
    
        public String say() {
            return "hello " + msg;
        }//为我们服务的方法
    
        public String getMsg() {
            return msg;
        }
    
        public void setMsg(String msg) {
            this.msg = msg;
        }
    }
    复制代码

    现在编写我们的自动配置类。

    复制代码
    @Configuration //配置类
    @EnableConfigurationProperties(HelloProperties.class)//这里就是前面说的,这个注解读入我们的配置对象类
    @ConditionalOnClass(HelloService.class)//当类路径存在这个类时才会加载这个配置类,否则跳过,这个很有用比如不同jar包间类依赖,依赖的类不存在直接跳过,不会报错
    public class HelloAutoConfiguration { @Autowired private HelloProperties helloProperties; @Bean @ConditionalOnMissingBean(HelloService.class)//这个配置就是SpringBoot可以优先使用自定义Bean的核心所在,如果没有我们的自定义Bean那么才会自动配置一个新的Bean public HelloService auto(){ HelloService helloService =new HelloService(); helloService.setMsg(helloProperties.getMsg()); return helloService; } }
    复制代码

    好了现在自动配置的类也写好了,我们可以启动一下SpringBoot应用,测试一下。

    三,测试自动配置

    复制代码
    @SpringBootApplication
    @RestController
    public class MyRun {
    
        @Autowired
        private HelloService helloService;
    
        @RequestMapping("/auto/home")
        public String home(){
            return helloService.say();
        }
    
        public static void main(String[] args) {
            SpringApplication.run(MyRun.class,args);
        }
    }
    复制代码

    ok ,运行后访问你会看到:

    hello world

    代表我们的自动配置功能成功。

    四,SpringBoot管理自动配置

    其实在很多时候我们的配置是在很多jar包里的,那么我们新的应用该怎么读入这些jar包里的配置文件呢,SpringBoot是这样管理的。

    最主要的注解就是@enableAutoConfiguration,而这个注解会导入一个EnableAutoConfigurationImportSelector的类,而这个类会去读取一个spring.factories下key为EnableAutoConfiguration全限定名对应值.

    复制代码
    # 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,
    org.springframework.boot.autoconfigure.MessageSourceAutoConfiguration,
    org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration,
    org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,
    org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,
    org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,
    org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,
    org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,
    org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,
    org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,
    org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,
    org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,
    org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,
    org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,
    org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,
    org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,
    org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,
    org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,
    org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,
    org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,
    org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,
    org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,
    org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,
    org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,
    org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,
    org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,
    org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,
    org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,
    org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,
    org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,
    org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,
    org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,
    org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,
    org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,
    org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,
    org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,
    org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,
    org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,
    org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,
    org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,
    org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,
    org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,
    org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,
    org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,
    org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,
    org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,
    org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,
    org.springframework.boot.autoconfigure.jms.hornetq.HornetQAutoConfiguration,
    org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,
    org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,
    org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,
    org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,
    org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,
    org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,
    org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,
    org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,
    org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration,
    org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,
    org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,
    org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,
    org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,
    org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,
    org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,
    org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,
    org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,
    org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,
    org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,
    org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,
    org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,
    org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration,
    org.springframework.boot.autoconfigure.social.FacebookAutoConfiguration,
    org.springframework.boot.autoconfigure.social.LinkedInAutoConfiguration,
    org.springframework.boot.autoconfigure.social.TwitterAutoConfiguration,
    org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,
    org.springframework.boot.autoconfigure.velocity.VelocityAutoConfiguration,
    org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,
    org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,
    org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,
    org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration,
    org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,
    org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,
    org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration,
    org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,
    org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,
    org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,
    org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration,
    org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,
    org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,
    org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,
    org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration
    复制代码

    所以如果需要我们可以在我们的resources目录下创建spring.factories下添加类似的配置即可。。

    ok,自动配置的原理差不多就这样,我现在了解的并不深入,还需要继续学习。 

    
    
    
     
    分类: 实习内容
     
    _______________________________________________________________________________________________________________________
    _______________________________________________________________________________________________________________________

    SpringBoot的运行原理之自动配置

    SpringBoot核心原理---自动配置 之创建自己的starter pom maven依赖包

     
     

    SpringBoot核心原理---自动配置 之创建自己的starter pom maven依赖包

     
    上一篇:SpringBoot 的运行原理之自动配置,了解SpringBoot自动配置的原理,在此基础上动手做一个自己的自动配置依赖包。
    本Demo源码:GitHub

    一、准备工作
    先创建Maven工程:

    目录结构:


    二、编码
    MistraService.java
    这个类就是要自动配置的Bean,条件就设为是否存在这个类的Bean,没有的话就创建。

    package com.mistra.mistrastarter;

    /**
    * Author: RoronoaZoro丶WangRui
    * Time: 2018/6/25/025
    * Describe: 是否进行自动配置的判断依据类,根据此类是否存在来决定是否创建这个类的Bean
    */
    public class MistraService {

    private String name;

    public String sayYourName(){
    return "I'm " + name + "! ";
    }

    public String getName() {
    return name;
    }

    public void setName(String name) {
    this.name = name;
    }
    }
     


    MistraServiceProperties .java
    为MistraService提供配置参数值得类。name设有默认值,配置文件配置前缀是"mistra"—>“mistra.name”,当没有在配置文件配置时就取默认值。

    package com.mistra.mistrastarter;

    import org.springframework.boot.context.properties.ConfigurationProperties;

    /**
    * Author: RoronoaZoro丶WangRui
    * Time: 2018/6/25/025
    * Describe: 自动配置的类型安全的注入参数类
    * 通过application.properties配置mistra.name的值来设置参数,若不设置,默认为"RoronoaZoro丶小王瑞"
    */
    @ConfigurationProperties(prefix = "mistra")
    public class MistraServiceProperties {

    private static final String NAME = "RoronoaZoro丶小王瑞";

    private String name = NAME;

    public String getName() {
    return name;
    }

    public void setName(String name) {
    this.name = name;
    }
    }

    MistraServiceAutoConfiguration.java
    自动配置类。

    package com.mistra.mistrastarter;

    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;

    /**
    * Author: RoronoaZoro丶WangRui
    * Time: 2018/6/25/025
    * Describe: 自动配置类
    * 根据条件判断是否要自动配置,创建Bean
    */
    @Configuration
    @EnableConfigurationProperties(MistraServiceProperties.class)
    @ConditionalOnClass(MistraService.class)//判断MistraService这个类在类路径中是否存在
    @ConditionalOnProperty(prefix = "mistra",value = "enabled",matchIfMissing = true)
    public class MistraServiceAutoConfiguration {

    @Autowired
    private MistraServiceProperties mistraServiceProperties;

    @Bean(name = "mistraService")
    @ConditionalOnMissingBean(MistraService.class)//当容器中没有这个Bean时(MistraService)就自动配置这个Bean,Bean的参数来自于MistraServiceProperties
    public MistraService mistraService(){
    MistraService mistraService = new MistraService();
    mistraService.setName(mistraServiceProperties.getName());
    return mistraService;
    }


    根据MistraServiceProperties提供的参数,判断MistraService这个类在类路径中是否存在,并且当容器中没有这个Bean(MistraService )时就自动配置创建这个Bean。
    spring.factories
    注册自动配置类。注意位置:src.main.resources.META-INF.spring.factories


    三、maven打包
    然后打包,并注册到本地maven仓库:
    CMD 切换到项目根目录下:mvn install


    然后在本地仓库就可以看见依赖包了:


    四、引用
    在别的项目引入依赖:

    <dependency>
    <groupId>com.mistra</groupId>
    <artifactId>mistrastarter</artifactId>
    <version>1.0-SNAPSHOT</version>
    </dependency>
     
    刷新Maven后可以在依赖里面找到自定义的包:

    SpringBoot启动类TestApplication.java

    @SpringBootApplication(scanBasePackages = "com.spring.boot.test")
    public class TestApplication {

    public static void main(String[] args) {
    System.out.println("☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆ RoronoaZoro丶小王瑞 ☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆");
    SpringApplication.run(TestApplication.class, args);
    }
     
    在配置文件配置debug:true,可以看到自动配置的情况,可以找到自己写的配置类:


    单元测试类StarterPomTest.java

    package com.spring.boot.test.starter;

    import com.mistra.mistrastarter.MistraService;
    import com.spring.boot.test.TestApplication;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

    /**
    * Author: RoronoaZoro丶WangRui
    * Time: 2018/6/26/026
    * Describe: 自定义starter测试
    */
    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringBootTest(classes = TestApplication.class)
    public class StarterPomTest {

    @Autowired
    private MistraService mistraService;

    @Test
    public void say() {
    System.out.println(mistraService.sayYourName());
    }
    }


    在配置文件中加入参数:

    mistra:
    name: 罗罗诺亚索隆
    1
    2
    如果不配置,就是取类中定义的默认值。
    运行say():


    至此,自定义的starter测试就完成了,也是对SpringBoot的核心自动配置的一次理解。
    总结:
    SpringBoot自动配置:@SpringBootApplication --> @EnableAutoConfiguration --> @Import({AutoConfigurationImportSelector.class}) -->AutoConfigurationImportSelector的selectImports()-getCandidateConfigurations() --> 调用SpringFactoriesLoader.loadFactoryNames()方法 --> 最后调用的loadSpringFactories()方法加载的“META-INF/spring.factories”文件

    本Demo源码:GitHub
    ———————————————— 
    原文链接:https://blog.csdn.net/Axela30W/article/details/80809311

     
  • 相关阅读:
    【转】python装饰器
    【原】python异步学习
    【转】Docker学习_本地/容器文件互传(5)
    【原】容灾/容错概念理解
    【原】thinkphp实现存储session至redis
    【原】thinkphp修改Redis操作类,支持选择数据库功能及添加其他方法
    高性能CSS(三)
    Free Code Camp社区对数百计编程学习者进行的统计希望告诉你什么?
    最精简24L01程序--发送
    金日
  • 原文地址:https://www.cnblogs.com/kelelipeng/p/12837904.html
Copyright © 2011-2022 走看看