Spring Boot自动配置

http://blog.javachen.com/2015/03/13/how-to-run-spring-boot-application.html

http://blog.javachen.com/2015/03/13/some-spring-boot-features.html

http://blog.javachen.com/2016/02/19/spring-boot-auto-configuration.html

在上篇文章如何运行Spring Boot应用中,已经熟悉了如何通过maven或者gradle创建一个Spring Boot应用,这篇文章主要学习Spring Boot的自动配置,包括注解的使用以及一些配置约束等等。

关于Spring Boot的特性介绍,可以参考Spring Boot特性

主应用类

在Spring Boot应用中,我们通常将主应用类放置于应用的根包中,例如,com.javachen.example。主应用类有main方法,并且使用了@EnableAutoConfiguration注解,并暗地里定义了一个基础的包路径,Spring Boot会在该包路径来搜索类。例如,如果你正在编写一个JPA应用,被@EnableAutoConfiguration注解的类所在包将被用来搜索带有@Entity注解的实体类。

在主应用类上指定@ComponentScan,同样也隐式的指定了扫描时basePackage的路径。

如何运行Spring Boot应用中Application.java类声明了main方法,还使用了@EnableAutoConfiguration注解。

@RestController
@EnableAutoConfiguration
public class Application {
  @RequestMapping("/")
  String home() {
    return "Hello World!";
  }

  public static void main(String[] args) throws Exception {
    SpringApplication.run(Application.class, args);
  }
}

pasting

说明:

  • @RestController@RequestMapping注解是Spring MVC注解,它们不是Spring Boot的特定部分,具体查看Spring参考文档的MVC章节。
  • @EnableAutoConfiguration这个注解告诉Spring Boot根据添加的jar依赖猜测你想如何配置Spring。由于spring-boot-starter-web添加了Tomcat和Spring MVC,所以auto-configuration将假定你正在开发一个web应用并相应地对Spring进行设置。

配置类

在该类上也可以使用@Configuration注解,用来对spring boot进行配置,当然,你也可以使用一个XML源来调用SpringApplication.run()进行配置。

标有@Configuration注解的类为配置类。你不需要将所有的@Configuration放进一个单独的类。@Import注解可以用来导入其他配置类。另外,你也可以使用@ComponentScan注解自动收集所有的Spring组件,包括@Configuration类。

如果你需要使用基于XML的配置,你可以在注有@Configuration的类上使用附加的@ImportResource注解加载XML配置文件。

你可以通过将@EnableAutoConfiguration@SpringBootApplication注解添加到一个@Configuration类上来选择自动配置。自动配置的意思是Spring Boot尝试根据你添加的jar依赖自动配置你的Spring应用。

如果需要找出当前应用了哪些自动配置及应用的原因,你可以使用--debug开关启动应用,这将会记录一个自动配置的报告并输出到控制台。

如果发现应用了你不想要的特定自动配置类,你可以使用@EnableAutoConfiguration注解的排除属性来禁用它们。

import org.springframework.boot.autoconfigure.*; import org.springframework.boot.autoconfigure.jdbc.*; import org.springframework.context.annotation.*;  @Configuration @EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}) public class MyConfiguration { } 

总结,上面提到了几个注解,用途分别如下:

  • @Configuration。标注一个类为配置类。
  • @EnableAutoConfiguration。开启自动配置。
  • @SpringBootApplication。等价于以默认属性使用@Configuration@EnableAutoConfiguration@ComponentScan

如果启动类在根包下面,则你可以在该类上添加@ComponentScan注解而不需要添加任何参数,Spring Boot会在根包下面搜索注有@Component@Service,@Repository@Controller注解的所有类,并将他们注册为Spring Beans,否则,你需要在@ComponentScan注解上定义basePackages或者其他属性。

这样Application.java可以定义为:

package com.javachen.example;  import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;  @RestController @Configuration @ComponentScan @EnableAutoConfiguration public class Application {   @RequestMapping("/")   String home() {     return "Hello World!";   }    public static void main(String[] args) throws Exception {     SpringApplication.run(Application.class, args);   } } 

或者:

