您的位置:首页 > 健康 > 美食 > 电商设计师需要掌握什么技能_好品质高端网站设计厂家_seo推广哪家好_营销软文范文

电商设计师需要掌握什么技能_好品质高端网站设计厂家_seo推广哪家好_营销软文范文

2025/5/7 20:52:18 来源:https://blog.csdn.net/postnull/article/details/147015455  浏览:    关键词:电商设计师需要掌握什么技能_好品质高端网站设计厂家_seo推广哪家好_营销软文范文
电商设计师需要掌握什么技能_好品质高端网站设计厂家_seo推广哪家好_营销软文范文

这是学透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

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com