springboot - 02自动配置

91 篇文章 1 订阅
12 篇文章 0 订阅

title: 自动配置原理
date: 2019-08-15 16:26:37
tags:

自动配置

  • @service @compnent @bean都是注入spring ioc容器中的,但是bean代表的可以是类和方法,service不同,他指定的是一个service层,spring会默认把它塞进ioc容器,也就是说用了service注解之后,不需要再用其他注解了

  • springboot启动的时候加载主配置类,开启自动配置功能*@EnableAutoConfiguration*

    • @EnableAutoConfiguration作用

      1. 利用EnableAutoConfigurationImportSelector给容器中导入组件

      2. 具体可以看SelectImport()方法内容

      3. List<String> configurations = getCandidateConfigurations(annotationMetadata,
              attributes);
        springfactory.loadFactoryNames()扫描到的这些文件的内容包装成properties对象
        把扫描到的这些文件的内容包装成properties对象
        从properties中获取到EnableAutoConfiguration.class类对应的值,然后把他们添加到容器中
        

        [外链图片转存失败(img-VZG1Jrtf-1566090328753)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\1565790059819.png)]

        [外链图片转存失败(img-1AKEPn8l-1566090328759)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\1565790259563.png)]

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

    • 每一个自动配置类都进行自动配置功能:一旦配置类生效,这个配置类就会给容器中添加各种组件,这些组件的属性是从对应的properties中获取的,这些类里面的每一个属性又是和配置文件绑定的

    • 所有在配置文件中能配置的属性都是在XXXproperties类中封装着,配置文件中能配置什么就可以参照某个能对应的这个属性类

      1. springboot启动会加载大量的自动配置类
      	2. 查看需要的功能有没有spring boot默认写好的配置类
              	3. 查看自动配置类中到底配置了那些组件,只要我们用的组件有,就不需要配置
            	4. 给容器中自动配置类添加组件的时候,会从properties类中获取某些属性,我们就可以在配置文件中使用这些值
      

