SprignBoot中的一些小知识点(一)

1、@Configuration 的 proxyBeanMethods 属性,意思是不是代理bean的方法。

proxyBeanMethods 属性默认为true,则为代理bean,且代理bean中的方法。所以,无论获取多少遍该配置类或者该配置类中的方法,均为单例。
若为 false,则Spring容器中不会保留该配置类的dailiduixi9ang,每次获取的配置类对象不同,方法也不同。

  总结:配置类组件之间无依赖关系,用 false,加速容器启动过程,减少判断。

       配置类组件之间有依赖关系,用true,方法被调用得到之前的单实例组件。

2、@Conditional   条件加载绑定

         条件装配的魅力,SpringBoot底层按需加载机制用到很多condition系列的注解,可以去详细看一下。

3、@ConfigurationProperties + @Component (加在容器中 并 进行属性绑定)

           加载配置文件中的属性到实体类。

4、SpringBoot 的自动配置原理:

      @SpringBootApplication  分为:

@SpringBootConfiguration :我是一个配置类。
@EnableAutoConfiguration :利用Register 给容器导入一系列组件,将指定包下的所有组件导入,也就是根目录下的所有的类。其下有一个功能,就是加载 所有 META-INF/spring.factories  下的所有组件,另外得益于Conditional 注解,按需加载的              机制,很好的限制了SpringBoot容器中的组件个数,举例来说:当引入了某个jar后 才会加载该组件。 
@ComponentScan :标识作为一个组件。

5、SpringBoot会在底层配置好所有组件,但是如果用户想自己配置了,则以用户配置的优先。

6、yaml 配置文件加入debug=true ,启动项目时会打印哪些组件生效(positive),那些组件不生效(negative)

7、Springboot 关于整合SpringMVC的一些概念知识

