[学习笔记] SpringBoot之深入自动装配原理

# 学习 # · 2021-04-20

自动装配原理

1、自动配置原理:

(1)SpringBoot启动的时候加载主配置类,开启了自动配置功能@EnableAutoConfiguration。

(2)@EnableAutoConfiguration:将类路径下META-INF/spring.factories里面配置的所有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.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
//...

(3)每一个这样的xxxAutoConfiguration类都是容器中的一个组件,都加入到容器中,用他们来做自动配置。

2、以HttpEncodingAutoConfiguration(Http 编码自动配置)为例解释自动配置原理:

(1)HttpEncodingAutoConfiguration源码视图:

// 表示这是一个配置类,以前编写的配置文件一样,也可以给容器中添加组件
@Configuration(proxyBeanMethods = false)

// 启动指定类的ConfigurationProperties功能
// 将配置文件中对应的值和ServerProperties绑定起来
// 并把HttpEncodingProperties加入到ioc容器中
@EnableConfigurationProperties({ServerProperties.class})

// Spring底层@Conditional注解
// 如果满足指定的条件,整个配置类里面的配置就会生效
// 即判断当前应用是否是web应用,如果是,当前配置类生效
@ConditionalOnWebApplication(type = Type.SERVLET)

// 判断当前项目有没有这个类CharacterEncodingFilter;SpringMVC中进行乱码解决的过滤器
@ConditionalOnClass({CharacterEncodingFilter.class})

// 判断配置文件中是否存在某个配置server.servlet.encoding
// 即使我们配置文件中不配置server.servlet.encoding=true,也是默认生效的
@ConditionalOnProperty(
    prefix = "server.servlet.encoding",
    value = {"enabled"},
    matchIfMissing = true
)
public class HttpEncodingAutoConfiguration {

      // 和SpringBoot的配置文件映射了
      private final Encoding properties;

       // 只有一个有参构造器的情况下,参数的值就会从容器中拿
      public HttpEncodingAutoConfiguration(ServerProperties properties) {
        this.properties = properties.getServlet().getEncoding();
    }

    //给容器中添加一个组件,这个组件的某些值需要从properties中获取
    @Bean
    //判断容器有没有这个组件
    @ConditionalOnMissingBean
    public CharacterEncodingFilter characterEncodingFilter() {
        CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
        filter.setEncoding(this.properties.getCharset().name());
        filter.setForceRequestEncoding(this.properties.shouldForce(org.springframework.boot.web.servlet.server.Encoding.Type.REQUEST));
        filter.setForceResponseEncoding(this.properties.shouldForce(org.springframework.boot.web.servlet.server.Encoding.Type.RESPONSE));
        return filter;
    }

(2)ServerProperties源码视图:

// 从配置文件中获取指定的值和bean的属性进行绑定
@ConfigurationProperties(
    prefix = "server",
    ignoreUnknownFields = true
)
public class ServerProperties {
    private Integer port;
    private InetAddress address;
}

(3)配置文件:

3、自动装配总结:

(1)SpringBoot 启动会加载大量的自动配置类。

(2)检查项目需要的功能有没有SpringBoot默认写好的自动配置类(xxxxAutoConfigurartion)。

(3)检查该自动配置类中到底配置了哪些组件(xxxxProperties)。

(4)给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。我们就可以在配置文件中指定这些属性的值。

4、@Conditional注解:必须是@Conditional 指定的条件成立,才给容器中添加组件,配置配里面的所有内容才生效。

@Conditional 扩展注解作用(判断是否满足当前指定条件)
@ConditionalOnJava系统的 java 版本是否符合要求
@ConditionalOnBean容器中存在指定 Bean;
@ConditionalOnMissingBean容器中不存在指定 Bean;
@ConditionalOnExpression满足 SpEL 表达式指定
@ConditionalOnClass系统中有指定的类
@ConditionalOnMissingClass系统中没有指定的类
@ConditionalOnSingleCandidate容器中只有一个指定的 Bean,或者这个 Bean 是首选 Bean
@ConditionalOnProperty系统中指定的属性是否有指定的值
@ConditionalOnResource类路径下是否存在指定资源文件
@ConditionalOnWebApplication当前是 web 环境
@ConditionalOnNotWebApplication当前不是 web 环境
@ConditionalOnJndiJNDI 存在指定项
如无特殊说明,本博所有文章均为博主原创。

如若转载,请注明出处:一木林多 - https://www.l5v.cn/archives/290/

评论