细节

  • [外链图片转存失败(img-GTMK3Kyh-1566090328762)(C:\Users\admin\AppData\Roaming\Typora\typora-user-images\1565860639302.png)]

    @Conditional注解,条件判断类,自动配置类必须在一定条件下才能生效,开启springboot的debug模式即在配置文件中启用debug=true,来让控制台打印自动配置报告

    springweb MVC自动配置原理

    • Spring Boot provides auto-configuration for Spring MVC that works well with most applications.

      The auto-configuration adds the following features on top of Spring’s defaults:

      • Inclusion of ContentNegotiatingViewResolver(组合所有解析器的方法) and BeanNameViewResolver beans. 配置了viewResolver试图解析器,根据方法的返回值得到视图对象view,视图对象决定如何渲染

        //源码 
        public View resolveViewName(String viewName, Locale locale) throws Exception {
                RequestAttributes attrs = RequestContextHolder.getRequestAttributes();
                Assert.state(attrs instanceof ServletRequestAttributes, "No current ServletRequestAttributes");
                List<MediaType> requestedMediaTypes = this.getMediaTypes(((ServletRequestAttributes)attrs).getRequest());
                if (requestedMediaTypes != null) {
                    List<View> candidateViews = this.getCandidateViews(viewName, locale, requestedMediaTypes);
                    View bestView = this.getBestView(candidateViews, requestedMediaTypes, attrs);
                    if (bestView != null) {
                        return bestView;
                    }
                }
        测试:
            package com.atguigu.springboot;
        
        import org.springframework.boot.SpringApplication;
        import org.springframework.boot.autoconfigure.SpringBootApplication;
        import org.springframework.context.annotation.Bean;
        import org.springframework.web.servlet.View;
        import org.springframework.web.servlet.ViewResolver;
        
        import java.util.Locale;
        
        
        @SpringBootApplication
        public class SpringBoot04WebRestfulcrudApplication {
        
        	public static void main(String[] args) {
        		SpringApplication.run(SpringBoot04WebRestfulcrudApplication.class, args);
        	}
        //构建自己的视图映射,成功
        	@Bean
        	public ViewResolver myViewReolver(){
        		return new MyViewResolver();
        	}
        
        	public static class MyViewResolver implements ViewResolver{
        
        		@Override
        		public View resolveViewName(String viewName, Locale locale) throws Exception {
        			return null;
        		}
        	}
        }
        
        
      • Support for serving static resources, including support for WebJars (see below).

        静态资源文件夹路径 webjars

      • Automatic registration of Converter(类型转换组件,比如前端转换过来的一些数据啥的你到后台需要进行相应的格式转换), GenericConverter, Formatter(格式花器,字符串转化成日期格式,注册条件是,需要配置文件中写一下配置日期格式化规则才会起作用,自己添加的格式化转换器,只需要放到容器中即可) beans.

        
                @Bean
                @ConditionalOnProperty(
                    prefix = "spring.mvc",
                    name = {"date-format"}
                )
                public Formatter<Date> dateFormatter() {
                    return new DateFormatter(this.mvcProperties.getDateFormat());
                }
        
        
      • Support for HttpMessageConverters (see below).springMVC用来转换http请求和响应的

      • Automatic registration of MessageCodesResolver (see below).

      • Static index.html support 首页访问

      • Custom Favicon support (see below).

      • Automatic use of a ConfigurableWebBindingInitializer bean (see below).

      If you want to keep Spring Boot MVC features, and you just want to add additional MVC configuration (interceptors, formatters, view controllers etc.) you can add your own @Configuration class of type WebMvcConfigurerAdapter, but without@EnableWebMvc. If you wish to provide custom instances of RequestMappingHandlerMapping, RequestMappingHandlerAdapter orExceptionHandlerExceptionResolver you can declare a WebMvcRegistrationsAdapter instance providing such components.

      If you want to take complete control of Spring MVC, you can add your own @Configuration annotated with @EnableWebMvc.如果你想保留Spring Boot MVC功能,并且你只想添加额外的MVC配置(拦截器,格式化程序,视图控制器等),你可以添加自己的@Configuration类类型WebMvcConfigurerAdapter,但没有 @EnableWebMvc。如果您希望提供自定义实例RequestMappingHandlerMappingRequestMappingHandlerAdapter或者ExceptionHandlerExceptionResolver您可以声明WebMvcRegistrationsAdapter 提供此类组件的实例。

      如果您想完全控制Spring MVC,可以添加自己的@Configuration 注释@EnableWebMvc

扩展springmvc(如果我们想要掌控mvc需要添加@EnabuleWebMvc)

  • 我理解的扩展springmvc的一个方向是把不带参数的静态资源映射,省略写那些空方法,只能用@Configuration,不能标注@EnableWebMvc,既保留了所有的自动配置,也能用我们扩展的配置,就是可以是一种对controller的一种优化

    package com.atguigu.springboot.config;
    
    import com.atguigu.springboot.component.LoginHandlerInterceptor;
    import com.atguigu.springboot.component.MyLocaleResolver;
    import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
    import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.LocaleResolver;
    import org.springframework.web.servlet.config.annotation.EnableWebMvc;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
    
    //使用WebMvcConfigurerAdapter可以来扩展SpringMVC的功能
    //@EnableWebMvc   不要接管SpringMVC
    @Configuration
    public class MyMvcConfig extends WebMvcConfigurerAdapter {
    
    
    
        @Override
        public void addViewControllers(ViewControllerRegistry registry) {
           // super.addViewControllers(registry);
            //浏览器发送 /atguigu 请求来到 success
            registry.addViewController("/atguigu").setViewName("success");
        }
    
        //所有的WebMvcConfigurerAdapter组件都会一起起作用
        @Bean //将组件注册在容器
        public WebMvcConfigurerAdapter webMvcConfigurerAdapter(){
            WebMvcConfigurerAdapter adapter = new WebMvcConfigurerAdapter() {
                @Override
                public void addViewControllers(ViewControllerRegistry registry) {
                    registry.addViewController("/").setViewName("login");
                    registry.addViewController("/index.html").setViewName("login");
                    registry.addViewController("/main.html").setViewName("dashboard");
                }
    
                //注册拦截器
                @Override
                public void addInterceptors(InterceptorRegistry registry) {
                    //super.addInterceptors(registry);
                    //静态资源;  *.css , *.js
                    //SpringBoot已经做好了静态资源映射
    //                registry.addInterceptor(new LoginHandlerInterceptor()).addPathPatterns("/**")
    //                        .excludePathPatterns("/index.html","/","/user/login");
                }
            };
            return adapter;
        }
    
        @Bean
        public LocaleResolver localeResolver(){
    
            return new MyLocaleResolver();
        }
    
    }
    
    
  • 扩展springmvc的原理

    1. WebMvcAutoConfiguration是springMvc的自动配置类

    2. 在做其他自动配置时候会导入@import(EnableWebMvcConfiguration.class)

      @Configuration
          public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration {
              private final WebMvcProperties mvcProperties;
              private final ListableBeanFactory beanFactory;
              private final WebMvcRegistrations mvcRegistrations;
      //从容器中获取所有的WebMvcConfigurer
              @Configuration
      public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
      
      	private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
      
      //自动装配,寻找ioc容器里面所有的
      	@Autowired(required = false)
      	public void setConfigurers(List<WebMvcConfigurer> configurers) {
      		if (!CollectionUtils.isEmpty(configurers)) {
                  //从容器中获取所有的WebMvcConfigurer和相关的配置都进行调用,意思就是
      			this.configurers.addWebMvcConfigurers(configurers);
      		}
      	}
      
      
    3. 容器中所有的WebMvcCongurer都会一起作用

    4. 我们的配置类同样也会被调用

    5. 效果就是:springmvc的自动配置和我们的扩展配置也会一起起作用

全面接管springmvc

  • springboot对springmvc的自动配置不需要了,所有的都是我们自己配置,所有的springmvc的自动配置都失效了,我们需要在配置类中添加@EnableWebMvc即可

  • 不推荐全面接管

  • 为什么使用这个注解就失效了呢

    @Import(DelegatingWebMvcConfiguration.class)
    public @interface EnableWebMvc {
    }
    
    
    @Configuration
    public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
    
    @Configuration
    @ConditionalOnWebApplication
    @ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurerAdapter.class})
    @ConditionalOnMissingBean({WebMvcConfigurationSupport.class})//容器中没有这个类的时候才起作用,
    @AutoConfigureOrder(-2147483638)
    @AutoConfigureAfter({DispatcherServletAutoConfiguration.class, ValidationAutoConfiguration.class})
    public class WebMvcAutoConfiguration {
    

    @EnableWebMvc将WebMvcConfigurationSupport组件导入进来

    导入的WebMvcConfigurationSupport只是具有springmvc的基本功能

修改springboot默认配置

1. springboot在自动配置很多组件的时候,先看容器中有没有用户自己配置的@

bean@component如果有就使用用户配置ide,如果没有,才自动配置,如果有些组件比如viewresolver将用户配置和自己默认的组合起来

  1. 在spring boot中会有非常多的configurer帮助我们进行扩展配置
  2. 在springboot中会有非常多的customizer帮助我们进行定制配置
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值