1、静态资源路径概念:
默认:只要静态资源放在以下类路径下:/static or /public or /resource or /MET-INF/resources 下,访问静态资源时只需 在当前项目根路径 / + 静态资源文件名 即可
原理: 静态映射配置的 /**
请求进来,先去找Controller 试下能不能处理,不能处理的请求进一步交给静态资源处理器,静态资源再找不到直接404
2、修改静态资源前缀:web项目一般都会有未登录不让访问动态资源的拦截器校验,为了不让拦截器一起把静态资源也拦截掉,就统一给静态资源添加一个例如 /res 前缀,然后在拦截器中放开 /res 路径访问权限,这样就可以实现只拦截动态资源访问,不拦截静态资源。
实现以上功能只需在yaml中配置 spring.mvc.static-path-pattern: /res/**
添加/res配置后不需要在静态资源访问目录加/res
3、限制静态资源存储目录:开发中,我们如果想要把所有的静态资源全部放到 /haha 目录下,只需在yaml中添加 spring.resources.static-locations: classpath:/haha/  即可 或者数组 spring.resources.static-locations: [classpath:/haha/,classpath:/hehe/]

8、SpringBoot 集成SpringMVC 底层静态资源配置

SpringMVC配置类主要集中在:WebMvcAutoConfiguration 这个配置类中,

目录:/org/springframework/boot/spring-boot-autoconfigure/2.4.5/spring-boot-autoconfigure-2.4.5.jar!/org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.class
我们进入WebMvcAutoConfiguration类中的一个静态内部类:WebMvcAutoConfigurationAdapter ,注意到该内部类只有一个构造方法:

public WebMvcAutoConfigurationAdapter(WebProperties webProperties, WebMvcProperties mvcProperties, ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider, ObjectProvider<WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider, ObjectProvider<DispatcherServletPath> dispatcherServletPath, ObjectProvider<ServletRegistrationBean<?>> servletRegistrations) {
            this.mvcProperties = mvcProperties;
            this.beanFactory = beanFactory;
            this.messageConvertersProvider = messageConvertersProvider;
            this.resourceHandlerRegistrationCustomizer = (WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer)resourceHandlerRegistrationCustomizerProvider.getIfAvailable();
            this.dispatcherServletPath = dispatcherServletPath;
            this.servletRegistrations = servletRegistrations;
            this.mvcProperties.checkConfiguration();
        }

约定的规则就是:配置类如果只有一个有参构造器,那么构造方法中所有参数的值都会从容器中寻找。 

WebProperties webProperties :在内部类的 @EnableConfigurationProperties 注解上已经绑定 WebProperties 到容器中,直接在容器中获取即可 

WebMvcProperties mvcProperties:同上一个

 ListableBeanFactory beanFactory:相当于Spring的bean 工厂 

ObjectProvider<HttpMessageConverters> messageConvertersProvider:找到所有httpMessageConverter

ObjectProvider<WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider:资源处理器的自定义器

ObjectProvider<DispatcherServletPath> dispatcherServletPath, ObjectProvider<ServletRegistrationBean<?>> servletRegistrations:给用注册sevlet、Filter,后来再说

 好的,我们继续在类中寻找与静态资源配置相关的方法:

// addResourceHandlers 顾名思义:添加静态资源处理器
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
            super.addResourceHandlers(registry);
            if (!this.resourceProperties.isAddMappings()) {
                logger.debug("Default resource handling disabled");
            } else {
                ServletContext servletContext = this.getServletContext();
                this.addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");
                this.addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
                    registration.addResourceLocations(this.resourceProperties.getStaticLocations());
                    if (servletContext != null) {
                        registration.addResourceLocations(new Resource[]{new ServletContextResource(servletContext, "/")});
                    }

                });
            }
        }

所以:所有静态资源处理规则就在这个方法了,不难看出第一个判断,this.resourceProperties.isAddMappings() ,获取了容器中 resourceProperties 的addMapping 这个 布尔类型的数据

为true 就往下加载静态配置类的规则。

     配置了webjars的访问路径(前端的一些js引用也达成了jar供项目引入 )

     包括设置静态资源缓存配置时间配置

      包括配置静态资源默认的路径  

                this.addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
                    registration.addResourceLocations(this.resourceProperties.getStaticLocations());
                    if (servletContext != null) {
                        registration.addResourceLocations(new Resource[]{new ServletContextResource(servletContext, "/")});
                    }

                });

// 点进 this.mvcProperties.getStaticPathPattern(),很容易看到配置了如下几个默认的四个静态资源路径
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};
 

为fale 就直接 在degug级别打印日志 说:默认资源处理器失效,仅用所有静态资源规则,不再允许访问所有的静态资源。

注:(这个 addMapping 就是 配置文件中 spring.web.resources.add-mappings 对应的值)

 我们再看一下,SpringBoot 底层封装SpringMVC如何处理欢迎页静态资源的。

继续在  WebMvcAutoConfiguration 这个类中 找到  welcomePageHandlerMapping ,顾名思义 这是欢迎页处理器映射,

        @Bean
        public WelcomePageHandlerMapping welcomePageHandlerMapping(ApplicationContext applicationContext, FormattingConversionService mvcConversionService, ResourceUrlProvider mvcResourceUrlProvider) {
            WelcomePageHandlerMapping welcomePageHandlerMapping = new WelcomePageHandlerMapping(new TemplateAvailabilityProviders(applicationContext), applicationContext, this.getWelcomePage(), this.mvcProperties.getStaticPathPattern());
            welcomePageHandlerMapping.setInterceptors(this.getInterceptors(mvcConversionService, mvcResourceUrlProvider));
            welcomePageHandlerMapping.setCorsConfigurations(this.getCorsConfigurations());
            return welcomePageHandlerMapping;
        }

我们进入 new WelcomePageHandlerMapping(..) 这个有参构造:

    WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders, ApplicationContext applicationContext, Resource welcomePage, String staticPathPattern) {
        //第一行判断代码的意思就是:当欢迎页存在 且 静态资源路径为  /** 的时候,才会跳转欢迎页面
        if (welcomePage != null && "/**".equals(staticPathPattern)) {
            logger.info("Adding welcome page: " + welcomePage);
            this.setRootViewName("forward:index.html");
        } else if (this.welcomeTemplateExists(templateAvailabilityProviders, applicationContext)) {
            //否则,他会去找Controller 找一下,谁能处理
            logger.info("Adding welcome page template: index");
            this.setRootViewName("index");
        }

    }
原文地址:https://www.cnblogs.com/dk1024/p/14794305.html