《02.Spring Boot连载:Spring Boot实战.Spring Boot核心原理剖析》

在上节中我们通过了一个小的入门案例已经看到了Spring Boot的强大和简单之处。本章将详细介绍Spring Boot的核心注解,基本配置和运行机制。笔者一直认为:精通一个技术一定要深入了解这个技术帮助我们做了哪些动作,深入理解它底层的运行原理,只有达到这个目标才可以熟练使用框架,最终达到融会贯通的目的。

一.启动类与@SpringBootApplication

Spring Boot的项目一般都会有注解*Application标注的入口类,入口类中会有一个main方法,main方法是一个标准的Java应用程序的入口方法,可以直接启动。
@SpringBootApplication注解是Spring Boot的核心注解,用此注解标注的入口类是应用的启动类,通常会在启动类的main方法中通过 SpringApplication.run(App.class, args) 来启动Spring Boot应用项目。
@SpringBootApplication其实是一个组合注解,查看源码如下:

  1. // 程序清单:org/springframework/boot/autoconfigure/SpringBootApplication
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @SpringBootConfiguration
    @EnableAutoConfiguration
    @ComponentScan(excludeFilters = {
            @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
            @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
    public  @interface  SpringBootApplication {
    @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "exclude")
        Class<?>[] exclude() default {};
        @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "excludeName")
        String[] excludeName() default {};
        @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
        String[] scanBasePackages() default {};
        @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
        Class<?>[] scanBasePackageClasses() default {};
    }

