当前位置: 首页 > wzjs >正文

南昌网站建设报价单在建工程项目查询

南昌网站建设报价单,在建工程项目查询,北京小程序制作首选华网天下,棋牌app开发多少钱这是学透Spring Boot的第14篇文章,更多文章请移步我的专栏: 学透 Spring Boot_postnull咖啡的博客-CSDN博客 目录 没有Spring Boot时的Spring MVC 使用Spring Boot后的Spring MVC Spring MVC的自动配置解析 明确目标 入口类 Spring容器的启动 S…

这是学透Spring Boot的第14篇文章,更多文章请移步我的专栏:

学透 Spring Boot_postnull咖啡的博客-CSDN博客

目录

没有Spring Boot时的Spring MVC

使用Spring Boot后的Spring MVC

Spring MVC的自动配置解析

明确目标

入口类

Spring容器的启动

Spring容器生命周期hook类

配置类解析类 ConfigurationClassParser

自动配置类列表 AutoConfiguration.imports

Spring MVC的自动配置类WebMvcAutoConfiguration

自动配置的视图解析器 

Http消息转换器自动配置类

数据源自动配置类 DataSourceAutoConfiguration

RestClient的自动配置 RestClientAutoConfiguration

嵌入式的web容器配置 

DispatcherServlet的自动配置

总结


没有Spring Boot时的Spring MVC

早些年还没有Spring Boot的时候,我们开发一个Spring MVC应用,需要做一大堆的配置,而且和其它的项目比较,这些配置大部分都是大同小异的,我们也可以称之为样板配置。

所以每次新建一个项目,我们通常是复制一个项目,然后复制这个项目的配置,做少量的修改,虽然没有什么太大的问题,但是如果一不小心改错,可能半天都找不到问题。

可以参考之前的一篇文章,里面介绍了没有Spring Boot时完整的手动配置。

学透Spring Boot — [二] Spring 和 Spring Boot的比较-CSDN博客

我们可以大概看看传统Spring MVC项目的配置

web.xml 中配置DispatchServlet

在 servlet-context.xml 中配置 Spring MVC 相关组件

这两份配置,非常冗余,因为绝大部分项目都大同小异。

最后再实现控制器

使用Spring Boot后的Spring MVC

如果使用Spring Boot,事情变得非常简单。

我们只要在我们的应用启动类添加一个注解 @SpringBootApplication

然后,所有的事情,SpringBoot都会自动帮我们完成。

简直是单车 到 摩托车的飞跃。

Spring MVC的自动配置解析

下面我们一步步来研究,Spring Boot是如何做到自动配置MVC的。

明确目标

自动配置的结果,就是把手动显示的配置,变成自动的配置。

比如servlet-context.xml中配置的视图解析器

Spring Boot 它会通过@Bean声明的方式,帮我们创建一个视图解析器的Bean

我们今天的任务,就是要搞清楚,Spring Boot在哪里以及什么时候,帮我创建的这个Bean。

入口类

首先我们的入口类,使用了一个注解@SpringBootApplication。

@SpringBootApplication
public class JoeLabApplication {public static void main(String[] args) {SpringApplication.run(JoeLabApplication.class, args);}
}

它其实是个组合注解。

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
public @interface SpringBootApplication {

我们重点关注@EnableAutoConfiguration 这个注解,它是一个总开关,开启了自动配置的新世界。

这个注解也是一个组合注解。

@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

通过@Import(AutoConfigurationImportSelector.class)这个注解,会触发自动配置类的导入,spring boot会用这个类去完成自动配置的功能。

Spring容器的启动

这次,我们先看看Spring Boot的启动,来分析自动配置是如何生效。

public class SpringApplication {public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {return run(new Class<?>[] { primarySource }, args);}
}

SpringBoot的run方法,会创建并刷新Spring容器。

public ConfigurableApplicationContext run(String... args) {context = createApplicationContext();context.setApplicationStartup(this.applicationStartup);prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);refreshContext(context); // 刷新 Spring 容器,加载各种 BeanafterRefresh(context, applicationArguments);startup.started();
}

关注:refreshContext(context); // 刷新 Spring 容器,加载各种 Bean

接着刷新容器

刷新容器的关键过程包括 Bean 的加载与初始化。refreshContext 方法会启动各类 Bean 的生命周期,调用 invokeBeanFactoryPostProcessors 来执行 BeanFactory 后处理器。

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors());if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean("loadTimeWeaver")) {beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));}
}

重点关注:invokeBeanFactoryPostProcessors

我们理解成Spring提供的生命周期钩子就行。通过这些钩子,我们可以在Spring启动过程中,做一些特殊的工作。比如自动化配置各种bean。

