微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

9.自动配置原理

那些属性可以在配置文件中写呢: 参考官方文档:https://docs.spring.io/spring-boot/docs/1.5.10.RELEASE/reference/htmlsingle/#common-application-properties 具体:Part X. Appendices Appendix A. Common application properties @H_502_0@


自动配置原理:   1.springboot在启动时加载著配置类(@SpringBootApplication标注的类),开启了自动配置功能(@EnableAutoConfiguration)   2.@EnableAutoConfiguration的作用:
1.@EnableAutoConfiguration标签代码如下:
    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @AutoConfigurationPackage------------------>自动扫描启动类包下和其子包下的所有带标签的组件
    @Import({AutoConfigurationImportSelector.class})
    public @interface EnableAutoConfiguration {
         ...   
    }

2.AutoConfigurationImportSelector的代码如下:
    protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
        ...
        //获取候选配置
        List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
        ....
    }
3.getCandidateConfigurations的代码如下:
    protected List<String> getCandidateConfigurations(AnnotationMetadata Metadata, AnnotationAttributes attributes) {
        //第一个参数返回:EnableAutoConfiguration.class 
        List<String> configurations = SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader());
        Assert.notEmpty(configurations, "No auto configuration classes found in meta-inf/spring.factories. If you are using a custom packaging, make sure that file is correct.");
        return configurations;
    }
4.loadFactoryNames代码如下:
    public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
        String factoryTypeName = factoryType.getName();
        return (List)loadSpringFactories(classLoader).getorDefault(factoryTypeName, Collections.emptyList());
    }
5.loadSpringFactories代码如下:
    {
        ...
        Enumeration<URL> urls = classLoader != null ? classLoader.getResources("meta-inf/spring.factories") : ClassLoader.getSystemResources("meta-inf/spring.factories");
        ...
    }

总结:发现其底层是获取jar类路径下的: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,\
    org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
    ...很多很多!
    
每一个这样的xxxAutoConfiguration都是容器的一个组件,都加到容器中,用他们来做自动配置

springboot的精髓:

1.springboot启动时会加载大量的自动配置类(xxxAutoConfiguration) 2.我们看我们需要的功能有没有springboot认写好的自动配置类 3.我们再来看这个自动配置类中到底配置了哪些组件(只要我们要用的组件有,就不需要再来配置了) 4.给容器中自动配置添加组件时,会从properties类中获取某些属性值。我们就可以在配置文件中指定这些属性的值4   xxxAutoConfiguration:自动配置 给容器中添加组件 xxxProperties:封装了配置文件中相关的属性   以HttpEncodingAutoConfiguration来理解其底层的(http编码自动设置)为例解释自动配置原理:
@Configuration( //表示这是一个配置类,跟以前编写的配置文件一样(<bean></bean>)也可以给容器中添加组件
    proxyBeanMethods = false
)
    @EnableConfigurationProperties({ServerProperties.class})//启动指定类的ConfigurationProperties功能;将配置文件中的值和ServerProperties绑定起来
    //判断当前类是不是web应用,如果是,当前配置类生效
    @ConditionalOnWebApplication(//里面是spring的@Conditional(条件判断注解),根据不同的条件,如果满足指定的条件,配置类中的配置就会生效
    type = Type.SERVLET  
)
@ConditionalOnClass({CharacterEncodingFilter.class})//判断当前项目有没有这个类:CharacterEncodingFilter;springmvc中进行乱码解决的过滤器
@ConditionalOnProperty(//判断当前项目是否存在某个配置:server.servlet.encoding.enabled; 如果不存在,判断也是成立的()matchIfMissing = true),
                        //即使我们的配置文件中不配置server.servlet.encoding.enabled=true,也是认生效的
    prefix = "server.servlet.encoding",
    value = {"enabled"},
    matchIfMissing = true
)
public class HttpEncodingAutoConfiguration {
    //这个Encoding 类是ServerProperties的内部类,所以和springboot的appliaction.properties文件以形成了映射关系(重要!)
    private final Encoding properties;
    @Bean//给容器中添加一个组件,这个组件的某些值要从properties中获取
    @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;
}
}
根据当前不同的条件判断,决定这个配置类是否生效!!
细节 1.@Conditional派生注解(spring注解版的原生的@Conditional的作用) 作用:是必须@Conditional指定的条件必须成立,才能给容器中添加组件,配置里面的内容才能生效
@Conditional扩展注解 作用(判断是否满足当前条件)
@ConditionalOnjava 系统的java版本是否满足要求
@ConditionalOnBean 容器中存在指定的bean
@ConditionalOnMissingBean 容器中不存在指定的bean
@ConditionalOnExpression 满足SPEL表达式的
@ConditionalOnClass 系统中存在指定的类
@ConditionalOnMissingClass 系统中不存在指定的class
@ConditionalOnSingleCandidate 容器中只有一个指定的bean,或者这个bean是首选的bean
@ConditionalOnProperty 系统中指定的属性是否存在指定的值
@ConditionalOnResource 类路径下是否存在指定的资源文件
自动配置类必须在一定的条件下才能生效! 我们可以在配置文件中设置;debug=true,控制台上会输出自动配置的类! @H_502_0@

============================
CONDITIONS EVALUATION REPORT
============================


Positive matches:(自动配置类启动的)
-----------------

   AopAutoConfiguration matched:
      - @ConditionalOnProperty (spring.aop.auto=true) matched (OnPropertyCondition)

   AopAutoConfiguration.ClassproxyingConfiguration matched:
      - @ConditionalOnMissingClass did not find unwanted class 'org.aspectj.weaver.Advice' (OnClassCondition)
      - @ConditionalOnProperty (spring.aop.proxy-target-class=true) matched (OnPropertyCondition)
    。。。。
    
    
Negative matches:(自动配置类没有匹配上的)
-----------------

   ActiveMQAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class 'javax.jms.ConnectionFactory' (OnClassCondition)

   AopAutoConfiguration.AspectJAutoproxyingConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class 'org.aspectj.weaver.Advice' (OnClassCondition)
         ....
@H_502_0@ 

@H_502_0@

@H_502_0@

@H_502_0@

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