1. SpringBoot启动主程序类:

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

每次我们直接直接启动这个启动类,SpringBoot就启动成功了,并且帮我们配置了好多自动配置类。

其中最重要是 @SpringBootApplication 这个注解,我们点进去看一下。

2. 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 {

  三个比较重要的注解:

  • @SpringBootConfiguration : Spring Boot的配置类,标注在某个类上,表示这是一个Spring Boot的配置类

  • @EnableAutoConfiguration: 开启自动配置类,SpringBoot的精华所在。

  • @ComponentScan包扫描

  以前我们需要配置的东西,Spring Boot帮我们自动配置;@EnableAutoConfiguration告诉SpringBoot开启自动配置功能;这样自动配置才能生效;

3. EnableAutoConfiguration注解:

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

两个比较重要的注解:

  • @AutoConfigurationPackage:自动配置包

  • @Import: 导入自动配置的组件

4. AutoConfigurationPackage注解:

     static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

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

它其实是注册了一个Bean的定义。

new PackageImport(metadata).getPackageName(),它其实返回了当前主程序类的 同级以及子级     的包组件。

以上图为例,DemoApplication是和demo包同级,但是demo2这个类是DemoApplication的父级,和example包同级

也就是说,DemoApplication启动加载的Bean中,并不会加载demo2,这也就是为什么,我们要把DemoApplication放在项目的最高级中。

5. Import(AutoConfigurationImportSelector.class)注解:

可以从图中看出  AutoConfigurationImportSelector 继承了 DeferredImportSelector 继承了 ImportSelector

ImportSelector有一个方法为:selectImports。

 @Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List<String> configurations = getCandidateConfigurations(annotationMetadata,
attributes);
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
return StringUtils.toStringArray(configurations);
}

可以看到第九行,它其实是去加载  public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";外部文件。这个外部文件,有很多自动配置的类。如下:

6. 如何自定义自己的Bean:

我们以RedisTemplate为例:

 @Configuration
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration { @Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
} @Bean
@ConditionalOnMissingBean
public StringRedisTemplate stringRedisTemplate(
RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
} }

我们每次在Spring中使用Redis,都会使用到RedisTemplate这个工具类,但是他默认给我们返回的这个工具类,可能不是很符合我们的要求。比如:我们想要开启事务,或者想要改变它默认的序列化。

这时候该如何去做呢?

根据前面的分析,只要我们在容器中放入一个RedisTemplate Bean即可。

 @Bean("redisTemplate")
public RedisTemplate<Object, Object> myRedisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
// 修改序列化为Jackson
template.setDefaultSerializer(new GenericJackson2JsonRedisSerializer());
// 开启事务
template.setEnableTransactionSupport(true);
return template;
}

我们自己定义我们的RedisTemplate模板,修改序列化,开启事务等操作。

我们将我们自己的Bean加入到IoC容器中以后,他就会默认的覆盖掉原来的RedisTemplate,达到定制的效果。

我们在以Kafka为例:

假设我们想要消费的对象不是字符串,而是一个对象呢?比如Person对象,或者其他Object类呢?

1:我们首先去查找KafkaAutoConfiguration(xxxAutoConfiguration),看看是否有关于Serializer属性的配置

2:假设没有我们就去KafkaProperties文件查找是否有Serializer的配置

然后直接在application.properties修改默认序列化就好,连Bean都不需要自己重写。

类似这种,可以使用Spring提供的Json序列化,也可以自动使用第三方框架提供的序列化,比如Avro, Protobuff等

 spring.kafka.producer.key-serializer=org.springframework.kafka.support.serializer.JsonSerializer
spring.kafka.producer.value-serializer=org.springframework.kafka.support.serializer.JsonSerializer
spring.kafka.consumer.key-deserializer=com.example.common.MyJson
spring.kafka.consumer.value-deserializer=com.example.common.MyJson

后记:

  •    很多时候我们刚开始看一个知识点,不懂迷茫的时候,真的不要慌,可能说明你暂时的知识储备还不够理解。
  •    等你经过不断的学习,不断的深入以后
  •    突然有一天,你会突然的醒悟
  •    哇!原来他讲的是这个意思
  •    可能我们不理解,我们可以去尝试去看两遍,三遍,甚至更多遍,突然会有一个时刻,你会醒悟过来的
  •    且行且珍惜,共勉