(1)@SpringBootConfiguration:这是Spring Boot项目的配置注解,这也是一个组合注解:

  1. //程序清单:org/springframewor/boot/SpringBootConfiguration
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Configuration
    public @interface SpringBootConfiguration {

(2)@EnableAutoConfiguration:启动自动配置,该注解会让Spring Boot根据当前项目所依赖的jar包自动配置项目的相关配置项。
例如,当我们在Spring Boot项目的pom.xml文件中配置了spring-boot-starter-web依赖:

  1. <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

图2.1 spring-boot-starter-web自动配置图

通过上述例子可以看出,如果我们又在项目中添加spring-boot-starter-data-solr依赖,Spring Boot就会自动进行Solr技术的相关配置。
(3) @ComponentScan:扫描配置,Spring Boot默认会扫描@SpringBootApplication所在类的同级包以及它的子包。所以建议将@SpringBootApplication修饰的入口类放置在项目包下(Group Id+Artifact Id),这样做的好处是:可以保证Spring Boot项目自动扫描到项目所有的包。

二.Spring Boot基本配置介绍

1 关闭某个自动配置

通过上节@SpringBootApplication下的@EnableAutoConfiguration得知,Spring Boot会根据项目中的jar包依赖,自动做出配置,Spring Boot支持的自动配置如下(非常多):

假如我们不需要Spring Boot自动配置,想关闭某一项的自动配置,该如何设置呢?
例如:我们不想自动配置Redis,想自己手动配置呢?通过查看@SpringBootApplication的源码可以看出,关闭特定的自动配置应该使用@SpringBootApplication下的exclude参数,现以关闭Redis自动配置为例:
@SpringBootApplication(exclude={RedisAutoConfiguration.class})

2.定制启动Banner

在启动Spring Boot项目的时候我们在控制台下看到了如下默认的启动图案:

如果想自己来指定启动的图案应该如何配置呢?

(1) 在浏览器中打开网站http://patorjk.com/software/taag,如下图:

(2)在第一步所示范的网站上选择左下方的“select & copy”按钮将自定义的banner图案进行复制,然后新建一个banner.txt文件,将复制好的图案写入到banner.txt文件中。

(3)将banner.txt文件放置到项目的src/main/resources目录下。

(4)重新启动程序,查看效果如下:

3. 应用的全局配置文件

可以在Spring Boot项目的src/main/resources目录下或者在类路径下的/config目录下创建一个全局的配置文件application.properties或者是后缀为.yml的application.yml的文件用于修改Spring Boot项目的默认配置值,例如修改项目的默认端口,或者进入DispatcherServlet的请求地址规则等。
通常,在实际开发中我们习惯使用application.properties文件作为应用的全局配置文件,一般我们放到src/main/resources目录下。
例如,在src/main/resources目录下创建一个名称为application.properties的文件,配置内容如下:

server.port=9999
server.servlet-path=*.action

(1)其中, server.port参数用于将Spring Boot项目的默认端口改为9999,启动应用,端口修改后如下图所示:

(2) server.servlet-path参数用于将进入DispatcherServlet的规则修改为:*.action,测试如下:

从上面的参数配置可以看出,Spring Boot支持很多参数的配置与参数值的修改,关于其他配置参数的详细说明和描述可以查看官方的文档说明:http://docs.spring.io/spring-boot/docs/1.5.6.RELEASE/reference/htmlsingle/#common-application-properties

4 Starters启动器

Spring Boot为我们提供了简化项目开发的Starter启动器,例如我们在项目中使用的pom.xml文件下配置:

  1. <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

Spring Boot就会自动关联web开发相关的依赖,如Tomcat以及spring-webmvc等,进而对web开发进行支持,同时相关技术的配置也将实现自动配置,程序员即可从繁琐的配置文件中脱身而出了。除此之外,官方还提供了如下Starters:

  1. ?spring-boot-starter:这是Spring Boot的核心启动器,包含了自动配置、日志和YAML文件的支持。
    ?spring-boot-starter-activemq:为JMS使用Apache ActiveMQ    ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线
    ?spring-boot-starter-amqp:通过spring-rabbit来支持AMQP协议(Advanced Message Queuing Protocol)。
    ?spring-boot-starter-aop:支持面向方面的编程即AOP,包括spring-aop和AspectJ。
    ?spring-boot-starter-artemis:通过Apache Artemis支持JMS的API(Java Message Service API)。
    ?spring-boot-starter-batch:支持Spring Batch,包括HSQLDB数据库。
    ?spring-boot-starter-cache:支持Spring的Cache抽象。
    ?spring-boot-starter-cloud-connectors:支持Spring Cloud Connectors,简化了在像Cloud Foundry或Heroku这样的云平台上连接服务。
    ?spring-boot-starter-data-cassandra:使用Cassandra分布式数据库、Spring Data Cassandra,Apache Cassandra是一套开源分布式NoSQL数据库系统。
    ?spring-boot-starter-data-couchbase:使用Couchbase 文件存储数据库、Spring Data Couchbase。Spring Data是一个用于简化数据库访问,并支持云服务的开源框架。
    ?spring-boot-starter-data-elasticsearch:支持ElasticSearch搜索和分析引擎,包括spring-data-elasticsearch。
    ?spring-boot-starter-data-gemfire:支持GemFire分布式数据存储,包括spring-data-gemfire。
    ?spring-boot-starter-data-jpa:支持JPA(Java Persistence API),包括spring-data-jpa、spring-orm、Hibernate。
    ?spring-boot-starter-data-ldap:支持 Spring Data LDAP。
    ?spring-boot-starter-data-mongodb:支持MongoDB数据,包括spring-data-mongodb。
    ?spring-boot-starter-data-neo4j:使用Neo4j图形数据库、Spring Data Neo4j    Neo4j是一个高性能的,NOSQL图形数据库,它将结构化数据存储在网络上而不是表中。
    ?spring-boot-starter-redis:支持Redis键值存储数据库,包括spring-redis。
    ?spring-boot-starter-data-rest:通过spring-data-rest-webmvc,支持通过REST暴露Spring Data数据仓库。
    ?spring-boot-starter-data-solr:支持Apache Solr搜索平台,包括spring-data-solr。
    ?spring-boot-starter-freemarker:支持FreeMarker模板引擎。
    ?spring-boot-starter-groovy-templates:支持Groovy模板引擎。
    ?spring-boot-starter-hateoas:通过spring-hateoas支持基于HATEOAS的RESTful Web服务。
    ?spring-boot-starter-integration:支持通用的spring-integration模块。
    ?spring-boot-starter-jdbc:支持JDBC数据库。
    ?spring-boot-starter-jersey:支持Jersey RESTful Web服务框架。
    ?spring-boot-starter-hornetq:通过HornetQ支持JMS。
    ?spring-boot-starter-jta-atomikos:通过Atomikos支持JTA分布式事务处理。
    ?spring-boot-starter-jta-bitronix:通过Bitronix支持JTA分布式事务处理。
    ?spring-boot-starter-mail:支持javax.mail模块。
    ?spring-boot-starter-mobile:支持spring-mobile。
    ?spring-boot-starter-mustache:支持Mustache模板引擎。
    ?spring-boot-starter-security:支持spring-security。
    ?spring-boot-starter-social-facebook:支持spring-social-facebook
    ?spring-boot-starter-social-linkedin:支持pring-social-linkedin
    ?spring-boot-starter-social-twitter:支持pring-social-twitter
    ?spring-boot-starter-test:支持常规的测试依赖,包括JUnit、Hamcrest、Mockito以及spring-test模块。
    ?spring-boot-starter-thymeleaf:支持Thymeleaf模板引擎,包括与Spring的集成。
    ?spring-boot-starter-velocity:支持Velocity模板引擎。
    ?spring-boot-starter-web:支持全栈式Web开发,包括Tomcat和spring-webmvc。
    ?spring-boot-starter-websocket:支持WebSocket开发。
    ?spring-boot-starter-ws:支持Spring Web Services。

Spring Boot在进行SpringApplication对象实例化时会加载META-INF/spring.factories文件,将该配置文件中的配置载入到Spring容器,进行自动配置。

1 源码分析

首先进入到启动Spring Boot项目代码SpringApplication.run(App.class, args)的源码下:

  1. 程序清单:org/springframework/boot/SpringApplication
  2. public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
  3.    return new SpringApplication(sources).run(args);
  4. }            

