- Spring Bean 初始化与销毁回调
- Spring Boot pom.xml 文件继承两种方式
- Spring Boot 获取properties文件三种方式
- Spring Boot Properties 变量引用
- Spring Boot Properties 变量使用默认值
- Spring 配置文件说明
- Spring Boot 生产环境与测试环境使用不同的配置文件
- Spring 按条件装配
- Spring Boot @Enable*注解工作原理
- String @EnabelAutoConfiguration深入分析
- Spring Boot 自定义事件
- Spring Boot 扩展点
- Spring Boot 自定义Banner
- Spring Boot 运行流程分析
- Spring 配置
- Spring Boot 使用ServletAPI
- Spring MVC Interceptor 使用
- Spring Boot 禁用默认异常页面
- Spring Boot 定制和优化内置的Tomcat
- Spring Boot 使用Druid数据源
- Spring Boot 使用AOP
- 自定义Spring Boot Starter
- Spring Boot 日志格式自定义
Spring Bean 初始化与销毁回调
1. 使用Spring接口
package com.edu.spring;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
public class Car implements InitializingBean, DisposableBean{
@Override
public void destroy() throws Exception {
System.out.println("============Car destroy=============");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("==========Car afterPropertiesSet==========");
}
}
2. 使用Spring Bean注解属性
@Bean(initMethod="init", destroyMethod="destory")
3. 使用Spring注解方式
@PostConstruct
public void init2() {
System.out.println("=============Car init2=============");
}
@PreDestroy
public void destory2() {
System.out.println("==============Car destory2================");
}
Spring Boot pom.xml 文件继承两种方式
方式1: 直接继承
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
方式2: 使用Pom依赖
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.0.0.RELEASE</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
Spring Boot 默认配置文件名称为 application.properties
Spring Boot 获取properties文件三种方式
配置如下:
local.ip=127.0.0.1
local.port=8080
方式1: 通过 getEnvironment 直接获取
@SpringBootApplication
public class Main {
public static void main(String[] args) {
ConfigurableApplicationContext app = SpringApplication.run(Main.class);
System.out.println("local.ip=" + app.getEnvironment().getProperty("local.ip"));
}
}
方式2:通过注入 Envirnoment 属性获取
@Component
public class MyConfig {
@Autowired
private Environment env;
public void show() {
System.out.println(env.getProperty("local.ip"));
}
}
方式3:使用Value注解直接注入
@Component
public class MyConfig {
@Value("${local.ip}")
private String ip;
@Value("${local.port}")
private String port;
public void show() {
System.out.println(ip + ", "+ port);
}
}
方式4:使用属性对象直接注入
配置文件如下:
ds.url=jdbc:mysql://127.0.0.0/
ds.driverClassName=com.mysql.jdbc.Driver
ds.username=root
ds.password=123456
ds.ports[0]=8080
ds.ports[1]=8081
ds.ports[2]=8082
@Component
@ConfigurationProperties(prefix="ds")
public class DataBase {
private String url;
private String driverClassName;
private String username;
private String password;
private String[] ports;//可以注入数组类型或List类型
// 省略 Getter 和Setter方法
public void show() {
System.out.println("=========dirver==========");
System.out.println("url:"+url);
System.out.println("dirverClassName:"+ this.driverClassName);
System.out.println("username:"+username);
System.out.println("password:"+password);
System.out.println("ports:"+ports);
}
}
Spring Boot Properties 变量引用
local.ip=127.0.0.1
local.port=8080
# 这里使用了上面两个变量
local.host=${local.ip}:${local.port}
@Component
public class MyConfig {
@Value("${local.host}")
private String host;
public void show() {
System.out.println(host);
}
}
Spring Boot Properties 变量使用默认值
@Value("${local.port2:9090}")
private String port;
SpringApplication.setDefaultProperties(Map
Spring 配置文件说明
- 默认的配置文件为 application.properties 需要放在 classpath 路径中,或者 config/application.properties
- –spring.config.name 指定配置文件名称
- –spring.config.location 指定配置文件的路径,多个用逗号分割
指定方式有两种 1:classpath 2:file - 可以使用注解 @PropertySource(“classpath:”)或者 @PropertySources()
Spring Boot 生产环境与测试环境使用不同的配置文件
默认配置文件 application.properties
ds.url=jdbc:mysql://127.0.0.0/
ds.driverClassName=com.mysql.jdbc.Driver
ds.username=root
ds.password=123456
测试环境配置文件 application-test.properties
ds.url=jdbc:mysql://127.0.0.0/test
生产环境配置文件 application-product.properties
ds.url=jdbc:mysql://127.0.0.0/product
使用方式如下:
1.使用Java代码设置环境
SpringApplication app = new SpringApplication(Main.class);
// 指定使用的环境 test 或 product
app.setAdditionalProfiles("test");
ConfigurableApplicationContext config = app.run(args);
2.使用启动参数指定:(多个使用逗号分割)
--spring.profiles.active=test
3.Bean装配时可以使用注解 @Profile(“test”) 指定Bean的生效环境
Spring 按条件装配
编码转换接口
public interface EncodingConvert {
}
UTF-8编码转换类
public class UTF8EncodingConvert implements EncodingConvert{
}
GBK 编码转换类
public class GBKEncodingConvert implements EncodingConvert{
}
GBK 条件装配Condition
public class GBKCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String encoding = System.getProperty("file.encoding");
return "gbk".equalsIgnoreCase(encoding);
}
}
UTF-8条件装配类
public class UTF8Condition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String encoding = System.getProperty("file.encoding");
return "utf-8".equalsIgnoreCase(encoding);
}
}
条件装配使用如下:
@SpringBootConfiguration
public class EncodingConfiguration {
@Bean
@Conditional(UTF8Condition.class)
public EncodingConvert createUtf8() {
return new UTF8EncodingConvert();
}
@Bean
@Conditional(GBKCondition.class)
public EncodingConvert createGbk() {
return new GBKEncodingConvert();
}
}
运行方法:
@SpringBootApplication
public class Main {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(Main.class);
ConfigurableApplicationContext config = app.run(args);
System.out.println(config.getBeansOfType(EncodingConvert.class));
}
}
可以在运行时指定编码:
-Dfile.encoding=GBK
运行结果
{createGbk=com.edu.spring.GBKEncodingConvert@6b8d96d9}
Spring Boot 提供的条件装配
使用比较多的条件装配
1. @ConditionalOnProperty 根据属性确认
2. @ConditionalOnClass(name=”com.google.gson.Gson”) Classpath中存在类才装配
3. @ConditionalOnBean(name=”user”) 存在Bean时装配
Spring Boot @Enable*注解工作原理
@EnableConfigurationProperties 启用配置文件属性注入到Bean里面去
Spring Boot 异步执行,@EnableAsync(启用异步) @Async
@Enable*注解工作原理
其核心思想是通过@Import注解将Bean对象注入Spring容器
以下是一个简单的Bean信息打印Demo
1. 编写注解类,使用@Import注解实现相应的功能
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
//通过@Import注解指定的Class解析该注解,Import注解接收的参数:Configuration、
// ImportSelector、ImportBeanDefinitionRegistrar
@Import(EnableEchoImportBeanDefinitionRegistrar.class)
public @interface EnableEcho {
String[] packages();
}
2. @EnableEcho注解解析类
public class EnableEchoImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 获取EnableEcho注解中packages属性值
Map<String, Object> attr = importingClassMetadata.getAnnotationAttributes(EnableEcho.class.getName());
List<String> packages = Arrays.asList((String[]) attr.get("packages"));
// 通过 BeanDefinitionBuilder 构建 BeanDefinition
BeanDefinitionBuilder bdb = BeanDefinitionBuilder.genericBeanDefinition(EchoBeanPostProcessor.class);
bdb.addPropertyValue("packages", packages);// 设置属性
// 将EchoBeanPostProcessor 直接注入Spring容器中
registry.registerBeanDefinition(EchoBeanPostProcessor.class.getSimpleName(), bdb.getBeanDefinition());
}
}
3. Bean对象初始化时打印日志信息
public class EchoBeanPostProcessor implements BeanPostProcessor {
private List<String> packages;
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
for (String pack : packages) {
if (bean.getClass().getName().startsWith(pack)) {
System.out.println("echo bean: " + bean.getClass().getName());
}
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
public List<String> getPackages() {
return packages;
}
public void setPackages(List<String> packages) {
this.packages = packages;
}
}
String @EnabelAutoConfiguration深入分析
1.@EnableAutoConfiguration 作用:从classpath中搜索所有META-INF/spring.factories配置文件
然后,将其中org.springframework.boot.autoconfigure.EnableAutoConfiguration key对应的
配置添加到spring容器中
2.只有spring.boot.enableautoconfiguration为true(默认为true)时,才启用自动配置
@EnableAutoConfiguration还可以进行排除,排除方式有两种,1:class排除(exclude),2:class name 排除(excludename)
3.其内部实现关键点:
1. ImportSelector 该接口的方法的返回值都会被纳入到spring容器管理中
2. SpringFactoriesLoader 该类可以冲classpath中搜索所有META-INF/spring.factories配置文件,并读取配置
Spring Boot 自定义事件
- 自定义事件,继承ApplicationEvent抽象类
- 定义事件监听器,实现ApplicationListener接口
- 配置监听器,启动的时候需要把监听器添加到Spring容器中
- 发布时间,使用ApplicationContext.publishEvent()发布事件
配置事件监听器
1. SpringApplication,addListeners 添加监听器
2. 通过注解把监听器纳入到Spring容器中
3. 使用context.listener.classes配置项,指定监听器
4. 使用@EvenetListener 注解,在方法上面加入@EventListener注解,该类也需要纳入Spring容器管理
5. 在META-INF/spring.factories 文件中配置key=value;key 接口全路径=实现类全路径
Spring Boot 扩展点
ApplicationContextInitializer接口是在Spring容器执行refreshed之前的一个回调
使用步骤:
1. 实现ApplicationContextInitializer接口
2. 注册ApplicationContextInitializer
注册方式:
1. SpringApplication.addInitializers
2. 通过配置项:context.initalizer.classes 指定,多个使用逗号分割
3. 使用META-INF/spring.factories 机制,注册 key(接口全路径)=value(实现类全路径)
CommandLineRunner 和ApplicationRunner
CommandLineRunner、ApplicationRunner 接口实在容器启动成功后的最后一步回调
使用步骤:
1. 实现CommandLineRunner 接口
2. 把该类纳入到Spring容器的管理中
注意:可以通过@Order注解或者Ordered接口来控制执行顺序
CommandLineRunner 和 ApplicationRunner 的区别
- 接受的参数不一样,CommandLineRunner 接受main类型参数[–my=admin],ApplicationRunner接受封装类型参数
- CommandLineRunner 参数是原始参数,没有任何处理[–my=admin]
- ApplicationRunner 参数是ApplicationArguments ,是对参数做了进一步的封装。可以直接通过参数名字获取参数值
Spring Boot 自定义Banner
- 关闭Banner, SpringApplication.setBannerMode(Banner.Mode.OFF);
- 在classpath中放入banner.txt 文件可自定义
- banner.location 配置项指定 banner文本文件位置
- banner.charset 配置项用来指定banner的编码.默认UTF-8
- banner 支持图片格式,支持的格式为png、jpg、gif
- banner.image.location 配置项指定 图片Banner的文件路径
Spring Boot 运行流程分析
Spring 配置
- server.port 配置Web端口
Spring Boot 使用ServletAPI
方式1:使用注解
- 启用Servlet,注解为@ServletComponentScan
- Servlet,Filter,Listener,可以使用Servlet3.x 注解:例如:@WebServlet,@WebFilter,@WebListener
方式2:Servlet < 3.0
- 编写相应的接口实现类
- 注入到Spring容器
- Servlet ServletRegistrationBean
- Filter FilterRegistrarionBean
- Listener ServletListenerRegistrationBean
Spring MVC Interceptor 使用
拦截器接口 HandlerInterceptor
1. 实现HandlerInterceptor接口
2. 继承WebMvcConfigurerAdapter类,重写addInterceptors方法,添加Interceptor类
+ HandlerInterceptor接口方法说明
- preHandle: controller 执行之前回调
- postHandle: controller执行之后调用
- afterCompletion: 页面渲染之后回调,一般用于资源清理工作
Spring Boot 禁用默认异常页面
- 修改配置项:server.error.whitelabel.enabled = false (默认为True)
- 方式2:排除WhitelabelErrorViewConfiguration类
- 自定义400页面,实现ErrorPageRegistrar接口即可
- Spring MVC Controller中处理异常,注解也可指定要处理的异常类型
@ExceptionHandler
public String error(Exception e) {
return "file not Found!";
}
- Spring MVC全局异常处理类
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler
@ResponseBody
public String errorHandler(Exception e) {
return "global error :" + e.getMessage();
}
}
Spring Boot 定制和优化内置的Tomcat
Spring Boot 内嵌支持 tomcat,jetty
1. server.port 配置项,修改端口
2. 其他配置参见:org.springframework.boot.autoconfigure.web.ServerProperties
3.
Spring Boot 使用Druid数据源
1. pom中添加druid依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.9</version>
</dependency>
2. 使用代码方式添加数据源
@SpringBootConfiguration
public class DruidDataSourceConfiguration {
@Autowired
private DataSourceProperties dataSourceProperties;
@Bean
public DataSource createDruidDataSource() {
DruidDataSource ds = new DruidDataSource();
ds.setUrl(dataSourceProperties.getUrl());
ds.setDriverClassName(dataSourceProperties.getDriverClassName());
ds.setUsername(dataSourceProperties.getUsername());
ds.setPassword(dataSourceProperties.getPassword());
return ds;
}
}
3. 添加数据源配置项
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?useSSL=false
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root
Spring Boot 使用AOP
- 在pom文件中添加AOP依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
- 添加切入点类
@Component
@Aspect
public class LogAop {
@Before("execution(* com.aimilin.demo..*.*(..))")
public void before() {
System.out.println("start ---- log");
}
@After("execution(* com.aimilin.demo..*.*(..))")
public void after(JoinPoint joinPoint) {
System.out.println(
"after --------log, Class: " + joinPoint.getTarget().getClass() + "\n" +
"Method: " + joinPoint.getSignature().getName() + "\n" +
"Args :" + Arrays.asList(joinPoint.getArgs()));
}
}
- Spring Boot Aop常用配置
配置文件位置: AopAutoConfiguration
# 是否启用AOP,默认启用
spring.aop.auto=true
# true 使用JDK代理(类需要有接口),false - cgLib代理
spring.aop.proxy-target-class=true
自定义Spring Boot Starter
- pom中添加依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
</dependencies>
- 编写配置类:
@Configuration
@EnableConfigurationProperties(JedisProperties.class)
@ConditionalOnClass(Jedis.class)
public class JedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public Jedis jedis(JedisProperties jedisProperties) {
Jedis jedis = new Jedis(jedisProperties.getHost(), jedisProperties.getPort());
jedis.auth(jedisProperties.getPassword());
System.out.println("jedis-----------init");
return jedis;
}
}
- 编写属性文件配置类:
@ConfigurationProperties(prefix = "redis")
public class JedisProperties {
private String host;
private Integer port;
private String password;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
}
- META-INF/spring.properties 中添加配置,或者使用@Impoert注解导入
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.aimilin.JedisAutoConfiguration
- 使用:pom导入依赖:
<dependency>
<groupId>com.aimilin</groupId>
<artifactId>spring-boot-starter-redis</artifactId>
<version>1.0.0</version>
</dependency>
@Component
public class RedisTest {
@Autowired
private Jedis jedis;
public void run() {
jedis.set("hello", "text");
System.out.println("redis ---- text");
}
}
Spring Boot 日志格式自定义
- 配置项 logging.file 指定日志文件名称
- 配置项 logging.path 指定日志目录(此时的日志名称为spring.log)
- 日志文件输出,文件的默认大小为10M,超过会自动分隔
- logging.pattern.console 配置控制台输出日志格式
- logging.pattern.file 配置文件日志输出格式
Spring Boot 默认使用LogBack作为日志框架
也就是说,只需要在classpath中添加一个 logback.xml 或者logback-spring.xml 文件,就可以自定义日志的输出
Spring Boot 使用其他日志的步骤
- pom.xml中排除默认日志框架依赖
- 加入新的日志框架依赖
- 添加相应的日志配置文件到classpath中