SpringBoot自动配置注解原理解析的更多相关文章

  1. springboot自动配置源码解析

    springboot版本:2.1.6.RELEASE SpringBoot 自动配置主要通过 @EnableAutoConfiguration, @Conditional, @EnableConfig ...

  2. 聊一聊 SpringBoot 自动配置的原理

    解析思路 我们建立好一个SpringBoot的工程后,我们将从启动类,SpringBootApplication开始进行探究. 开始解析 首先我们建立一个 Springboot的工程.找到启动类,我们 ...

  3. SpringBoot自动配置的原理

    Spring Boot的运行是由注解@EnableAutoConfiguration提供的它的关键功能是@Import注解.        EnableAutoConfigurationImportS ...

  4. SpringBoot自动配置的魔法

    Spring自动配置 从@SpringBootApplication注解说起 SpringBoot会根据类路径下的类自动配置,省去了编写繁琐的xml配置文件.原本基于xml配置bean的方式编程基于J ...

  5. SpringBoot实战之SpringBoot自动配置原理

    SpringBoot 自动配置主要通过 @EnableAutoConfiguration, @Conditional, @EnableConfigurationProperties 或者 @Confi ...

  6. SpringBoot自动配置原理学习

    介绍 构建Springboot项目时我们会创建一个启动类 @SpringBootApplication public class DemoApplication { public static voi ...

  7. 助力SpringBoot自动配置的条件注解ConditionalOnXXX分析--SpringBoot源码(三)

    注:该源码分析对应SpringBoot版本为2.1.0.RELEASE 1 前言 本篇接 如何分析SpringBoot源码模块及结构?--SpringBoot源码(二) 上一篇分析了SpringBoo ...

  8. 小BUG大原理:重写WebMvcConfigurationSupport后SpringBoot自动配置失效

    一.背景 公司的项目前段时间发版上线后,测试反馈用户的批量删除功能报错.正常情况下看起来应该是个小 BUG,可怪就怪在上个版本正常,且此次发版未涉及用户功能的改动.因为这个看似小 BUG 我了解到不少 ...

  9. 小BUG大原理 | 第一篇:重写WebMvcConfigurationSupport后SpringBoot自动配置失效

    一.背景 公司的项目前段时间发版上线后,测试反馈用户的批量删除功能报错.正常情况下看起来应该是个小BUG,可怪就怪在上个版本正常,且此次发版未涉及用户功能的改动.因为这个看似小BUG我了解到不少未知的 ...

随机推荐

  1. boost asio 学习(六) 定时器

    http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting- started-with-boostasio?pg=7 6 定时器 ...

  2. Python3基础知识之数据结构List和Tuple

    问题:今天学习python数据结构中的List和Tuple. 目标:了解二者的区别,学会一般的应用 相关知识:列表(List) : 类似于 .NET ArrayList / List.元组(Tuple ...

  3. drf1 rest & restful规范

    web服务交互 我们在浏览器中能看到的每个网站,都是一个web服务.那么我们在提供每个web服务的时候,都需要前后端交互,前后端交互就一定有一些实现方案,我们通常叫web服务交互方案. 目前主流的三种 ...

  4. Hibernate 映射及查询

    实体类和实体之间的关系:一对多,多对多 数据库设计:e_r 一个实体对象就是一个表格,  如果是1对多的关系,将多方的主键拿到1方做外键.  多对多:重新建立一张新的表格,将双方的主键拿到这里做外键 ...

  5. 【慕课网实战】Spark Streaming实时流处理项目实战笔记十八之铭文升级版

    铭文一级: 功能二:功能一+从搜索引擎引流过来的 HBase表设计create 'imooc_course_search_clickcount','info'rowkey设计:也是根据我们的业务需求来 ...

  6. 前端之html表单

    html表单 用于搜集不同类型的用户输入 表单由不同类型的标签组成   1.<form>标签 定义整体的表单区域     * action属性 定义表单数据提交地址     * metho ...

  7. Web API使用HttpResponseMessage与HttpResponseException的差异 HttpResponseMessage 返回类型

    在 Web API 中提供了 HttpResponseMessage 与 HttpResponseException 用于处理返回讯息,HttpResponseMessage 用于返回一个来自于客户端 ...

  8. ESP32 windows开发环境的搭建(官方方法)

    首先保证电脑中的已经下载了git客户端,没有的自行去https://git-scm.com/下载 STEP1: 获得编译工具链 Windows没有内置的“make”环境,所以安装工具链你将需要一个兼容 ...

  9. 关不掉的小姐姐程序python tkinter实现 学习---打包教程

    首先,我们先准备两个.py文件,还要图片文件         代码//是我自己手写的,copy时记得删掉,不然有可能错误,比如中英文啥的    当然 一些语法的无问题就百度,都能给你答案 第一个.py ...

  10. shell 文件操作

      序   在linux平台下开发,我们经常会接触到一些任务性质的工作,而处理方式多样化.现积累各个案例.   从远程服务器拉取文件到本地服务器   scp work@cp01-xx-dev.com: ...