springboot我爱编程

Spring Boot 系列之二 Spring Boot 核心

2017-03-21  本文已影响784人  FlySheep_ly

一、基本配置

1. Spring Boot 的入口

Spring Boot 一般有一个名为 *Application 的入口类,在入口类里有一个标准的 Java main 方法,在 main 方法中使用 SpringApplication.run(DemoApplication.class, args); 来启动 Spring Boot 应用项目。
  在 *Application 入口类上通常有一个@SpringBootApplication注解,它是 Spring Boot 的核心注解,也是一个组合注解。

@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 {

    /**
     * Exclude specific auto-configuration classes such that they will never be applied.
     * @return the classes to exclude
     */
    @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "exclude")
    Class<?>[] exclude() default {};

    /**
     * Exclude specific auto-configuration class names such that they will never be
     * applied.
     * @return the class names to exclude
     * @since 1.3.0
     */
    @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "excludeName")
    String[] excludeName() default {};

    /**
     * Base packages to scan for annotated components. Use {@link #scanBasePackageClasses}
     * for a type-safe alternative to String-based package names.
     * @return base packages to scan
     * @since 1.3.0
     */
    @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
    String[] scanBasePackages() default {};

    /**
     * Type-safe alternative to {@link #scanBasePackages} for specifying the packages to
     * scan for annotated components. The package of each class specified will be scanned.
     * <p>
     * Consider creating a special no-op marker class or interface in each package that
     * serves no purpose other than being referenced by this attribute.
     * @return base packages to scan
     * @since 1.3.0
     */
    @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
    Class<?>[] scanBasePackageClasses() default {};

}

其中 @EnableAutoConfiguration 让 Spring Boot 根据类路径中的 jar 包依赖为当前项目进行自动配置。
  例如,添加了 spring-boot-starter-web 依赖,会自动添加 Tomcat 和 Spring MVC 的依赖,那么 Spring Boot 会对 Tomcat 和 Spring MVC 进行自动配置。
  又如,添加了 spring-boot-starter-data-jpa 依赖,Spring Boot 会自动进行 JPA 相关的配置。
  Spring Boot 会自动扫描 @SpringBootApplication 所在类的同级包以及下级包里的 Bean(若为 JPA 项目还可以扫描标注 @Entity 的实体类)。

2. 关闭特定的自动配置

关闭特定的自动配置应该使用 @SpringBootApplication 注解的 exclude 参数。

3. 定制 Banner

3.1 修改 Banner

(1)在Spring Boot 启动的时候会有一个默认启动图案,如下图所示。

默认启动图案

(2)在 src/main/resources 下新建一个 banner.txt。
  (3)通过 http://patorjk.com/software/taag 网站生成字符,将网站生成的字符复制到 banner.txt 中。
  (4)这时再启动程序,图案将显示为自定义的图案。

改变后的图案
3.2 关闭 banner

main 里面的内容修改为:

SpringApplication springApplication = new SpringApplication(DemoApplication.class);
springApplication.setBannerMode(Banner.Mode.OFF);
springApplication.run(args);

4. Spring Boot 的配置文件

Spring Boot 使用一个全局的配置文件 application.properties 或 application.yml,放置在 src/main/resources 目录或者类路径的 /config 下。
  Spring Boot 的全局配置文件的作用是对一些默认配置的配置值进行修改。
  将 Tomcat 的默认端口号 8080 修改为 9090,并将默认的访问路径 “/” 修改为 “/helloboot”。可以在 application.yml 中添加:

server:
  port: 9090
  context-path: /helloboot

5. 使用 XML 配置

Spring Boot 提倡零配置,即无 XML 配置,可能有一些特殊要求必须使用 XML 配置,这时我们可以通过 Spring 提供的 @ImportResource 来加载 XML 配置,例如

@ImportResource({"classpath:some-context.xml","classpath:another-context.xml"})

二、外部配置

1. 命令行参数配置

