Spring Boot 系列之二 Spring Boot 核心

一、基本配置

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 项目的条件下。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,923评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,154评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,775评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,960评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,976评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,972评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,893评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,709评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,159评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,400评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,552评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,265评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,876评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,528评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,701评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,552评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,451评论 2 352

推荐阅读更多精彩内容