SpringBoot自定义配置
使用传统Spring配置的过程中,我们可以完全控制Spring配置的内容,可是显示声明应用程序里全部的Bean并不是明智之举。而使用Spring Boot自动配置,让Spring Boot处理各种细节比自己声明上下文里全部的Bean要容易很多。
幸运的是,Spring Boot自动配置十分灵活,Spring Boot能让你参与进来,影响自动配置的实施。
这里我们将介绍两种方式——使用显式进行覆盖和使用属性进行精细化配置。
1、覆盖SpringBoot自动配置
大多数情况下,自动配置的Bean刚好能满足需要,不需要去覆盖它们。但某些特定情况下,Spring Boot在自动配置时还不能很好地进行推断。
例如,当需要在程序中添加安全特性时,围绕程序安全有许多决策要做,SpringBoot并不能帮你做决定,SpringBoot虽然为安全提供了一些基本的自动配置,但我们还是需要去覆盖它来满足一些特定的场景需求。
项目中添加Security配置,使用Maven的情况下,首先需要在Maven中添加相关的项目依赖如下:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
重新构建运行项目,即一个安全的Web程序,Security起步依赖在应用程序的Classpath里添加了Spring Secuirty和其它一些东西。Classpath里 有Spring Security后,自动配置就能介入其中创建一个基本的Spring Security配置。
然而,此时http访问项目时,将只有一个特定的账号密码用于登陆校验,且密码将随机生成并写入日志,我们需要的是通过数据库或者其他一些登陆手段来进行用户登录,因此我们需要覆盖自动配置对Spring Secuirty进行一些配置。
覆盖自动配置的方法,即当原自动配置不存在即可,我们直接创建一个配置类,使用XML或者直接使用Java皆可,这里使用Java即意味着需要扩展WebSecurityConfigurerAdapter的配置类。如下:
@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");
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(new UserDetailsService() {
@Override
public UserDetails loadUserByUsername(String username)throws UsernameNotFoundException {
return readerRepository.findOne(username);
}
});
}
}
如上,我们覆盖了该类的两个configue()方法,第一个configue()方法中指明,访问"/"路径时,只有经过权限校验,角色为‘READER’的用户能够访问,其他的访问路径则对所有的用户开放权限,并将登陆页和登陆失败页指定到/login。
第二个configue()方法中我们可通过jpa持久化操作来获取校验我们的用户信息,在Reader实体当中,可覆盖UserDetails方法中的授权方法,赋予READER角色,这样我们便可通过验证登陆。
也就是说,我们要覆盖SpringBoot的自动配置,我们需要做的只是显示的编写一个配置,SpringBoot会发现并执行你的配置。
自动配置原理
为什么我们能够显示的直接覆盖SpringBoot的自动配置,Spring Boot自动配置自带了很多配置类,每一个都能运用在我们的应用程序里。它们都使用了Spring 4.0的条件化,可以在运行时判断这个配置是该运用,还是该被忽略。
@ConditionalOnMissingBean注解是覆盖自动配置的关键。如下:
@Bean
@ConditionalOnMissingBean(JdbcOperations.class)
public JdbcTemplate jdbcTemplate() {
return new JdbcTemplate(this.dataSource);
}
JdbcTemplate类上有@Bean注解,可在需要时配置出一个JdbcTemplate的Bean,但是它的@ConditionalOnMissingBean注解表明,只有当前不存在JdbcOperations的Bean时,该配置类才生效。
什么情况下会存在一个JdbcOperations Bean呢?Spring Boot的设计是加载应用级配置,随后再考虑自动配置。因此,如果已经配置了一个JdbcTemplate Bean,那么在执行自动配置时就已经存在在一个JdbcOperations类型的Bean了,于是忽略自动配置的JdbcTemplate Bean。
2、通过属性外置配置
显然当我们只需要修改一些自动配置的细节的时候,我们完全没有必要去显示声明一个定义完整的配置类,那么这时候我们可以通过属性文件来微调我们需要变更的属性。
这里可在启动时通过命令行方式来指定,但我们一般在properties或者yml文件中进行调整,或者通过@PropertySource标记的属性源。例如:
创建一个名为application.properties的文件,包含如下内容:spring.main.show-banner=false。
我们一般需要在这类配置文件中,配置以下一些信息:
1、禁用模板缓存
2、配置嵌入式服务
3、配置日志 logback.xml
4、配置数据源
等等。