springboot回顾一,介绍,自动以及自定义配置

从本质上来说,Spring Boot就是Spring,它做了那些没有它你自己也会去做的SpringBean配置。谢天谢地,幸好有Spring,你不用再写这些样板配置了,可以专注于应用程序的逻辑,这些才是应用程序独一无二的东西。

spring的介绍

启动引导spring

package readinglist;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ReadingListApplication {
    public static void main(String[] args) {
        SpringApplication.run(ReadingListApplication.class, args);
    }
}

@SpringBootApplication:开启组件扫描和自动配置
SpringApplication.run 负责启动引导应用程序
@SpringBootApplication 将三个有用的注解组合在了一起。

  • Spring的 @Configuration :标明该类使用Spring基于Java的配置。虽然本书不会写太多
    配置,但我们会更倾向于使用基于Java而不是XML的配置。
  • Spring的 @ComponentScan :启用组件扫描,这样你写的Web控制器类和其他组件才能被
    自动发现并注册为Spring应用程序上下文里的Bean。本章稍后会写一个简单的Spring MVC
    控制器,使用 @Controller 进行注解,这样组件扫描才能找到它。
  • Spring Boot 的 @EnableAutoConfiguration : 这 个 不 起 眼 的 小 注 解 也 可 以 称 为
    @Abracadabra
    ① ,就是这一行配置开启了Spring Boot自动配置的魔力,让你不用再写成
    篇的配置了。

spring的自动配置

在maven的依赖里面我们会看到一些starter之类的依赖,这个是启动依赖,比如hibernate,在依赖之后spring就会为我们做一个自动配置的事情,那么我们如果想要自定义的配置的话,就需要用自定义的配置来覆盖这个自定义的。

这里有个不错的例子:当你在应用程序里添加安全特性时,自动配置做得还不够好。安全配置并不是放之四海而皆准的,围绕应用程序安全有很多决策要做,Spring Boot不能替你做决定。
虽然Spring Boot为安全提供了一些基本的自动配置,但是你还是需要自己覆盖一些配置以满足特定的安全要求。想知道如何用显式的配置来覆盖自动配置,我们先从为阅读列表应用程序添加SpringSecurity入手。在了解自动配置提供了什么之后,我们再来覆盖基础的安全配置,以满足特定的
场景需求。
首先我们配置一个

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private ReaderRepository readerRepository;
@Override
protected void configure(HttpSecurity http) throws Exception {
    http
    .authorizeRequests()
    .antMatchers("/").access("hasRole('READER')")
    .antMatchers("/**").permitAll()
    .and()
    .formLogin()
    .loginPage("/login")
    .failureUrl("/login?error=true");
}
3.1 覆盖 Spring Boot自动配置 
@Override
protected void configure(
        AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(new UserDetailsService() {
              @Override
              public UserDetails loadUserByUsername(String username)
              throws UsernameNotFoundException {
              return readerRepository.findOne(username);
        }
    });
  }
}

那么自动配置那边是怎么检测到这个类然后并且覆盖自动配置类呢?

@Configuration
@EnableConfigurationProperties
@ConditionalOnClass({ EnableWebSecurity.class })
@ConditionalOnMissingBean(WebSecurityConfiguration.class)
@ConditionalOnWebApplication
public class SpringBootWebSecurityConfiguration {
...
}

如你所见, SpringBootWebSecurityConfiguration 上加了好几个注解。看到 @ConditionalOnClass 注解后,你就应该知道Classpath里必须要有 @EnableWebSecurity 注解。
@ConditionalOnWebApplication 说 明 这 必 须 是 个 Web 应 用 程 序 。 @ConditionalOn-MissingBean 注解才是我们的安全配置类代替 SpringBootWebSecurityConfiguration 的关键所在。
@ConditionalOnMissingBean 注解要求当下没有WebSecurityConfiguration 类型的Bean。虽然表面上我们并没有这么一个Bean,但通过在 SecurityConfig 上添加 @EnableWeb-Security 注解,我们实际上间接创建了一个 WebSecurityConfiguration Bean。所以在自动
配置时,这个Bean就已经存在了, @ConditionalOnMissingBean 条件不成立, SpringBoot-WebSecurityConfiguration 提供的配置就被跳过了。
虽然Spring Boot的自动配置和 @ConditionalOnMissingBean 让你能显式地覆盖那些可以自动配置的Bean,但并不是每次都要做到这种程度。让我们来看看怎么通过设置几个简单的配置属性调整自动配置组件吧。

通过属性文件外置配置

在处理应用安全时,你当然会希望完全掌控所有配置。不过,为了微调一些细节,比如改改端口号和日志级别,便放弃自动配置,这是一件让人羞愧的事。为了设置数据库URL,是配置一个属性简单,还是完整地声明一个数据源的Bean简单?答案不言自明,不是吗?事实上,Spring Boot自动配置的Bean提供了300多个用于微调的属性。当你调整设置时,只要在环境变量、Java系统属性、JNDI(Java Naming and Directory Interface)、命令行参数或者属性文件里进行指定就好了

  • 比如springboot程序开启时候会有一个banner就是一个图形化的代码出现,如果你想要禁用的话,就在application.properties文件里面加上配置:spring.main.show-banner=false,当然如果你喜欢的话,也可以创建名为application.yml的YAML文件:
spring:
  main:
    show-banner: false
  • 比如你想要修改tomcat的端口号:
