SpringBoot源码分析

1.自动配置原理

首先我们进入@SpringBootApplication这个注解

我们会发现里面又这三个注解

@SpringBootConfiguration

这个注解点进去有@Configuration这个注解,再进去有@Component这个注解,主要告诉我们这个类是一个spring配置、组件。(参照spring 的javaConfig 类配置方式)

@ComponentScan

这个注解是spring扫描注解,用来扫描某个路径下的java类是否符合条件,若符合条件就会注入到ioc容器中,在这里是给这个注解添加两个ExcludeFilter

(条件是类上有没有@Component注解,当然@Controller、@Service也算,因为他们内部也有@Component注解)

@EnableAutoConfiguration

我们重点看一下这个注解,开启自动配置

进入这个注解

这两个注解需要看一下

@AutoConfigurationPackage

点进去,我们发现,它引入了Registrar.class这样一个组件(@Import注解在传统的xml配置文件里就是import标签,引入别的配置文件,在javaConfig中,就是引入一个Configuration,也就是一个组件Component)

点进Registerar.class

这里面的结构是一个抽象类,AutoConfigurationPackages,抽象类里有Registrar引入的这个类。

这里面的两个方法,

第一个方法是把@AutoConfigurationPackage这个注解下的类的包路径下的所有带有@Component注解的类作为组件找出来。

第二个方法是把刚刚找出来的组件加载到ioc容器中。

我们再看一下导入的这个组件AutoConfigurationImportSelector.class,重点

获取所有配置方法

进入getAutoConfigurationEntry()方法,这个方法是获取所有实体(就是 配置 封装的实体)

进入getCandidateConfigurations() ,获取所有候选配置

所有的候选配置在

spring.factories文件里,这里面写着springboot所有可以自动配置的组件

比如说springmvc,打开spring.factories文件,里面有一堆自动配置的路径,每一行代表一个组件,找到这个

org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
点进去,会发现它就是一个javaConfig。里面给我们配好了,handlerMapping 、handlerAdapter、viewResolver、DispatcherServlet等springmvc所有需要的组件。也就是说,把这个组件配置进spring容器,springmvc就相当于配置好了。

这上面带Conditional的注解都是是否把这个配置类引入spring容器的条件,条件满足才引入。

补充:

application.yml里的配置是如何实现的。

比如说,tomcat的端口号配置,    server.port    这个配置默认是8080

去搜ServerProperties这个类,就明白了。

javaConfig类上有这个注解@ConfigurationProperties(prefix = "server")   这样的就可以在application.yml;里配置了。

(另外,spring-configuration-metadata.json这里配置了所有application.yml里的默认配置。比如server.port之类的配置)

 

回过头来,我们再看loadFactoryNames方法,大概意思就是从spring.factories文件里把所有配置都加载出来。

2.springboot中web模块的研究

在springboot中,web模块是核心模块,其实就是集成了springmvc。

我们在依赖中找到这个文件,所有的自动配置写在这里

打开

找到这个配置,这就是web模块的自动配置类,点进去

先看它的注解,第1个配置注解,说明这个类是一个spring配置。第2、3、4个注解带Conditional的,对照上面的表。

@AutoConfigureOrder注解规定了此配置加载到spring容器的顺序。

@AutoConfigureAfter是加载完此配置,然后再去加载的东西,dispatcherServlet、任务执行模块、校验模块。

 

1)添加静态资源处理器

这个东西是springmvc的一部分。如果对springmvc的原理清楚的话,应该知道,所有的客户端请求都会先经过dispatcherServlet,但是请求会有两种情况,第一种是请求handler进行业务处理,第二种是请求js、css、jpg等静态资源。处理静态资源的请求就需要下面这个资源处理器来处理了。

        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            if (!this.resourceProperties.isAddMappings()) {
                logger.debug("Default resource handling disabled");
            } else {
                Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
                CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
                if (!registry.hasMappingForPattern("/webjars/**")) {
                    this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{"/webjars/**"}).addResourceLocations(new String[]{"classpath:/META-INF/resources/webjars/"}).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
                }

                String staticPathPattern = this.mvcProperties.getStaticPathPattern();
                if (!registry.hasMappingForPattern(staticPathPattern)) {
                    this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern}).addResourceLocations(WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
                }

            }
        }

