SpringBoot自动配置注解原理解析

1. SpringBoot启动主程序类:

1 @SpringBootApplication
2 public class DemoApplication {
3     public static void main(String[] args) {
4
5         SpringApplication.run(DemoApplication.class, args);
6     }
7 }

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

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

2. SpringBootApplication注解:

 1 @Target(ElementType.TYPE)
 2 @Retention(RetentionPolicy.RUNTIME)
 3 @Documented
 4 @Inherited
 5 @SpringBootConfiguration
 6 @EnableAutoConfiguration
 7 @ComponentScan(excludeFilters = {
 8         @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
 9         @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
10 public @interface SpringBootApplication {

  三个比较重要的注解:

  • @SpringBootConfiguration : Spring Boot的配置类,标注在某个类上,表示这是一个Spring Boot的配置类
  • @EnableAutoConfiguration: 开启自动配置类,SpringBoot的精华所在。
  • @ComponentScan包扫描

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

3. EnableAutoConfiguration注解:

1 @Target(ElementType.TYPE)
2 @Retention(RetentionPolicy.RUNTIME)
3 @Documented
4 @Inherited
5 @AutoConfigurationPackage
6 @Import(AutoConfigurationImportSelector.class)
7 public @interface EnableAutoConfiguration {

两个比较重要的注解:

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

4. AutoConfigurationPackage注解:

1     static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
2
3         @Override
4         public void registerBeanDefinitions(AnnotationMetadata metadata,
5                 BeanDefinitionRegistry registry) {
6             register(registry, new PackageImport(metadata).getPackageName());
7         }

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

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

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

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

5. Import(AutoConfigurationImportSelector.class)注解:

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

ImportSelector有一个方法为:selectImports。

 1 @Override
 2     public String[] selectImports(AnnotationMetadata annotationMetadata) {
 3         if (!isEnabled(annotationMetadata)) {
 4             return NO_IMPORTS;
 5         }
 6         AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
 7                 .loadMetadata(this.beanClassLoader);
 8         AnnotationAttributes attributes = getAttributes(annotationMetadata);
 9         List<String> configurations = getCandidateConfigurations(annotationMetadata,
10                 attributes);
11         configurations = removeDuplicates(configurations);
12         Set<String> exclusions = getExclusions(annotationMetadata, attributes);
13         checkExcludedClasses(configurations, exclusions);
14         configurations.removeAll(exclusions);
15         configurations = filter(configurations, autoConfigurationMetadata);
16         fireAutoConfigurationImportEvents(configurations, exclusions);
17         return StringUtils.toStringArray(configurations);
18     }

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

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

我们以RedisTemplate为例:

 1 @Configuration
 2 @ConditionalOnClass(RedisOperations.class)
 3 @EnableConfigurationProperties(RedisProperties.class)
 4 @Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
 5 public class RedisAutoConfiguration {
 6
 7     @Bean
 8     @ConditionalOnMissingBean(name = "redisTemplate")
 9     public RedisTemplate<Object, Object> redisTemplate(
10             RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
11         RedisTemplate<Object, Object> template = new RedisTemplate<>();
12         template.setConnectionFactory(redisConnectionFactory);
13         return template;
14     }
15
16     @Bean
17     @ConditionalOnMissingBean
18     public StringRedisTemplate stringRedisTemplate(
19             RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
20         StringRedisTemplate template = new StringRedisTemplate();
21         template.setConnectionFactory(redisConnectionFactory);
22         return template;
23     }
24
25 }

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

这时候该如何去做呢?

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

 1 @Bean("redisTemplate")
 2     public RedisTemplate<Object, Object> myRedisTemplate(
 3             RedisConnectionFactory redisConnectionFactory) {
 4         RedisTemplate<Object, Object> template = new RedisTemplate<>();
 5         template.setConnectionFactory(redisConnectionFactory);
 6         // 修改序列化为Jackson
 7         template.setDefaultSerializer(new GenericJackson2JsonRedisSerializer());
 8         // 开启事务
 9         template.setEnableTransactionSupport(true);
10         return template;
11     }

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

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

我们在以Kafka为例:

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

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

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

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

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

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

后记:

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

原文地址:https://www.cnblogs.com/jiligalaer/p/12070584.html

时间: 2024-08-10 18:29:08

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

SpringBoot自动配置的原理

Spring Boot的运行是由注解@EnableAutoConfiguration提供的它的关键功能是@Import注解.        EnableAutoConfigurationImportSelector 使用 SpringFactoriesLoader.loadFactoryNames 方法来扫描具有MEAT-INF/spring.factories文件的jar包 在了解原理前我们需要先认识下面几个注解:        @ConditionalOnBean:当容器里有指定的Bean为

SpringBoot自动配置原理

SpringBoot自动配置主要通过@EnableAutoConfiguration, @Conditional, @EnableConfigurationProperties或者@ConfigurationProperties 等几个注解来进行自动配置完成的. @EnableAutoConfiguration开启自动配置,主要作用就是调用Spring-Core包里的loadFactoryNames(),将autoconfig 包里的已经写好的自动配置加载进来. @Conditional条件注解

助力SpringBoot自动配置的条件注解ConditionalOnXXX分析--SpringBoo

注:该源码分析对应SpringBoot版本为2.1.0.RELEASE 1 前言 本篇接如何分析SpringBoot源码模块及结构?--SpringBoot源码(二) 上一篇分析了SpringBoot源码结构及各个模块pom之间的关系后,那么此篇开始就开始解开SpringBoot新特性之一--自动配置的神秘面纱了.因为SpringBoot自动配置原理是基于其大量的条件注解ConditionalOnXXX,因此,本节我们先来撸下Spring的条件注解的相关源码. 2 SpringBoot的派生条件

SpringBoot自动配置的实现原理

之前一直在用SpringBoot框架,一直感觉SpringBoot框架自动配置的功能很强大,但是并没有明白它是怎么实现自动配置的,现在有空研究了一下,大概明白了SpringBoot框架是怎么实现自动配置的功能,我们编写一个最简单的自动配置功能,大概的总结一下. 一,配置属性类 其实就是值对象注入的方式去配置一些Spring常用的配置,我们编写一个最简单的配置对象. @ConfigurationProperties(prefix = "hello") //@Component //如果这

springBoot 自动配置原理

在之前文章中说过,springBoot会根据jar包去添加许多的自动配置,本文就来说说为什么会自动配置,自动配置的原理时什么? springBoot在运行SpringApplication对象实例化时,就会去加载 META-INF/spring.factories文件,就会将这个文件中的配置都加载到spring容器中.下面,我们去看看SpringApplication对象的初始化方法 initialize() 方法. 因为我们在项目启动时有用到这个对象,所以,我们可以直接从这里进入. 找到 in

SpringBoot初体验及原理解析

一.前言 ? 我们来用SpringBoot开始HelloWorld之旅.SpringBoot是Spring框架对"约定大于配置(Convention over Configuration)"理念的最佳实践.SpringBoot应用本质上就是一个基于Spring框架的应用.我们大多数程序猿已经对Spring特别熟悉了,那随着我们的深入挖掘,会发现SpringBoot中并没有什么新鲜事,如果你不信,那就一起走着瞧呗! 二.SpringBoot初体验 首先,我们按照下图中的步骤生成一个Spr

springboot自动配置

springboot是在spring基础上的一次跃迁,是约定先于配置的完美实践. 最近在学习springboot相关内容,看到自动配置这个知识点时,着实有些困惑,网上大多博客多介绍何为springboot自动配置及其实现原理,读完依然还有些云遮雾绕. 鉴于现今我浅薄的spring知识,并不深刻知道springboot自动配置相较于spring的原始配置之间究竟有何不同,遂遍历多篇相关博客并请教大佬,才堪堪在逻辑上对二者之区别略有知晓. 我想从spring之XML配置到spring之注解配置后至s

SpringBoot源码分析----(一)SpringBoot自动配置

前言 springboot项目将模块化设计发挥到及至,需要什么模块,只需导入这个模块对应的stater即可,当然,用户根据业务需要自定义相关的stater,关于自定义stater在后续章节将一一解说,学习springboot,首要了解springboot的自动配置原理,我们从springboot项目的主启动类说起逐步解读springboot自动配置的奥秘. springboot自动配置解读 @SpringBootApplication public class SpringBootQuickAp

自定义的Spring Boot starter如何设置自动配置注解

本文首发于个人网站:自定义的Spring Boot starter如何设置自动配置注解 在Spring Boot实战之定制自己的starter一文最后提到,触发Spring Boot的配置过程有两种方法: spring.factories:由Spring Boot触发探测classpath目录下的类,进行自动配置: @Enable:有时需要由starter的用户触发*查找自动配置文件的过程. 实战 接着上篇文章的例子,首先将spring.factories中的内容注释掉 #org.springf