SpringBoot

目录

@Configuration注解

@Import

@Conditional

 @ImportResource("classpath:bean.xml")导入spring的配置文件

@EnableConfigurationProperties(MySQLDialect.class)

SpringBoot自动配置原理

@SpringBootConfiguration

@ComponentScan

###@EnableAutoConfiguration

@AutoConfigurationPackage

@Import({AutoConfigurationImportSelector.class})

按需开启自动配置项

修改默认配置

静态资源配置原理

配置类只有一个有参构造器

静态资源访问的默认规则

欢迎页的处理规则

请求映射原理


主启动类只会扫描同包及其子包。可以设置这个字段来指定扫描的基准包。

 SpringBoot的自动配置功能,都在spring-boot-autoconfigure中

<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-autoconfigure</artifactId>
     <version>2.2.4.RELEASE</version>
     <scope>compile</scope>
</dependency>
@SpringBootApplication注解的组成
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration    //SpringBoot配置
@EnableAutoConfiguration   //配置自动注入的注解
@ComponentScan(     //配置包扫描的
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {

@Configuration注解

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";
     //默认是true,当设置为true时,在需要用到该组件时,会先去容器找是否存在,没有再创建
     //可以保持组件的单实例。
     //使用的是cglib代理
    boolean proxyBeanMethods() default true; 

}

当proxyBeanMethods设置为true时,为Full模式,反之为Lite模式

在配置类组件组件无依赖关系用Lite模式,加速启动,减少判断。

在配置类组件有依赖关系,方法会被调用得到之前单实例组件,用Full模式。

@Import

//给容器中自动创建出这两个类型的组件,默认组件的名字就是全类名
@Import({Math.class, MySQLDialect.class})

@Conditional

条件装配:满足Conditional指定的条件,则进行组件注入。

 @ImportResource("classpath:bean.xml")导入spring的配置文件。

@ConfigurationProperties(prefix = "mycar") 将javaBean中的属性和配置文件一一绑定,不过这个javaBean必须在容器中。

@EnableConfigurationProperties(MySQLDialect.class)

  1. 开启MySQLDialect配置绑定功能
  2. 把这个MySQLDialect组件自动注册到容器中
  3. 第三方包可以这样使用。

SpringBoot自动配置原理

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication

@SpringBootConfiguration

代表当前是一个配置类

@ComponentScan

指定扫描哪些包。

###@EnableAutoConfiguration

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

@AutoConfigurationPackage

自动配置包?

@Import({Registrar.class})      //给容器中导入一个组件
public @interface AutoConfigurationPackage {

//利用Registrar给容器中导入一系列组件:registerBeanDefinitions()
//将指定的一个包下的所有组件导入进来:SpringDemoApplication所在包下。
static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
        Registrar() {
        }

        public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
            AutoConfigurationPackages.register(registry, (new AutoConfigurationPackages.PackageImport(metadata)).getPackageName());
        }

        public Set<Object> determineImports(AnnotationMetadata metadata) {
            return Collections.singleton(new AutoConfigurationPackages.PackageImport(metadata));
        }
    }

@Import({AutoConfigurationImportSelector.class})

1、利用getAutoConfigurationEntry(autoConfigurationMetadata, annotationMetadata);给容器中批量导入一些组件
2、调用List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);获取到所有需要导入到容器中的配置类
3、利用工厂加载 Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) :得到所有组件
4、Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
从META-INF/spring.factories位置来加载一个文件
      默认扫描我们当前系统里面所有META-INF/spring.factories位置的文件
      spring-boot-autoconfigure-2.5.3.jar包里面也有META-INF/spring.factories
      文件下面写死了所有需要导入的组件

spring-boot-autoconfigure-2.5.3.jar/META-INF/spring.factories
文件里面写死了spring-boot一启动就要给容器中加载的所有配置类
# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration,\
org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jReactiveDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jReactiveRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration,\
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration,\
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration,\
org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration,\
org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration,\
org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
org.springframework.boot.autoconfigure.jsonb.JsonbAutoConfiguration,\
org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration,\
org.springframework.boot.autoconfigure.netty.NettyAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration,\
org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration,\
org.springframework.boot.autoconfigure.r2dbc.R2dbcTransactionManagerAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketRequesterAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketServerAutoConfiguration,\
org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.servlet.SecurityFilterAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration,\
org.springframework.boot.autoconfigure.security.rsocket.RSocketSecurityAutoConfiguration,\
org.springframework.boot.autoconfigure.security.saml2.Saml2RelyingPartyAutoConfiguration,\
org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.servlet.OAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.client.reactive.ReactiveOAuth2ClientAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.servlet.OAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.security.oauth2.resource.reactive.ReactiveOAuth2ResourceServerAutoConfiguration,\
org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration,\
org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration,\
org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.ReactiveWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.error.ErrorWebFluxAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.ClientHttpConnectorAutoConfiguration,\
org.springframework.boot.autoconfigure.web.reactive.function.client.WebClientAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.reactive.WebSocketReactiveAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration,\
org.springframework.boot.autoconfigure.websocket.servlet.WebSocketMessagingAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration,\
org.springframework.boot.autoconfigure.webservices.client.WebServiceTemplateAutoConfiguration

按需开启自动配置项

虽然我们所有的场景的自动配置启动的时候默认全部加载。
按照条件装配规则,最终会按需配置

@Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnClass({Advice.class})
    static class AspectJAutoProxyingConfiguration {

@ConditionalOnClass({Advice.class}):必须存在org.aspectj.weaver.Advice类才能将配置注册进容器。

修改默认配置

@Bean
@ConditionalOnBean({MultipartResolver.class})  //容器中有这个类型的组件
@ConditionalOnMissingBean(
    name = {"multipartResolver"}   //容器中没有multipartResolver这个名字的组件
)
public MultipartResolver multipartResolver(MultipartResolver resolver) {
    //给@Bean标注的方法传入了对象参数,这个参数的值就会从容器中找
    //防止有些用户配置文件上传解析器不符合规范
    return resolver;
}
给容器中加入了文件上传解析器;

springboot会在底层配好所有的组件。但是如果用户自己配置了以用户配置的优先

@Bean
@ConditionalOnMissingBean
public CharacterEncodingFilter characterEncodingFilter() {

总结:

  • SpringBoot先加载所有的自动配置类    xxxAutoConfiguration
  • 每个自动配置类按照条件进行生效,默认都会绑定配置文件指定的值   xxxProperties里面拿。xxxProperties和配置文件进行了绑定
  • 生效的配置类就会给容器中装配很多组件
  • 只要容器中有这些组件,相当于这些功能就有了
  • 定制化配置      
  •       用户直接自己@Bean替换底层的组件
  •       用户去看这个组件是获取的配置文件什么值就去修改

xxxAutoConfiguration------->组件-------->xxxProperties里面拿值------->application.properties

@EnableAutoConfiguration自动配置的魔法其实就变成了:

从classpath中搜寻所有的META-INF/spring.factories配置文件,并将其中org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的配置项通过反射(Java Refletion)实例化为对应的标注了@Configuration的JavaConfig形式的IoC容器配置类,然后汇总为一个并加载到IoC容器。
 

静态资源配置原理

SpringMVC功能的自动配置类 WebMvcAutoConfiguration,生效

@Configuration(
    proxyBeanMethods = false
)
@ConditionalOnWebApplication(
    type = Type.SERVLET
)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
@AutoConfigureOrder(-2147483638)
@AutoConfigureAfter({DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class})
public class WebMvcAutoConfiguration {}

给容器中配了什么

@Configuration(
   proxyBeanMethods = false
)
@Import({WebMvcAutoConfiguration.EnableWebMvcConfiguration.class})
@EnableConfigurationProperties({WebMvcProperties.class, ResourceProperties.class, WebProperties.class})
@Order(0)
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer, ServletContextAware {}

配置文件的相关属性和xxx进行了绑定,WebMvcProperties==spring.mvc、ResourceProperties==spring.resources、WebProperties==spring.web

配置类只有一个有参构造器

  有参构造器的所有参数的值都会从容器中确定
  ResourceProperties resourceProperties:获取和spring.resource绑定的所有的值的对象
  WebProperties webProperties:获取和spring.web绑定的所有的值的对象
  WebMvcProperties mvcProperties:获取和spring.mvc绑定的所有的值的对象
  ListableBeanFactory beanFactory:spring的bean工厂
  ObjectProvider<HttpMessageConverters>:找到所有的HttpMessageConverters
  ResourceHandlerRegistrationCustomizer:找到资源处理器的自定义器
  dispatcherServletPath
  servletRegistrations:给应用注册Servlet、filter....
public WebMvcAutoConfigurationAdapter(ResourceProperties resourceProperties, WebProperties webProperties, WebMvcProperties mvcProperties, ListableBeanFactory beanFactory, ObjectProvider<HttpMessageConverters> messageConvertersProvider, ObjectProvider<WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer> resourceHandlerRegistrationCustomizerProvider, ObjectProvider<DispatcherServletPath> dispatcherServletPath, ObjectProvider<ServletRegistrationBean<?>> servletRegistrations) {
            this.resourceProperties = (Resources)(resourceProperties.hasBeenCustomized() ? resourceProperties : webProperties.getResources());
            this.mvcProperties = mvcProperties;
            this.beanFactory = beanFactory;
            this.messageConvertersProvider = messageConvertersProvider;
            this.resourceHandlerRegistrationCustomizer = (WebMvcAutoConfiguration.ResourceHandlerRegistrationCustomizer)resourceHandlerRegistrationCustomizerProvider.getIfAvailable();
            this.dispatcherServletPath = dispatcherServletPath;
            this.servletRegistrations = servletRegistrations;
            this.mvcProperties.checkConfiguration();
        }

静态资源访问的默认规则

public void addResourceHandlers(ResourceHandlerRegistry registry) {
            if (!this.resourceProperties.isAddMappings()) {
                logger.debug("Default resource handling disabled");
            } else {
                webjars的规则
                this.addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");
                this.addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
                    registration.addResourceLocations(this.resourceProperties.getStaticLocations());
                    if (this.servletContext != null) {
                        ServletContextResource resource = new ServletContextResource(this.servletContext, "/");
                        registration.addResourceLocations(new Resource[]{resource});
                    }

                });
            }
        }

静态资源路径默认的四个位置

private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};

欢迎页的处理规则

HandleMapping:处理器映射,保存了每一个Handler能处理哪些请求。

@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;
        }




WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders, ApplicationContext applicationContext, Optional<Resource> welcomePage, String staticPathPattern) {
        if (welcomePage.isPresent() && "/**".equals(staticPathPattern)) {
            //  要使用欢迎页功能,必须是/**
            logger.info("Adding welcome page: " + welcomePage.get());
            this.setRootViewName("forward:index.html");
        } else if (this.welcomeTemplateExists(templateAvailabilityProviders, applicationContext)) {
            //如果欢迎页存在并且默认路径不是/**,将由Controller处理,看谁能处理/index请求
            logger.info("Adding welcome page template: index");
            this.setRootViewName("index");
        }

    }

Rest原理(表单提交要使用REST的时候)

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        HttpServletRequest requestToUse = request;
        //判断提交方式是否是POST并且请求正确
        if ("POST".equals(request.getMethod()) && request.getAttribute("javax.servlet.error.exception") == null) {
            //得到_method的值
            String paramValue = request.getParameter(this.methodParam);
            if (StringUtils.hasLength(paramValue)) {
                String method = paramValue.toUpperCase(Locale.ENGLISH);
                if (ALLOWED_METHODS.contains(method)) {
             //返回的包装的HttpMethodRequestWrapper,method会替换成自己的请求方式,重写了getMethod方法
                    requestToUse = new HiddenHttpMethodFilter.HttpMethodRequestWrapper(request, method);
                }
            }
        }

        filterChain.doFilter((ServletRequest)requestToUse, response);
    }

    static {
       //可以执行的请求
        ALLOWED_METHODS = Collections.unmodifiableList(Arrays.asList(HttpMethod.PUT.name(), HttpMethod.DELETE.name(), HttpMethod.PATCH.name()));
    }

表单提交会带上_method=PUT

请求过来会被HiddenHttpMethodFilter拦截

请求如果正常,并且是POST

获取到_method的值

兼容以下请求:

原生Request(post),包装模式HttpMethodRequestWrapper重写 getMethod(),返回的是传入的method值。

过滤器链放行的时候用HttpMethodRequestWrapper。以后的方法调用getMethod是调用HttpMethodRequestWrapper的

Rest使用客户端工具直接发送,就和上面的流程没有关系。

请求映射原理

 doDispach方法

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
		HttpServletRequest processedRequest = request;
		HandlerExecutionChain mappedHandler = null;
		boolean multipartRequestParsed = false;

		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

		try {
			ModelAndView mv = null;
			Exception dispatchException = null;

			try {
				processedRequest = checkMultipart(request);
				multipartRequestParsed = (processedRequest != request);

				// 得到可以处理当前请求的handler(Controller)处理器
				mappedHandler = getHandler(processedRequest);
				if (mappedHandler == null) {
					noHandlerFound(processedRequest, response);
					return;
				}

				// Determine handler adapter for the current request.
				HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

				// Process last-modified header, if supported by the handler.
				String method = request.getMethod();
				boolean isGet = "GET".equals(method);
				if (isGet || "HEAD".equals(method)) {
					long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
					if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
						return;
					}
				}

				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
					return;
				}

				// Actually invoke the handler.
				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

				if (asyncManager.isConcurrentHandlingStarted()) {
					return;
				}

				applyDefaultViewName(processedRequest, mv);
				mappedHandler.applyPostHandle(processedRequest, response, mv);
			}
			catch (Exception ex) {
				dispatchException = ex;
			}
			catch (Throwable err) {
				// As of 4.3, we're processing Errors thrown from handler methods as well,
				// making them available for @ExceptionHandler methods and other scenarios.
				dispatchException = new NestedServletException("Handler dispatch failed", err);
			}
			processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
		}
		catch (Exception ex) {
			triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
		}
		catch (Throwable err) {
			triggerAfterCompletion(processedRequest, response, mappedHandler,
					new NestedServletException("Handler processing failed", err));
		}
		finally {
			if (asyncManager.isConcurrentHandlingStarted()) {
				// Instead of postHandle and afterCompletion
				if (mappedHandler != null) {
					mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
				}
			}
			else {
				// Clean up any resources used by a multipart request.
				if (multipartRequestParsed) {
					cleanupMultipart(processedRequest);
				}
			}
		}
	}
通过此方法遍历所有的handler,找到可以处理当前请求的handler
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
		if (this.handlerMappings != null) {
			for (HandlerMapping mapping : this.handlerMappings) {
				HandlerExecutionChain handler = mapping.getHandler(request);
				if (handler != null) {
					return handler;
				}
			}
		}
		return null;
}

RequestMappingHandlerMapping:保存了所有@RequestMapping和handler的映射规则

请求处理:各种类型参数解析原理

HandlerMapping中找到能处理请求的handler(Controller.method)

为当前handler找到一个适配器HandlerAdapter:默认找到RequestMappingHandlerAdapter

 执行目标方法

//DispatcherServlet中doDispatch方法中,执行目标方法的地方
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

//ha.handle()中真正执行目标方法的地方
mav = this.invokeHandlerMethod(request, response, handlerMethod);

//执行目标方法的地方,ServletInvocableHandlerMethod类下
Object returnValue = this.invokeForRequest(webRequest, mavContainer, providedArgs);

参数解析器

确定将要执行目标方法的每一个参数的值是什么

    

第一步先判断当前解析器是否支持解析这种参数

第二步支持就调用resolveArgument

返回值处理器

SpringBoot启动原理

1、创建SpringApplication

  • 保存一些信息。
  • 判定当前应用类型。ClassUtils,servlet
  • 初始化器:去spring.factoriesApplicationContextInitializer,找到之后保存在当前对象Initializer中:      this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
  • ApplicationListener:应用监听器  spring.factories

2、运行SpringApplication

1.StopWatch

2.记录应用的启动时间

3.让当前应用进入headless模式。java.awt.headless

4.获取所有Runlistener(运行监听器)【为了方便所有Listener进行事件感知】

  • getSpringFactoriesInstances()去spring.factoriesSpringApplicationRunlistener.class

5.遍历所有的SpringApplicationRunlistener调用starting方法;

  • 相当于通知所有感兴趣系统正在启动过程的人,项目正在starting

6.保存命令行参数:ApplicationArguments

7.准备环境prepareEnvironment();

  • 返回或创建基础环境信息。StandardServletEnvironment
  • 配置环境信息对象。
  • 读取所有的配置源的配置属性值。
  • 绑定环境信息
  • 监听器调用listener.environmentPrepared:通知所有的监听器当前环境准备完成

8.创建IOC容器(createApplicationContext())

  • 根据项目类型(Servlet)创建容器
  • 当前会创建AnnotationConfigServletWebServerApplicationContext

9.准备ApplicationContext IOC容器的基本信息 prepareContext()

  • 保存环境信息
  • IOC后置处理流程
  • 应用初始化器:applyInitializers;遍历所有的ApplicationContextInitializer,调用initialize来对ioc容器进行初始化扩展功能
  • 遍历所有的listener调用contextPrepared。EventPublishRunListener;通知所有的监听器contextPrepared
  • 所有监听器调用contextLoaded。通知所有的监听器contextLoaded;

10.刷新IOC容器。refreshContext

  • 创建容器中的所有组件

11.容器刷新完成后工作?afterRefresh

12.所有监听器调用listeners.started(context);通知所有的监听器contextPrepared

13.调用所有的runners;callRunners()

  • 获取容器中的ApplicationRunner
  • 获取容器中的CommandLineRunner
  • 合并所有runner并且按照@Order进行排序
  • 遍历所有的runner。调用run方法

14.如果以上有异常

  • 调用Listener的failed

15.调用所有监听器的running方法 listeners.running(context);通知所有监听器running

16.running如果有问题。继续通知failed。调用所有Listener的failed;通知所有的监听器failed

SpringBoot的自动装配

核心类:ConfigurationClassPostProcessor中的postProcessBeanDefinitionRegistry().最后到ConfigurationClassParser类中的doProcessConfigurationClass()中解析并装配带有各种注解的类。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值