package com.javachen.example;  import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;  @RestController @SpringBootApplication public class Application {   @RequestMapping("/")   String home() {     return "Hello World!";   }    public static void main(String[] args) throws Exception {     SpringApplication.run(Application.class, args);   } } 

命令行参数

启动类可以实现CommandLineRunner接口,通过run方法处理main方法传入的参数,并且你能够使用@Value注解将命令行参数传入的值或者properties资源文件中定义的值注入到程序中。例如,创建一个HelloWorldService类:

package com.javachen.example.service;  import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component;  @Component public class HelloWorldService {   @Value("${name:World}")   private String name;    public String getMessage() {     return "Hello " + this.name;   } } 

并添加资源文件application.properties:

name: JavaChen 

修改Application类为如下:

package com.javachen.example;  import com.javachen.example.service.HelloWorldService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;  @RestController @SpringBootApplication public class Application implements CommandLineRunner {   @Autowired   private HelloWorldService helloWorldService;    @RequestMapping("/")   String home() {     return "Hello World!";   }    @Override   public void run(String... args) {     System.out.println(this.helloWorldService.getMessage());     if (args.length > 0 && args[0].equals("exitcode")) {       throw new ExitException();     }   }    public static void main(String[] args) throws Exception {     SpringApplication.run(Application.class, args);   } } 

运行该类的main方法,则默认会输出:

Hello JavaChen 

再次运行main方法,并传入参数--name=whatever,则会输出:

Hello whatever 

如果一些CommandLineRunner beans被定义必须以特定的次序调用,你可以额外实现org.springframework.core.Ordered接口或使用@Order注解。

利用command-line runner的这个特性,再配合依赖注入,可以在应用程序启动时后首先引入一些依赖bean,例如data source、rpc服务或者其他模块等等,这些对象的初始化可以放在run方法中。不过,需要注意的是,在run方法中执行初始化动作的时候一旦遇到任何异常,都会使得应用程序停止运行,因此最好利用try/catch语句处理可能遇到的异常。

每个SpringApplication在退出时为了确保ApplicationContext被优雅的关闭,将会注册一个JVM的shutdown钩子。所有标准的Spring生命周期回调(比如,DisposableBean接口或@PreDestroy注解)都能使用。

此外,如果beans想在应用结束时返回一个特定的退出码,可以实现org.springframework.boot.ExitCodeGenerator接口,例如上面例子中的ExitException异常类:

package com.javachen.example;  import org.springframework.boot.ExitCodeGenerator;  public class ExitException extends RuntimeException implements ExitCodeGenerator {   @Override   public int getExitCode() {     return 10;   } } 

自动配置

在启动类上使用@EnableAutoConfiguration注解,就会开启自动配置,简单点说就是它会根据定义在classpath下的类,自动的给你生成一些Bean,并加载到Spring的Context中。

它的神秘之处,不在于它能做什么,而在于它会生成什么样的Bean对于开发人员是不可预知(或者说不容易预知)。

例如,上面例子中引入了对spring-boot-starter-web的依赖,则会开启Spring MVC自动配置,观察启动日志,可以发现应用启动了tomcat和spring mvc。

Spring Boot为Spring MVC提供适用于多数应用的自动配置功能。在Spring默认基础上,自动配置添加了以下特性:

  • 引入ContentNegotiatingViewResolver和BeanNameViewResolver beans。
  • 对静态资源的支持,包括对WebJars的支持。
  • 自动注册Converter,GenericConverter,Formatter beans。
  • 对HttpMessageConverters的支持。
  • 自动注册MessageCodeResolver。
  • 对静态index.html的支持。
  • 对自定义Favicon的支持。

如果想全面控制Spring MVC,你可以添加自己的@Configuration,并使用@EnableWebMvc对其注解。如果想保留Spring Boot MVC的特性,并只是添加其他的MVC配置(拦截器,formatters,视图控制器等),你可以添加自己的WebMvcConfigurerAdapter类型的@Bean(不使用@EnableWebMvc注解)。

再举个例子:要开发一个基于Spring JPA的应用,会涉及到下面三个Bean的配置,DataSource,EntityManagerFactory,PlatformTransactionManager。