Spring容器生命周期hook类

其中Spring就提供了一个钩子类。

它是生命周期类,所以启动过程中自动被找到并执行。

public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor, BeanRegistrationAotProcessor, BeanFactoryInitializationAotProcessor, PriorityOrdered, ResourceLoaderAware, ApplicationStartupAware, BeanClassLoaderAware, EnvironmentAware {
}

这个类会去处理配置类 也就是加了@Configuration的类

    public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");parser.parse(candidates);parser.validate();}

配置类解析类 ConfigurationClassParser

接下来,它把任务交给了解析器——ConfigurationClassParser

最终这个解析工具类,通过一长串的调用链,最终到了另一个工具类ImportCandidates

public final class ImportCandidates implements Iterable<String> {public static ImportCandidates load(Class<?> annotation, ClassLoader classLoader) {Assert.notNull(annotation, "'annotation' must not be null");ClassLoader classLoaderToUse = decideClassloader(classLoader);String location = String.format(LOCATION, annotation.getName());Enumeration<URL> urls = findUrlsInClasspath(classLoaderToUse, location);List<String> importCandidates = new ArrayList<>();while (urls.hasMoreElements()) {URL url = urls.nextElement();importCandidates.addAll(readCandidateConfigurations(url));}return new ImportCandidates(importCandidates);}
}

我们重点看这一行代码

String location = String.format(LOCATION, annotation.getName());

其中:private static final String LOCATION = "META-INF/spring/%s.imports";

所以location是:META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

这个文件,在我们的自动配置模块下

自动配置类列表 AutoConfiguration.imports

我们把这个文件的内容罗列出来

是不是很多名字都似曾相识呢?

是的,这就是SpringBoot提供的自动配置类,对各种常用的组件,都提供了自动配置类。

SpringBoot在启动Spring容器的过程中,会定位到这个文件,然后逐个尝试去加载配置类。

Spring MVC的自动配置类WebMvcAutoConfiguration

我们先重点关注其中一个WebMvcAutoConfiguration

这个类提就是Spring MVC的自动配置类。

这个配置类会被找到,但是要不要加载,得看条件。条件配置就是它上面的注解。

我们逐条解析:

@AutoConfiguration(after = { DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
        ValidationAutoConfiguration.class }

DispatcherServlet配置完后,才会配置Spring MVC。

说得通,就像我们先配置web.xml中的DispatcherServlet,再配置Spring mvc的配置servlet.xml

@ConditionalOnWebApplication(type = Type.SERVLET)

必须是Spring MVC(Servlet)的web才会加载。

如果是WebFlux的web,就不会自动配置MVC。

@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })

Classpath下有这个两个类。

表示我们引入了Spring mvc的依赖。

@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)

只有当Spring容器没有WebMvcConfigurationSupport这个bean时,才会配置MVC。

因为这个Bean是用来给我们自定义的,如果我们不想用自动配置,而是想覆盖默认配置,我们就需要继承这个类。这样,SpringBoot就以我们配置的为主,而忽略自动配置。

这些条件,我们都满足,所以Spring Boot开始用这个类进行自动配置MVC。

这个配置类中定义了很多Bean,这些bean就是MVC的组件。

自动配置的视图解析器 

其中,就包含默认的视图解析器。

		@Bean@ConditionalOnMissingBeanpublic InternalResourceViewResolver defaultViewResolver() {InternalResourceViewResolver resolver = new InternalResourceViewResolver();resolver.setPrefix(this.mvcProperties.getView().getPrefix());resolver.setSuffix(this.mvcProperties.getView().getSuffix());return resolver;}

还记得我们在传统Spring MVC项目手动的配置吗?是的,我们做到了,通过自动创建Bean的方式,成功完成了视图解析器的配置。

我们在看看其它的自动配置类。

都定义在org.springframework.boot.autoconfigure.AutoConfiguration.imports这个文件下。

Http消息转换器自动配置类

@AutoConfiguration(after = { GsonAutoConfiguration.class, JacksonAutoConfiguration.class, JsonbAutoConfiguration.class })
@ConditionalOnClass(HttpMessageConverter.class)
@Conditional(NotReactiveWebApplicationCondition.class)
@Import({ JacksonHttpMessageConvertersConfiguration.class, GsonHttpMessageConvertersConfiguration.class,JsonbHttpMessageConvertersConfiguration.class })
@ImportRuntimeHints(HttpMessageConvertersAutoConfigurationRuntimeHints.class)
public class HttpMessageConvertersAutoConfiguration {

它导入了三种解析器

@Import({ JacksonHttpMessageConvertersConfiguration.class,         GsonHttpMessageConvertersConfiguration.class,JsonbHttpMessageConvertersConfiguration.class })

其中Jackson的是

