- 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中