server:
  port: 8000
  • 要设置日志级别,你可以创建以 logging.level 开头的属性,后面是要日志名称。如果根日志级别要设置为 WARN ,但Spring Security的日志要用 DEBUG 级别,可以在application.yml里加入
logging:
    path: /var/logs/
    file: BookWorm.log
    level:
        root: WARN
        org:
          springframework:
            security: DEBUG

另外,你也可以把Spring Security的包名写成一行:

logging:
  level:
    root: WARN
      org.springframework.security: DEBUG
  • 配置数据源
spring:
    datasource:
        url: jdbc:mysql://localhost/readinglist
        username: dbuser
        password: dbpass
        driver-class-name: com.mysql.jdbc.Driver

以下内容:
实际上,Spring Boot应用程序有多种设置途径。Spring Boot能从多种属性源获得属性,包括如下几处。
(1) 命令行参数
(2) java:comp/env 里的JNDI属性
(3) JVM系统属性
(4) 操作系统环境变量
(5) 随机生成的带 random.* 前缀的属性(在设置其他属性时,可以引用它们,比如 ${random.long} )
(6) 应用程序以外的application.properties或者appliaction.yml文件
(7) 打包在应用程序内的application.properties或者appliaction.yml文件
(8) 通过 @PropertySource 标注的属性源
(9) 默认属性
这个列表按照优先级排序,也就是说,任何在高优先级属性源里设置的属性都会覆盖低优先级的相同属性。例如,命令行参数会覆盖其他属性源里的属性。application.properties和application.yml文件能放在以下四个位置。
(1) 外置,在相对于应用程序运行目录的/config子目录里。
(2) 外置,在应用程序运行的目录里。
(3) 内置,在config包内。
(4) 内置,在Classpath根目录。

应用程序 Bean 的配置外置

@RequestMapping("/")
@ConfigurationProperties(prefix="amazon")
public class ReadingListController {
    private String associateId;
    private ReadingListRepository readingListRepository;
    @Autowired
    public ReadingListController(
        ReadingListRepository readingListRepository) {
        this.readingListRepository = readingListRepository;
    }
    public void setAssociateId(String associateId) {
      this.associateId = associateId;
    }

如你所见, ReadingListController 现在有了一个 associateId 属性,还有对应的 setAssociateId() 方法,用它可以设置该属性。 readersBooks() 现在能通过 amazonID 这个键把associateId 的值放入模型。
棒极了!现在就剩一个问题了——从哪里能取到 associateId 的值。
请注意, ReadingListController 上加了 @ConfigurationProperties 注解,这说明该Bean的属性应该是(通过setter方法)从配置属性值注入的。说得更具体一点, prefix 属性说明ReadingListController 应该注入带 amazon 前缀的属性。
综合起来,我们指定 ReadingListController 的属性应该从带 amazon 前缀的配置属性中进行注入。 ReadingListController 只有一个setter方法,就是设置 associateId 属性用的setter方法。因此,设置Amazon Associate ID唯一要做的就是添加 amazon.associateId 属性,把它加入支持的任一属性源位置里即可。
在application.yml里设置:

amazon:
  associateId: habuma-20

在一个类里收集属性

虽然在 ReadingListController 上加上 @ConfigurationProperties 注解跑起来没问题,但这并不是一个理想的方案。 ReadingListController 和Amazon没什么关系,但属性的前缀却是 amazon ,这看起来难道不奇怪吗?再说,后续的各种功能可能需要在 ReadingListController 里新增配置属性,而它们和Amazon无关。
与其在 ReadingListController 里加载配置属性,还不如创建一个单独的Bean,为它加上@ConfigurationProperties 注解,让这个Bean收集所有配置属性。代码清单3-5里的 Amazon-Properties 就是一个例子,它用于加载Amazon相关的配置属性。

@Component
@ConfigurationProperties("amazon")
public class AmazonProperties {
private String associateId;
    public void setAssociateId(String associateId) {
        this.associateId = associateId;
    }
    public String getAssociateId() {
        return associateId;
    }
}

有了加载 amazon.associateId 配置属性的 AmazonProperties 后,我们可以调整
ReadingListController (如代码清单3-6所示),让它从注入的 AmazonProperties 中获取
Amazon Associate ID。

使用 Profile 进行配置

当应用程序需要部署到不同的运行环境时,一些配置细节通常会有所不同。比如,数据库连接的细节在开发环境下和测试环境下就会不一样,在生产环境下又不一样。Spring Framework从Spring 3.1开始支持基于Profile的配置。Profile是一种条件化配置,基于运行时激活的Profile,会使用或者忽略不同的Bean或配置类。

@Profile("production")
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
...
}

这里用的 @Profile 注解要求运行时激活 production Profile,这样才能应用该配置。如果production Profile没有激活,就会忽略该配置,而此时缺少其他用于覆盖的安全配置,于是应用自动配置的安全配置。
向application.yml里添加 spring.profiles.active 属性:

spring:
  profiles:
    active: production

使用多Profile YAML文件进行配置

如果使用YAML来配置属性,则可以遵循与配置文件相同的命名规范,即创建application-{profile}.yml这样的YAML文件,并将与Profile无关的属性继续放在application.yml里。但既然用了YAML,你就可以把所有Profile的配置属性都放在一个application.yml文件里。举例来说,我们可以像下面这样声明日志配置:

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

推荐阅读更多精彩内容