		@Bean@ConditionalOnMissingBean(value = MappingJackson2HttpMessageConverter.class,ignoredType = {"org.springframework.hateoas.server.mvc.TypeConstrainedMappingJackson2HttpMessageConverter","org.springframework.data.rest.webmvc.alps.AlpsJsonHttpMessageConverter" })MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(ObjectMapper objectMapper) {return new MappingJackson2HttpMessageConverter(objectMapper);}

数据源自动配置类 DataSourceAutoConfiguration

	@Configuration(proxyBeanMethods = false)@Conditional(PooledDataSourceCondition.class)@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })@Import({ DataSourceConfiguration.Hikari.class, DataSourceConfiguration.Tomcat.class,DataSourceConfiguration.Dbcp2.class, DataSourceConfiguration.OracleUcp.class,DataSourceConfiguration.Generic.class, DataSourceJmxConfiguration.class })protected static class PooledDataSourceConfiguration {@Bean@ConditionalOnMissingBean(JdbcConnectionDetails.class)PropertiesJdbcConnectionDetails jdbcConnectionDetails(DataSourceProperties properties) {return new PropertiesJdbcConnectionDetails(properties);}}

RestClient的自动配置 RestClientAutoConfiguration

	@Bean@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)@ConditionalOnMissingBeanRestClient.Builder restClientBuilder(RestClientBuilderConfigurer restClientBuilderConfigurer) {return restClientBuilderConfigurer.configure(RestClient.builder());}

嵌入式的web容器配置 

@AutoConfiguration
@ConditionalOnNotWarDeployment
@ConditionalOnWebApplication
@EnableConfigurationProperties(ServerProperties.class)
public class EmbeddedWebServerFactoryCustomizerAutoConfiguration {/*** Nested configuration if Tomcat is being used.*/@Configuration(proxyBeanMethods = false)@ConditionalOnClass({ Tomcat.class, UpgradeProtocol.class })public static class TomcatWebServerFactoryCustomizerConfiguration {@Beanpublic TomcatWebServerFactoryCustomizer tomcatWebServerFactoryCustomizer(Environment environment,ServerProperties serverProperties) {return new TomcatWebServerFactoryCustomizer(environment, serverProperties);}@Bean@ConditionalOnThreading(Threading.VIRTUAL)TomcatVirtualThreadsWebServerFactoryCustomizer tomcatVirtualThreadsProtocolHandlerCustomizer() {return new TomcatVirtualThreadsWebServerFactoryCustomizer();}}

DispatcherServlet的自动配置

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

总结

我们这篇文章,从另一个角度——Spring容器的启动过程,结合SpringBoot提供的注解,理解了Spring Boot的自动配置原理。

最终定义到自动配置类的列表文件:

org.springframework.boot.autoconfigure.AutoConfiguration.imports

http://www.dtcms.com/wzjs/572136.html

相关文章:

  • 中国建设银行网站登录不了建设英文网站多少钱
  • 加油站网站建设常用网站推荐
  • 书店网站建设规划书中国网站用Cn域名
  • 嘉盛建设集团官方网站做一个信息发布网站要多少钱
  • 企业门户网站建设机构杭州有专业做网站小型服装厂吗
  • 重庆网络公司网站建设wordpress5.2火车头发布
  • 苏州公司网站建设公司企业网站建设主要类型及选择
  • 织梦的网站收录不好自己做一个app
  • 福州最好的网站建设网络公司文章 wordpress
  • 怎么能创建自己的网站永康网站开发
  • win本地网站建设网站开发维护关键技术
  • 网站开发项目成本分析之合理性自建网站如何在百度上查到
  • 长沙做网站zwnet移动互联网技术网站
  • net网站开发花卉物流园做网站的素材
  • 教育资源网站建设网站设计建设介绍
  • 网站伪静态怎么做南宁网站建设优化排名
  • 如何设置网站的默认页外包做网站公司
  • 一级a做片性视频网站查询网站备案显示划横线
  • 咸阳做网站开发公司哪家好做国际贸易的一般用什么平台
  • 做网站需学什么重庆旅游网站建设规划
  • 企业网站优化做公司网站需要准备什么
  • 做盗版网站的中小学生在线做试卷的网站
  • 临沂建设质量监督站网站佛山大良营销网站建设
  • 网站地图怎么做的软文发布平台排名
  • 网站维护和制作怎么做会计分录个人可以做哪些网站
  • 漳州模板网站建设网站推广方案总结
  • php网站源码免费下载郑州新闻头条最新消息
  • 网站开发公司分析手机编程软件python
  • 网站邮件发送功能怎么做dk域名网站
  • 网站上的广告位是怎么做的杭州网站