@Configuration @EnableJpaRepositories @EnableTransactionManagement public class Application {   @Bean   public DataSource dataSource() {       ...   }    @Bean   public EntityManagerFactory entityManagerFactory() {       ..       factory.setDataSource(dataSource());       return factory.getObject();   }    @Bean   public PlatformTransactionManager transactionManager() {       JpaTransactionManager txManager = new JpaTransactionManager();       txManager.setEntityManagerFactory(entityManagerFactory());       return txManager;   } } 

说明:

  • @EnableJpaRepositories会查找满足作为Repository条件(继承父类或者使用注解)的类。
  • @EnableTransactionManagement的作用:Enables Spring’s annotation-driven transaction management capability, similar to the support found in Spring’s <tx:*> XML namespace。

但是,如果你使用了@EnableAutoConfiguration,那么上面三个Bean,你都不需要配置。在classpath下面只引入了MySQL的驱动和SpringJpa。

compile 'mysql:mysql-connector-java:5.1.18' compile 'org.springframework.boot:spring-boot-starter-data-jpa' 

在生产环境中,数据库连接可以使用DataSource池进行自动配置。下面是选取一个特定实现的算法:

  • 由于Tomcat数据源连接池的性能和并发,在tomcat可用时,我们总是优先使用它。
  • 如果HikariCP可用,我们将使用它。
  • 如果Commons DBCP可用,我们将使用它,但在生产环境不推荐使用它。
  • 最后,如果Commons DBCP2可用,我们将使用它。

如果你使用spring-boot-starter-jdbc或spring-boot-starter-data-jpa,你将会自动获取对tomcat-jdbc的依赖。

DataSource配置通过外部配置文件的spring.datasource.*属性控制。示例中,你可能会在application.properties中声明下面的片段:

spring.datasource.url=jdbc:mysql://localhost/test spring.datasource.username=dbuser spring.datasource.password=dbpass spring.datasource.driver-class-name=com.mysql.jdbc.Driver 

其他可选的配置可以查看DataSourceProperties。同时注意你可以通过spring.datasource.*配置任何DataSource实现相关的特定属性:具体参考你使用的连接池实现的文档。

既然Spring Boot能够从大多数数据库的url上推断出driver-class-name,那么你就不需要再指定它了。对于一个将要创建的DataSource连接池,我们需要能够验证Driver是否可用,所以我们会在做任何事情之前检查它。比如,如果你设置spring.datasource.driverClassName=com.mysql.jdbc.Driver,然后这个类就会被加载。

Spring的JdbcTemplate和NamedParameterJdbcTemplate类是被自动配置的,你可以在自己的beans中通过@Autowire直接注入它们。

如果数据源是jndi,则定义:

spring.datasource.jndi-name=java:jboss/datasources/customers 

XML配置

如果不想使用注解进行配置,则可以使用xml配置文件,修改main方法如下:

  public static void main(String[] args) throws Exception {     SpringApplication.run("classpath:/META-INF/application-context.xml", args);   } 

META-INF/application-context.xml文件如下:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"        xmlns:context="http://www.springframework.org/schema/context"        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">      <context:annotation-config/>     <context:property-placeholder/>      <bean id="helloService" class="com.javachen.example.service.HelloWorldService"/>     <bean id="application" class="com.javachen.example.Application"/>  </beans>