Spring Boot 基于 jar 包运行的命令:

java -jar xx.jar

也可以写成以下形式:
java -jar xx.jar --server.port=9090

2. 常规属性的配置

单个属性配置可以使用 @Value 注解。如在 application.yml 文件中有以下配置:

book:
  name: 书名
  price: 89.9

那么可以在代码中这么获取:
@Value("${book.name}")
private String bookName;

@Value("${book.price}")
private double bookPrice;

3. 类型安全的配置(基于 properties)

通过 @ConfigurationProperties 将 properties 属性和一个 Bean 及其属性关联,从而实现类型安全的配置。

@Component
@ConfigurationProperties(prefix = "book")
public class BookProperties {

    private String name;

    private double price;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }
}

通过以下方式取值:
@Autowired
private BookProperties bookProperties;

三、日志配置

Spring Boot 支持 Java Util Logging、Log4J、Log4J2和 Logback 作为日志框架,默认情况下使用 Logback 作为日志框架。建议日志配置文件还是以logback-spring.xml 文件配置。

四、Profile 配置

Profile 是 Spring 用来针对不同的环境对不同的配置提供支持的,全局 Profile 配置使用 application-{profile}. yml(如 application-prod.yml)。
  通过在 application.yml 中设置 spring.profiles.active = prod 来指定活动的 Profile。

五、Spring Boot 运行原理

Spring Boot 关于自动配置的源码在 spring-boot-autoconfigure-1.5.2.RELEASE.jar 内。可以通过在 application.yml 中设置属性 debug=true 或在运行 jar 时增加 --debug 参数查看当前项目中已启用和未启用的自动配置报告。

1. 运行原理

核心是 @SpringBootApplication 这个注解,而这个注解是一个组合注解,其核心功能是由 @EnableAutoConfiguration 提供的。

// @EnableAutoConfiguration 注解的源码
@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {

    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    /**
     * Exclude specific auto-configuration classes such that they will never be applied.
     * @return the classes to exclude
     */
    Class<?>[] exclude() default {};

    /**
     * Exclude specific auto-configuration class names such that they will never be
     * applied.
     * @return the class names to exclude
     * @since 1.3.0
     */
    String[] excludeName() default {};

}

这里的关键功能是 @Import 注解导入的配置功能,EnableAutoConfigurationImportSelector 使用 SpringFactoriesLoader.loadFactoryNames 方法来扫描具有 META-INF/spring.factories 文件的 jar 包,而在 spring-boot-autoconfigure-1.5.2.RELEASE.jar 里就有一个 spring.factories 文件,此文件中声明了有哪些自动配置。

2. 核心注解

任意一个 AutoConfiguration 文件,一般都有下面的条件注解,在 spring-boot-autoconfigure-1.5.2.RELEASE.jarorg.springframework.boot.autoconfigure.condition 包下,条件注解如下:

@ConditionalOnBean:当容器里有指定的 Bean 的条件下。
@ConditionalOnClass:当类路径下有指定的类的条件下。
@ConditionalOnCloudPlatform:当指定的云平台处于活动状态时匹配。
@ConditionalOnExpression:基于 SpEL 表达式作为判断条件。
@ConditionalOnJava:基于 JVM 版本作为判断条件。
@ConditionalOnJndi:在 JNDI 存在的条件下查找指定的位置。
@ConditionalOnMissingBean:当容器里没有指定 Bean 的情况下。
@ConditionalOnMissingClass:当类路径下没有指定的类的条件下。
@ConditionalOnNotWebApplication:当前项目不是 Web 项目的条件下。
@ConditionalOnProperty:指定的属性是否有指定的值。
@ConditionalOnResource:类路径是否有指定的值。
@ConditionalOnSingleCandidate:当指定 Bean 在容器中只有一个,或者虽然有多个但是指定首选的 Bean。
@ConditionalOnWebApplication:当前项目是 Web 项目的条件下。
上一篇下一篇

猜你喜欢

热点阅读