可以看到run方法实际上在创建SpringApplication对象实例,进入到创建SpringApplication对象实例代码中去:

  1. 程序清单:org/springframework/boot/SpringApplication
  2. public SpringApplication(Object... sources) {
  3.    initialize(sources);
  4. }

接下来就是调用initialize(sources)方法,进入到该方法源码如下:

  1. 程序清单:org/springframework/boot/SpringApplication
  2. @SuppressWarnings({ "unchecked", "rawtypes" })
  3. private void initialize(Object[] sources) {
  4.    if (sources != null && sources.length > 0) {
  5.        this.sources.addAll(Arrays.asList(sources));
  6.    }
  7.    this.webEnvironment = deduceWebEnvironment();
  8.    setInitializers((Collection) getSpringFactoriesInstances(
  9.            ApplicationContextInitializer.class));
  10.    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
  11.    this.mainApplicationClass = deduceMainApplicationClass();
  12. }

initialize方法中调用了getSpringFactoriesInstances方法,代码如下:

  1. 程序清单:org/springframework/boot/SpringApplication
  2. private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type,
  3.        Class<?>[] parameterTypes, Object... args) {
  4.    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
  5.    // Use names and ensure unique to protect against duplicates
  6.    Set<String> names = new LinkedHashSet<String>(
  7.            SpringFactoriesLoader.loadFactoryNames(type, classLoader));
  8.    List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
  9.            classLoader, args, names);
  10.    AnnotationAwareOrderComparator.sort(instances);
  11.    return instances;
  12. }

在getSpringFactoriesInstances中又调用了loadFactoryNames方法,继续进入到该方法中,查看源码如下:

  1. 程序清单:org/springframework/boot.SpringApplication
  2. public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
  3.    String factoryClassName = factoryClass.getName();
  4.    try {
  5. Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
  6. ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
  7.        List<String> result = new ArrayList<String>();
  8.        while (urls.hasMoreElements()) {
  9.            URL url = urls.nextElement();
  10.            Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
  11.            String factoryClassNames = properties.getProperty(factoryClassName);
  12.            result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
  13.        }
  14.        return result;
  15.    }
  16.    catch (IOException ex) {
  17.        throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +
  18.                "] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);
  19.    }
  20. }