前三行的意思是,如果在application.yml里面有spring.resources的配置的话,默认配置就失效。

后面写了两种获取静态资源的方式。

#   1.通过webjars寻找静态资源(一般不用)

webjars的一些东西,webjars就是可以通过maven引入前端的一些东西如jquery  angular等js。具体maven坐标可以去webjars官网去找。引入后,它添加了一个handler,它的requestMapping是    /webjars/**       映射的物理地址是classpath:/META-INF/resources/webjars/

/webjars/**    映射到     物理路径classpath:/META-INF/resources/webjars/

举例,在浏览器中搜索,http://localhost:8080/webjars/angular/1.7.9/angular.js,由于/webjars/angular匹配上了/webjars/**     springmvc就会到物理路径    classpath:/META-INF/resources/webjars/     下去寻找angular/1.7.9/angular.js

#   2.  通过静态资源路径  寻找静态资源

String staticPathPattern = this.mvcProperties.getStaticPathPattern();

的意思是获取mvcProperties配置类中的静态资源的匹配路径。点进去,我们会发现默认值是   /**    

添加路径时是从这里获取的this.resourceProperties.getStaticLocations()

点进去private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};     (他们几个有优先级)

这里有四个都是默认的资源路径。也就是会去这四个路径下面去寻找 /**   的静态资源。

总结一下,就是  请求路径里的   /**      映射到物理路径    CLASSPATH_RESOURCE_LOCATIONS这几个路径

 

举例,比如,  http://localhost:8080/1.txt      因为   /1.txt   和    /**匹配,所以就会去  映射的物理路径里去找静态资源。

 

2)欢迎页的配置

欢迎页就是index.html页面,就是web项目里的默认页面。也就是只写localhost:8080/   会请求到的页面。这个东西之前是在web.xml里配置的。

       @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));
            return welcomePageHandlerMapping;
        }

        private Optional<Resource> getWelcomePage() {
            String[] locations = WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations());
            return Arrays.stream(locations).map(this::getIndexHtml).filter(this::isReadable).findFirst();
        }

        private Resource getIndexHtml(String location) {
            return this.resourceLoader.getResource(location + "index.html");
        }

大概意思是把"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"   路径下的index.html设置为欢迎页。

但是一般我们不这么做,我们会写一个controller来跳转index页面。

另外,还有一个classpath:/template 目录  这个相当于  之前的WEB-INF目录,不能直接访问里面的静态资源,只能通过Controller间接访问。

3)模板引擎的使用

模板引擎就是用来替代jsp的,这种技术用来在服务端把数据渲染到页面上。springboot推荐使用thymeleaf模板,先在pom里引入依赖。

我们查找一下ThymeleafProperties这个类,这个类里有thymeleaf的配置。

@Configurationproperties  注解  spring.thymeleaf 

说明可以在application.yml里通过这个配置。

服务端的视图解析器找模板文件的前缀和后缀,这个和jsp很像。之前用jsp时,prefix是  /WEB-INF/jsp/   suffix是 .jsp

http://localhost:8080/helloThymeLeaf     通过controller  找到模板文件。和jsp一样。

4)视图解析器

我们打开这个接口WebMvcConfigurer,这里面是springmvc的配置。视图解析器的配置就在里面。

找到ViewResolverRegistry-》ContentNegotiatingViewResolver-》ViewResolver

ViewResolver是一个接口,只要实现了这个接口的类就是视图解析器了。

这个接口只有一个方法resolveViewName。找到实现类里这个方法。里面有个getCandidateViews获取候选视图方法。这里面会遍历viewResolvers(从ioc容器里获取的)所有视图解析器,选择其中一个最好的,来获取候选视图。

找到DispatcherServlet类,里有个doDispatch方法,这里面就是,dispatcherServlet从接收请求到调用handlerMapping、handlerAdapter、viewResolver等的全部过程,打个断点,看断点里的this会发现

里面又很多视图解析器,其中前两个是默认就有的,第三个是Thymeleaf的,第四个是我自定义的。

 

3.主配置类启动流程

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值