Spring Boot 入门的更多相关文章

  1. 161103、Spring Boot 入门

    Spring Boot 入门 spring Boot是Spring社区较新的一个项目.该项目的目的是帮助开发者更容易的创建基于Spring的应用程序和服务,让更多人的人更快的对Spring进行入门体验 ...

  2. spring boot 入门操作(二)

    spring boot入门操作 使用FastJson解析json数据 pom dependencies里添加fastjson依赖 <dependency> <groupId>c ...

  3. spring boot 入门操作(三)

    spring boot入门操作 devtools热部署 pom dependencies里添加依赖 <dependency> <groupId>org.springframew ...

  4. Spring Boot入门教程1、使用Spring Boot构建第一个Web应用程序

    一.前言 什么是Spring Boot?Spring Boot就是一个让你使用Spring构建应用时减少配置的一个框架.约定优于配置,一定程度上提高了开发效率.https://zhuanlan.zhi ...

  5. Spring Boot入门教程2-1、使用Spring Boot+MyBatis访问数据库(CURD)注解版

    一.前言 什么是MyBatis?MyBatis是目前Java平台最为流行的ORM框架https://baike.baidu.com/item/MyBatis/2824918 本篇开发环境1.操作系统: ...

  6. Spring Boot 入门教程

    Spring Boot 入门教程,包含且不仅限于使用Spring Boot构建API.使用Thymeleaf模板引擎以及Freemarker模板引擎渲染视图.使用MyBatis操作数据库等等.本教程示 ...

  7. Spring Boot入门(五):使用JDBC访问MySql数据库

    本系列博客记录自己学习Spring Boot的历程,如帮助到你,不胜荣幸,如有错误,欢迎指正! 在程序开发的过程中,操作数据库是必不可少的部分,前面几篇博客中,也一直未涉及到数据库的操作,本篇博客 就 ...

  8. Spring Boot入门(四):开发Web Api接口常用注解总结

    本系列博客记录自己学习Spring Boot的历程,如帮助到你,不胜荣幸,如有错误,欢迎指正! 在程序员的日常工作中,Web开发应该是占比很重的一部分,至少我工作以来,开发的系统基本都是Web端访问的 ...

  9. Spring Boot入门(六):使用MyBatis访问MySql数据库(注解方式)

    本系列博客记录自己学习Spring Boot的历程,如帮助到你,不胜荣幸,如有错误,欢迎指正! 本篇博客我们讲解下在Spring Boot中使用MyBatis访问MySql数据库的简单用法. 1.前期 ...

  10. Spring Boot入门(二):使用Profile实现多环境配置管理&如何获取配置文件值

    在上一篇博客Spring Boot入门(一):使用IDEA创建Spring Boot项目并使用yaml配置文件中,我们新建了一个最原始的Spring Boot项目,并使用了更为流行的yaml配置文件. ...

随机推荐

  1. 增强iOS应用程序性能的提示和技巧(25个)

    转自 http://www.cocoachina.com/newbie/basic/2013/0522/6259.html 在开发iOS应用程序时,让程序具有良好的性能是非常关键的.这也是用户所期望的 ...

  2. C# 多线程详解

    1.使用多线程的几种方式 (1)不需要传递参数,也不需要返回参数 ThreadStart是一个委托,这个委托的定义为void ThreadStart(),没有参数与返回值. 复制代码 代码如下: cl ...

  3. centos6.5安装vsftp服务并配置虚拟账户ftp

      当我们的用户量越来越大时,继续创建更多的系统用户是不明智的,这时就需要为vsftpd创建虚拟账户,但vsftpd虚拟账户的数据库要保存在Berkeley DB格式的数据文件中,所以需要安装db4- ...

  4. php 之 查询 投票练习(0508)

    练习题目: 解题: 方法一: 1. 投票主页面: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ...

  5. 入门5:PHP 语法基础——流程控制

    一.if...else 语句 if( ) else{ } 如果 .... 就.... 否则.... if(判断){ 判断成立 则执行该表达式 }else{ 如果上方判断都不成立 则执行该表达式 } i ...

  6. 入门4:PHP 语法基础1

    一.PHP标记符 1.PHP页面中 以<?php  开头, ?>结尾,纯PHP页面结尾可以不写?> 2.在HTML页面插入PHP代码,必须有?>结尾.代码如下: <!DO ...

  7. TatukGIS-TGIS_LayerVector-LocateEx

    方法原型: function LocateEx(const _ptg: TGIS_Point; const _prec: Double; const _uid: Integer; var _dist: ...

  8. assert sys.modules[modname] is old_mod

    使用了pypiwin32 包中的pythoncom的时候,当跑在apache下,日志报错: [Thu Aug 27 17:06:44 2015] [error] [client 127.0.0.1] ...

  9. 关于org.openqa.selenium.ElementNotVisibleException

    最近在使用Selenium,编写最简单的百度search脚本,结果使用name来定位元素抛出了如下exception: 在定位百度的输入框,使用By.name()定位失败,但是使用By.id()和By ...

  10. Java吸收换行符

            今天做题遇到的--         由于读入的字符串可能包含空格,所以采用nextLine. int n = sc.nextInt(); for(int i=0; i<n; i+ ...