在上述源码中可以查看到加载了一个常量:FACTORIESRESOURCELOCATION,查看该常量的源码如下:

  1. /**
  2. * The location to look for factories.
  3. * <p>Can be present in multiple JAR files.
  4. */
  5. public  static  final  String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

从该源码中可以看出,最终Spring Boot是通过加载META-INF/spring.factories 文件来进行自动配置的。其所在位置如下图所示。

2 spring.factories分析

Spring factories内容如下:

  1. # Initializers
  2. org.springframework.context.ApplicationContextInitializer=\
  3. org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
  4. org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer
  5. # Application Listeners
  6. org.springframework.context.ApplicationListener=\
  7. org.springframework.boot.autoconfigure.BackgroundPreinitializer
  8. # Auto Configuration Import Listeners
  9. org.springframework.boot.autoconfigure.AutoConfigurationImportListener=\
  10. org.springframework.boot.autoconfigure.condition.ConditionEvaluationReportAutoConfigurationImportListener
  11. # Auto Configuration Import Filters
  12. org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
  13. org.springframework.boot.autoconfigure.condition.OnClassCondition
  14. # Auto Configure
  15. org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  16. org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
  17. org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
  18. org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
  19. org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
  20. org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
  21. org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
  22. org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\
  23. org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\
  24. org.springframework.boot.autoconfigure.context.MessageSourceAutoConfiguration,\
  25. org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration,\
  26. org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration,\
  27. org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\
  28. org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\
  29. org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\
  30. org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\
  31. org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\
  32. org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\
  33. org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\
  34. org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\
  35. org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
  36. org.springframework.boot.autoconfigure.data.ldap.LdapDataAutoConfiguration,\
  37. org.springframework.boot.autoconfigure.data.ldap.LdapRepositoriesAutoConfiguration,\
  38. org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration,\
  39. org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration,\
  40. org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration,\
  41. org.springframework.boot.autoconfigure.data.neo4j.Neo4jRepositoriesAutoConfiguration,\
  42. org.springframework.boot.autoconfigure.data.solr.SolrRepositoriesAutoConfiguration,\
  43. org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
  44. org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration,\
  45. org.springframework.boot.autoconfigure.data.rest.RepositoryRestMvcAutoConfiguration,\
  46. org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration,\
  47. org.springframework.boot.autoconfigure.elasticsearch.jest.JestAutoConfiguration,\
  48. org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration,\
  49. org.springframework.boot.autoconfigure.gson.GsonAutoConfiguration,\
  50. org.springframework.boot.autoconfigure.h2.H2ConsoleAutoConfiguration,\
  51. org.springframework.boot.autoconfigure.hateoas.HypermediaAutoConfiguration,\
  52. org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration,\
  53. org.springframework.boot.autoconfigure.hazelcast.HazelcastJpaDependencyAutoConfiguration,\
  54. org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration,\
  55. org.springframework.boot.autoconfigure.integration.IntegrationAutoConfiguration,\
  56. org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
  57. org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
  58. org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
  59. org.springframework.boot.autoconfigure.jdbc.JndiDataSourceAutoConfiguration,\
  60. org.springframework.boot.autoconfigure.jdbc.XADataSourceAutoConfiguration,\
  61. org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration,\
  62. org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration,\
  63. org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration,\
  64. org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration,\
  65. org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration,\
  66. org.springframework.boot.autoconfigure.jms.artemis.ArtemisAutoConfiguration,\
  67. org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration,\
  68. org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAutoConfiguration,\
  69. org.springframework.boot.autoconfigure.jersey.JerseyAutoConfiguration,\
  70. org.springframework.boot.autoconfigure.jooq.JooqAutoConfiguration,\
  71. org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration,\
  72. org.springframework.boot.autoconfigure.ldap.embedded.EmbeddedLdapAutoConfiguration,\
  73. org.springframework.boot.autoconfigure.ldap.LdapAutoConfiguration,\
  74. org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration,\
  75. org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration,\
  76. org.springframework.boot.autoconfigure.mail.MailSenderValidatorAutoConfiguration,\
  77. org.springframework.boot.autoconfigure.mobile.DeviceResolverAutoConfiguration,\
  78. org.springframework.boot.autoconfigure.mobile.DeviceDelegatingViewResolverAutoConfiguration,\
  79. org.springframework.boot.autoconfigure.mobile.SitePreferenceAutoConfiguration,\
  80. org.springframework.boot.autoconfigure.mongo.embedded.EmbeddedMongoAutoConfiguration,\
  81. org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,\
  82. org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration,\
  83. org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
  84. org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration,\
  85. org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration,\
  86. org.springframework.boot.autoconfigure.security.SecurityFilterAutoConfiguration,\
  87. org.springframework.boot.autoconfigure.security.FallbackWebSecurityAutoConfiguration,\
  88. org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,\
  89. org.springframework.boot.autoconfigure.sendgrid.SendGridAutoConfiguration,\
  90. org.springframework.boot.autoconfigure.session.SessionAutoConfiguration,\
  91. org.springframework.boot.autoconfigure.social.SocialWebAutoConfiguration,\
  92. org.springframework.boot.autoconfigure.social.FacebookAutoConfiguration,\
  93. org.springframework.boot.autoconfigure.social.LinkedInAutoConfiguration,\
  94. org.springframework.boot.autoconfigure.social.TwitterAutoConfiguration,\
  95. org.springframework.boot.autoconfigure.solr.SolrAutoConfiguration,\
  96. org.springframework.boot.autoconfigure.thymeleaf.ThymeleafAutoConfiguration,\
  97. org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration,\
  98. org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration,\
  99. org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration,\
  100. org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration,\
  101. org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration,\
  102. org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration,\
  103. org.springframework.boot.autoconfigure.web.HttpEncodingAutoConfiguration,\
  104. org.springframework.boot.autoconfigure.web.HttpMessageConvertersAutoConfiguration,\
  105. org.springframework.boot.autoconfigure.web.MultipartAutoConfiguration,\
  106. org.springframework.boot.autoconfigure.web.ServerPropertiesAutoConfiguration,\
  107. org.springframework.boot.autoconfigure.web.WebClientAutoConfiguration,\
  108. org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,\
  109. org.springframework.boot.autoconfigure.websocket.WebSocketAutoConfiguration,\
  110. org.springframework.boot.autoconfigure.websocket.WebSocketMessagingAutoConfiguration,\
  111. org.springframework.boot.autoconfigure.webservices.WebServicesAutoConfiguration
  112. # Failure analyzers
  113. org.springframework.boot.diagnostics.FailureAnalyzer=\
  114. org.springframework.boot.autoconfigure.diagnostics.analyzer.NoSuchBeanDefinitionFailureAnalyzer,\
  115. org.springframework.boot.autoconfigure.jdbc.DataSourceBeanCreationFailureAnalyzer,\
  116. org.springframework.boot.autoconfigure.jdbc.HikariDriverConfigurationFailureAnalyzer
  117. # Template availability providers
  118. org.springframework.boot.autoconfigure.template.TemplateAvailabilityProvider=\
  119. org.springframework.boot.autoconfigure.freemarker.FreeMarkerTemplateAvailabilityProvider,\
  120. org.springframework.boot.autoconfigure.mustache.MustacheTemplateAvailabilityProvider,\
  121. org.springframework.boot.autoconfigure.groovy.template.GroovyTemplateAvailabilityProvider,\
  122. org.springframework.boot.autoconfigure.thymeleaf.ThymeleafTemplateAvailabilityProvider,\
  123. org.springframework.boot.autoconfigure.web.JspTemplateAvailabilityProvider

