Springboot-3 自动配置实例,处理命名不符合springmvc要求的方法,不看帮助文档修改配置方法 @EnableConfigurationProperties 和 @Condit

总结:

   1)SpringBoot先加载所有自动配置类

  2)每个自动配置类按照条件@Conditional参数进行生效,绑定配置文件指定的值

      一般都是XXx.properties来,x.properties和配置文件绑定

 3)生效的配置就会给容器中装配@Bean标记的组件,当然符合组件@Conditional要求

 4)只要有这些组件,相当于这些功能就有了

5)定制配置

     a)只要有用户自己配置的@Bean,以用户优先

     b)修改配置文件:用户去看这个类对应的配置文件

导入的lib里面的jar中:   XXAutoConfigration到导入了很多组件,组件又从xxxProperties中取值,

xxxProperties又从配置文件中取值

上文说到会默认全部加载127个jar包,但是会根据每个jar里面的@Conditional去按需配置

例1  以AopAutoConfiguration为例

  

 断点:

@SpringBootApplication--》@EnableAutoConfiguration-->AutoConfigurationImportSelector->

 

 这127个是

this = {AutoConfigurationImportSelector@3479} 
annotationMetadata = {StandardAnnotationMetadata@3480} 
 mergedAnnotations = {TypeMappedAnnotations@3794} 
 nestedAnnotationsAsMap = true
 annotationTypes = {Collections$UnmodifiableSet@3795}  size = 1
 introspectedClass = {Class@1363} "class com.i7i8i9.boot.MainApplication"
attributes = {AnnotationAttributes@3798}  size = 2
configurations = {LinkedList@3802}  size = 127
 0 = "org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration"
 1 = "org.springframework.boot.autoconfigure.aop.AopAutoConfiguration"
 2 = "org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration"
 3 = "org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration"
 4 = "org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration"
 5 = "org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration"
 6 = "org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration"
 7 = "org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration"
 8 = "org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration"
 9 = "org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration"
 10 = "org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration"
 11 = "org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration"
 12 = "org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration"
 13 = "org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration"
 14 = "org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration"
 15 = "org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration"
 16 = "org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration"
 17 = "org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration"
 18 = "org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration"
 19 = "org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration"
 20 = "org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration"
 21 = "org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration"
 22 = "org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration"
 23 = "org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRestClientAutoConfiguration"
 24 = "org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration"
 25 = "org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration"
 26 = "org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration"
 27 = "org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration"
 28 = "org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration"
 29 = "org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration"
 30 = "org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration"
 31 = "org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration"
 32 = "org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration"
 33 = "org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration"
 34 = "org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration"
 35 = "org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration"
 36 = "org.springframework.boot.autoconfigure.data.r2dbc.R2dbcTransactionManagerAutoConfiguration"
 37 = "org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration"
 38 = "org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration"
 39 = "org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration"
 40 = "org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration"
 41 = "org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration"
 42 = "org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration"
 43 = "org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration"
 44 = "org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration"
 45 = "org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration"
 46 = "org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration"
 47 = "org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration"
 48 = "org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration"
 49 = "org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration"
 50 = "org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration"
 51 = "org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration"
 52 = "org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration"
 53 = "org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration"
 54 = "org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration"
 55 = "org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration"
 56 = "org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration"
 57 = "org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration"
 58 = "org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration"
 59 = "org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration"
 60 = "org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration"
 61 = "org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration"
 62 = "org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration"
 63 = "org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration"
 64 = "org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration"
 65 = "org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration"
 66 = "org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration"
 67 = "org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration"
 68 = "org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration"
 69 = "org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration"
 70 = "org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration"
 71 = "org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration"
 72 = "org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration"
 73 = "org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration"
 74 = "org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration"
 75 = "org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration"
 76 = "org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration"
 77 = "org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration"
 78 = "org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration"
 79 = "org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration"
 80 = "org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration"
 81 = "org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration"
 82 = "org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration"
 83 = "org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration"
 84 = "org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration"
 85 = "org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration"
 86 = "org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration"
 87 = "org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration"
 88 = "org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration"
 89 = "org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration"
 90 = "org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration"
 91 = "org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration"
 92 = "org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration"
 93 = "org.springframework.boot.autoconfigure.security.rsocket.RSocketSecurityAutoConfiguration"
 94 = "org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration"
 95 = "org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration"
 96 = "org.springframework.boot.autoconfigure.session.SessionAutoConfiguration"
 97 = "org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration"
 98 = "org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration"
 99 = "org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration"

在其中可以发现 aop configuration确实导入进来了

 

根据

 

@ConditionalOnProperty(
    prefix = "spring.aop",
    name = {"auto"},
    havingValue = "true",
    matchIfMissing = true
)

需要配置文件中有 spring.aop的才生效,最后一句matchIfMissing = true代表没配也认为你配了

接下来看

   @Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnClass({Advice.class})
    static class AspectJAutoProxyingConfiguration {
        AspectJAutoProxyingConfiguration() {
        }

基于是否存在

这个advice 从import org.aspectj.weaver.Advice来看应该是aspectj下

在当前类中没有找到

 再看这里面的另外一个类

ConditionalOnMissingClass({"org.aspectj.weaver.Advice"})没有advice时使用

 @ConditionalOnMissingClass({"org.aspectj.weaver.Advice"})
    @ConditionalOnProperty(
        prefix = "spring.aop",
        name = {"proxy-target-class"},
        havingValue = "true",
        matchIfMissing = true
    )
    static class ClassProxyingConfiguration {
        ClassProxyingConfiguration(BeanFactory beanFactory) {
            if (beanFactory instanceof BeanDefinitionRegistry) {
                BeanDefinitionRegistry registry = (BeanDefinitionRegistry)beanFactory;
                AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
                AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            }

当前类中可以查到

 例2  没有生效的例子---cache

 AutoConfiguration都是自动配置类,但是不一定生效

可以看到其也是springboot一启动就加载

 另外看是否按需加载

@ConditionalOnClass({CacheManager.class})

在idea中搜索其存在于spring核心包

 第二个判断:是判断有没有CacheAspectSupport这种类型的Bean

@ConditionalOnBean({CacheAspectSupport.class})

在MainApplication中加入

       String[] beanNamesforCache= applicationContext.getBeanNamesForType(CacheAspectSupport.class);
        System.out.println("beanNamesforCache数量==="+beanNamesforCache.length);

输出:

  beanNamesforCache数量===0

代表没有生效

那么其下的@Bean给容器加东西的这种自然也不会生效

@Bean
    @ConditionalOnMissingBean
    public CacheManagerCustomizers cacheManagerCustomizers(ObjectProvider<CacheManagerCustomizer<?>> customizers) {
        return new CacheManagerCustomizers((List)customizers.orderedStream().collect(Collectors.toList()));
    }

    @Bean
    public CacheManagerValidator cacheAutoConfigurationValidator(CacheProperties cacheProperties, ObjectProvider<CacheManager> cacheManager) {
        return new CacheManagerValidator(cacheProperties, cacheManager);
    }

例三:生效的例子

 

 总类:    看其条件

@Configuration(  //说明是一个配置类
    proxyBeanMethods = false
)
@ConditionalOnWebApplication(  //需要是原生web,springboot2支持响应式和原生两种
    type = Type.SERVLET
)
@ConditionalOnClass({DispatcherServlet.class})

第二个条件

    @ConditionalOnWebApplication(  //需要是原生web,springboot2支持响应式和原生两种
    type = Type.SERVLET
)

   现在我们用的spring-boot就是原生的SpringMVC

    响应式导入的是SpringWebFlux

第三个条件

在class中存在以下类

   

 子类:总类生效了,子类才会生效

@Configuration(
    proxyBeanMethods = false
)
@Conditional({DispatcherServletRegistrationCondition.class})
@ConditionalOnClass({ServletRegistration.class})
@EnableConfigurationProperties({WebMvcProperties.class})
@Import({DispatcherServletConfiguration.class})
protected static class DispatcherServletRegistrationConfiguration {

确定有

 接下来是熟悉的跟配置文件绑定的功能

@EnableConfigurationProperties({WebMvcProperties.class})

进入可以看到其绑定了 spring.mvc,也就是说配置文件中spring mvc开头的都会被读取

 另外检查一下容器中是否有WebMvcProperties对象

String[] beanWebMVC= applicationContext.getBeanNamesForType(WebMvcProperties.class);
System.out.println("beanWebMVC数量==="+beanWebMVC.length);

则判断该子类对象生效了

查看子类中方法,@Bean表示加入到容器中,另外发现new了Servlet说明底层帮我们创建了SpringMVC核心对象   DispatcherServlet

  @Bean(
            name = {"dispatcherServlet"}
        )
        public DispatcherServlet dispatcherServlet(WebMvcProperties webMvcProperties) {
            DispatcherServlet dispatcherServlet = new DispatcherServlet();
            dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest());
            dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest());
            dispatcherServlet.setThrowExceptionIfNoHandlerFound(webMvcProperties.isThrowExceptionIfNoHandlerFound());
            dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents());
            dispatcherServlet.setEnableLoggingRequestDetails(webMvcProperties.isLogRequestDetails());
            return dispatcherServlet;
        }

 另外一个Bean是文件上传解析器

 @Bean
        @ConditionalOnBean({MultipartResolver.class})  //容器中有这个类型组件
        @ConditionalOnMissingBean(
            name = {"multipartResolver"}   //容器中没有这个名字的组件,SpringMVC要求必须是这个名字
        )
        public MultipartResolver multipartResolver(MultipartResolver resolver) {
            return resolver;
        }
    }

   有趣的是这个用法

 public MultipartResolver multipartResolver(MultipartResolver resolver) {
            return resolver;
        }

用了给@Bean方法传递了参数,这个参数的值会自动去容器中找

解决了名字没有按照springmvc要求命名为multipartResolver的问题

防止有些用户配置的文件上传解析器不符合规范

这样读进来后,返回,因为方法名字是规范的multipartResolve,符合SpringMVC要求

例三 HttpEncodingAutoConfiguration

先写一个中文例子

    controller:

  @RequestMapping("/hello")
    public String handle01(@RequestParam("name") String name){

        return "Hello,你好,i7i8i9"+name;
    }

在浏览器中请求

 为什么不乱吗,原因在于

   

@Configuration(   //声明是一个配置类
    proxyBeanMethods = false    
)
@EnableConfigurationProperties({ServerProperties.class})   //会去读配置文件
@ConditionalOnWebApplication(
    type = Type.SERVLET      //是不是原生,是的,我们用的是PSringMVC,不是响应式,没有webflux
)
@ConditionalOnClass({CharacterEncodingFilter.class})
@ConditionalOnProperty(
    prefix = "server.servlet.encoding",    //配置文件中是否有这个前缀
    value = {"enabled"},                   //前缀的值是 enables
    matchIfMissing = true    //没配也生效的意思
)
public class HttpEncodingAutoConfiguration {
    private final Encoding properties;

    public HttpEncodingAutoConfiguration(ServerProperties properties) {
        this.properties = properties.getServlet().getEncoding();
    }

 确实有

 进入子类

 characterEncodingFilter()是SpringMVC解决编码问题的,用这个拦截,否则就会乱码

 @ConditionalOnMissingBean   容器中没有配这个就会帮你配

   @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;
    }

spring设计模式:会自动配置组件,但是优先使用用户的

用户如果想自己写,可以写在   Myconfig这个配置类中,比如

@Bean

 public CharacterEncodingFilter characterEncodingFilter() {return null}

另外可以根据类Property去修改配置文件,比如

 在配置文件中可以根据这个前缀要求去修改:

   

 

修改配置文件propety举例

 要修改

ServerProperties.class,进入

 详细一点,就是

@ConditionalOnProperty(
    prefix = "server.servlet.encoding",
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值