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. 使用android访问SQLServer数据库

    1.SQL驱动 下载可以支持android的SQL驱动,下载地址http://sourceforge.net/projects/jtds/files/ 注意只能下载1.2.7版本.android不支持 ...

  2. Testng用例失败重新运行

    Testng用例失败重新运行   在ui测试用例的运行过程中,发现有很多不确定的因素会导致用例失败,比如网络原因,比如屏幕滑动失败等.想到需要让测试用例,在失败后重新运行来提高测试成功率. 在gith ...

  3. ABP框架系列之十七:(Data-Filters-数据过滤)

    Introduction It's common to use the soft-deletepattern which is used to not delete an entity from da ...

  4. save to project-level dictionary? save to application-level dictionary?

    通过静态代码分析工具lint在Spelling typo得到save to project-level dictionary? save to application-level dictionary ...

  5. brew安装和换源

    命令行执行ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)&q ...

  6. 可遇不可求的Question之flash的socket连接安全策略文件篇

    flash的socket连接安全策略文件   最近公司做压力测试的时候,发现了一个问题.flash的socket客户端向服务端请求安全策略文件的时候,服务端负责回发策略文件的端口能连接上,但是没有响应 ...

  7. 微信公众号UX分析—— 学生作业小结

    1. 不足: 1. 权威性:个人帐号,显得不够正式. 2. 排版问题: + 没有必要的外接端口,界面设计极度缺少排版.哪怕是个人公众号都不至于如此,更何况这是一个学校的教务平台. 3. 反应不及时或无 ...

  8. 使用Phabricator进行代码审查

    Pharicator 是FB的代码审查工具,主要开发者为Evan Priestley,是一个开源软件,可在Apache许可证第2版下作为自由软件分发.详细信息可查看官方文档.这里从应用的角度,一步一步 ...

  9. WPF触发器(Trigger) - DataTrigger

    官方文档中对DataTrigger的介绍 Represents a trigger that applies property values or performs actions when the ...

  10. 2018CCPC-女生专场

    (咕咕咕,咕了快一年的bu题.. A.CCPC直播 传送:http://acm.hdu.edu.cn/showproblem.php?pid=6297 题意:rt. 分析:模拟. #include&l ...