在spring.factories中可以看出web开发的自动配置类是:org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration,在这个类中就自动实现了Sprng MVC的配置。现在以Spring MVC的配置如下:

  1. <bean id="jspViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  2. <property name="prefix" value="/WEB-INF/jsp/"/>
  3. <property name="suffix" value=".jsp"/>
  4. </bean>

为例看Spring Boot是如何实现该自动配置的:

(1) 查询WebMvcAutoConfiguration的源码如下:

@[email protected]@ConditionalOnClass({ Servlet.class, DispatcherServlet.class,        WebMvcConfigurerAdapter.class })@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class,        ValidationAutoConfiguration.class })public class WebMvcAutoConfiguration {

其中@ConditionalOnClass是一个条件注解,意思就是只有当前项目运行环境中有Servlet类,并且有DispatcherServlet类以及WebMvcConfigurerAdapter类时(说明本项目是需要集成Spring MVC的),,Spring Boot才会初始化WebMvcAutoConfiguration进行自动配置。
(2) 自动配置试图解析器ViewResolver。
在WebMvcAutoConfiguration类下找到以下源码:

@[email protected] InternalResourceViewResolver defaultViewResolver() {    InternalResourceViewResolver resolver = new InternalResourceViewResolver();    resolver.setPrefix(this.mvcProperties.getView().getPrefix());    resolver.setSuffix(this.mvcProperties.getView().getSuffix());    return resolver;}

@Bean是在这里定义了一个Bean对象InternalResourceViewResolver,以前我们是通过标签来定义的。
@CoditionalOnMissingBean是一个条件注解,是当
前环境下没有这个Bean的时候才会创建该bean。
方法的返回值即是InternalResourceViewResolver,即是我们需要的对象,那么视图解析器中前缀和后缀Spring Boot是如何实现自动配置的呢?

resolver.setPrefix(this.mvcProperties.getView().getPrefix());resolver.setSuffix(this.mvcProperties.getView().getSuffix());该源码会找到一个View对象:public static class View {    /**     * Spring MVC view prefix.     */    private String prefix;    /**     * Spring MVC view suffix.     */    private String suffix;    public String getPrefix() {        return this.prefix;    }    public void setPrefix(String prefix) {        this.prefix = prefix;    }    public String getSuffix() {        return this.suffix;    }    public void setSuffix(String suffix) {        this.suffix = suffix;    }}

View对象则会通过获取prefix,suffix加载视图解析器需要的前缀和后缀,该参数的值是可以通过全局配置文件来指定前缀和后缀的,配置如下:

spring.mvc.view.prefix= # Spring MVC view prefix.
spring.mvc.view.suffix= # Spring MVC view suffix.

时间: 2024-10-10 07:54:22

《02.Spring Boot连载:Spring Boot实战.Spring Boot核心原理剖析》的相关文章

CI框架源码阅读笔记3 全局函数Common.php

从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap引导文件都会最先引入全局函数,以便于之后的处理工作). 打开Common.php中,第一行代码就非常诡异: if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 上一篇(CI框架源码阅读笔记2 一切的入口 index

IOS测试框架之:athrun的InstrumentDriver源码阅读笔记

athrun的InstrumentDriver源码阅读笔记 作者:唯一 athrun是淘宝的开源测试项目,InstrumentDriver是ios端的实现,之前在公司项目中用过这个框架,没有深入了解,现在回来记录下. 官方介绍:http://code.taobao.org/p/athrun/wiki/instrumentDriver/ 优点:这个框架是对UIAutomation的java实现,在代码提示.用例维护方面比UIAutomation强多了,借junit4的光,我们可以通过junit4的

Yii源码阅读笔记 - 日志组件

?使用 Yii框架为开发者提供两个静态方法进行日志记录: Yii::log($message, $level, $category);Yii::trace($message, $category); 两者的区别在于后者依赖于应用开启调试模式,即定义常量YII_DEBUG: defined('YII_DEBUG') or define('YII_DEBUG', true); Yii::log方法的调用需要指定message的level和category.category是格式为“xxx.yyy.z

源码阅读笔记 - 1 MSVC2015中的std::sort

大约寒假开始的时候我就已经把std::sort的源码阅读完毕并理解其中的做法了,到了寒假结尾,姑且把它写出来 这是我的第一篇源码阅读笔记,以后会发更多的,包括算法和库实现,源码会按照我自己的代码风格格式化,去掉或者展开用于条件编译或者debug检查的宏,依重要程度重新排序函数,但是不会改变命名方式(虽然MSVC的STL命名实在是我不能接受的那种),对于代码块的解释会在代码块前(上面)用注释标明. template<class _RanIt, class _Diff, class _Pr> in

CI框架源码阅读笔记5 基准测试 BenchMark.php

上一篇博客(CI框架源码阅读笔记4 引导文件CodeIgniter.php)中,我们已经看到:CI中核心流程的核心功能都是由不同的组件来完成的.这些组件类似于一个一个单独的模块,不同的模块完成不同的功能,各模块之间可以相互调用,共同构成了CI的核心骨架. 从本篇开始,将进一步去分析各组件的实现细节,深入CI核心的黑盒内部(研究之后,其实就应该是白盒了,仅仅对于应用来说,它应该算是黑盒),从而更好的去认识.把握这个框架. 按照惯例,在开始之前,我们贴上CI中不完全的核心组件图: 由于BenchMa

CI框架源码阅读笔记2 一切的入口 index.php

上一节(CI框架源码阅读笔记1 - 环境准备.基本术语和框架流程)中,我们提到了CI框架的基本流程,这里这次贴出流程图,以备参考: 作为CI框架的入口文件,源码阅读,自然由此开始.在源码阅读的过程中,我们并不会逐行进行解释,而只解释核心的功能和实现. 1.       设置应用程序环境 define('ENVIRONMENT', 'development'); 这里的development可以是任何你喜欢的环境名称(比如dev,再如test),相对应的,你要在下面的switch case代码块中

Apache Storm源码阅读笔记

欢迎转载,转载请注明出处. 楔子 自从建了Spark交流的QQ群之后,热情加入的同学不少,大家不仅对Spark很热衷对于Storm也是充满好奇.大家都提到一个问题就是有关storm内部实现机理的资料比较少,理解起来非常费劲. 尽管自己也陆续对storm的源码走读发表了一些博文,当时写的时候比较匆忙,有时候衔接的不是太好,此番做了一些整理,主要是针对TridentTopology部分,修改过的内容采用pdf格式发布,方便打印. 文章中有些内容的理解得益于徐明明和fxjwind两位的指点,非常感谢.

CI框架源码阅读笔记4 引导文件CodeIgniter.php

到了这里,终于进入CI框架的核心了.既然是"引导"文件,那么就是对用户的请求.参数等做相应的导向,让用户请求和数据流按照正确的线路各就各位.例如,用户的请求url: http://you.host.com/usr/reg 经过引导文件,实际上会交给Application中的UsrController控制器的reg方法去处理. 这之中,CodeIgniter.php做了哪些工作?我们一步步来看. 1.    导入预定义常量.框架环境初始化 之前的一篇博客(CI框架源码阅读笔记2 一切的入

jdk源码阅读笔记之java集合框架(二)(ArrayList)

关于ArrayList的分析,会从且仅从其添加(add)与删除(remove)方法入手. ArrayList类定义: p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Monaco } span.s1 { color: #931a68 } public class ArrayList<E> extends AbstractList<E> implements List<E> ArrayList基本属性: /** *

dubbo源码阅读笔记--服务调用时序

上接dubbo源码阅读笔记--暴露服务时序,继续梳理服务调用时序,下图右面红线流程. 整理了调用时序图 分为3步,connect,decode,invoke. 连接 AllChannelHandler.connected(Channel) line: 38 HeartbeatHandler.connected(Channel) line: 47 MultiMessageHandler(AbstractChannelHandlerDelegate).connected(Channel) line: