• 思考一下application.properties都能写哪些配置项,还有为什么可以写那么多的配置项,是不是觉得特别神奇呢。

    分析自动配置原理

  • 以RedisAutoConfiguration (redis相关自动配置)为例子来解释自动配置原理。 ```java // // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) //

package com.addicated.demo.pojo;

import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisOperations; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate;

// 表明这是一个配置类,前面文章有提及过,进行spring的相关配置可以通过application文件 // 以及javaConfig配置类, // 加了这个注解的类就表明是一个配置类。 @Configuration(proxyBeanMethods = false)

// Spring底层@Conditional注解 // 根据不同的条件判断,如果满足指定的条件,整个配置类里面的配置就会生效 // 这里的含义是 RedisOperations 是否被声明,如果没有进行声明的话,这个配置类就不会生效 @ConditionalOnClass({RedisOperations.class}) // 启动指定类的ConfigurationProperties功能 // 进入 RedisProperties 查看,将配置文件中对应的值和 RedisProperties绑定起来 // 并吧 RedisProperties 加入到ioc中 @EnableConfigurationProperties({RedisProperties.class}) @Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class}) public class RedisAutoConfiguration { // 无餐构造方法 public RedisAutoConfiguration() { }

  1. @Bean
  2. @ConditionalOnMissingBean(
  3. name = {"redisTemplate"}
  4. )
  5. // 条件为当 RedisConnectionFactory 该类被声明
  6. @ConditionalOnSingleCandidate(RedisConnectionFactory.class)
  7. public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
  8. RedisTemplate<Object, Object> template = new RedisTemplate();
  9. template.setConnectionFactory(redisConnectionFactory);
  10. return template;
  11. }
  12. // 给容器添加一个组建,这个组建的某些之需要从properties中获取
  13. @Bean
  14. @ConditionalOnMissingBean // 判断容器有没有这个组建
  15. @ConditionalOnSingleCandidate(RedisConnectionFactory.class)
  16. public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
  17. StringRedisTemplate template = new StringRedisTemplate();
  18. template.setConnectionFactory(redisConnectionFactory);
  19. return template;
  20. }

}

  1. <a name="taCZC"></a>
  2. ## 一句话总结:根据当前不同的条件判断,决定这个配置累是否生效
  3. - 一旦这个配置类生效;这个配置类就会给容器中添加各种组建
  4. - 这些组建的属性是从对应的properties类中获取的,这些类中的每一个属性又是和配置文件绑定的
  5. - 所有在配置文件中能配置的属性都是在xxxxProperties类中封装着
  6. - 配置文件能配置什么就可以参照某个功能对应的这个属性类。
  7. 注意:这里我没有导入redis相关的依赖所以 RedisProperties 点不进去,使用一个其他的properties来进行表示
  8. ```java
  9. //从配置文件中获取指定的值和bean的属性进行绑定
  10. @ConfigurationProperties(prefix = "spring.http")
  11. public class HttpProperties {
  12. // .....
  13. }
  • 来到配置文件中试试前缀是否可提示

image.png

  • 这就是字自动装配的原理

    精髓

  • springboot启动会加载大量的自动配置类

    • 那么如何知道哪些加载哪些没有加载呢? 在配置文件中 debug=true 之后在springboot应用启动的时候就可以根据日志推断哪些得到了加载哪些没有
  • 进行开发的时候首先看自己需要的功能有没有在自动配置类当中
  • 然后看看自动配置类中到底配置了哪些组件(只要需要的组建在其中,就不用再进行手动配置了)
  • 给容器中自动配置类添加组建的时候,会从properties类中获取某些属性,只要在配置文件中指定这些属性的值即可。

xxxxAutoConfigurartion:自动配置类;给容器中添加组件
xxxxProperties:封装配置文件中相关属性

了解 @Conditional

  • 了解完自动装配的原理后,关注一个细节问题,自动配置类必须在一定的条件下才能生效

    @Conditional派生注解(Spring注解版原声的Conditional作用)

    作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置配里面的所有内容才生效;
    image.png

    那么多的自动配置类,必须在一定的条件才能生效,也就是说,加载了这么多配置类,但不是所有的都生效了

  • 如何知道哪些自动配置类生效?

  • debug=true 来让控制台打印出来自动配置报告,这样就可以很方便的知道哪些自动配置类生效。
  • Positive matches:(自动配置类启用的:正匹配)

Negative matches:(没有启动,没有匹配成功的自动配置类:负匹配)
Unconditional classes: (没有条件的类)