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 配置文件說明

  1. 默認的配置文件爲 application.properties 需要放在 classpath 路徑中,或者 config/application.properties
  2. –spring.config.name 指定配置文件名稱
  3. –spring.config.location 指定配置文件的路徑,多個用逗號分割
    指定方式有兩種 1:classpath 2:file
  4. 可以使用註解 @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 自定義事件

  1. 自定義事件,繼承ApplicationEvent抽象類
  2. 定義事件監聽器,實現ApplicationListener接口
  3. 配置監聽器,啓動的時候需要把監聽器添加到Spring容器中
  4. 發佈時間,使用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 的區別

  1. 接受的參數不一樣,CommandLineRunner 接受main類型參數[–my=admin],ApplicationRunner接受封裝類型參數
  2. CommandLineRunner 參數是原始參數,沒有任何處理[–my=admin]
  3. ApplicationRunner 參數是ApplicationArguments ,是對參數做了進一步的封裝。可以直接通過參數名字獲取參數值

Spring Boot 自定義Banner

  1. 關閉Banner, SpringApplication.setBannerMode(Banner.Mode.OFF);
  2. 在classpath中放入banner.txt 文件可自定義
  3. banner.location 配置項指定 banner文本文件位置
  4. banner.charset 配置項用來指定banner的編碼.默認UTF-8
  5. banner 支持圖片格式,支持的格式爲png、jpg、gif
  6. banner.image.location 配置項指定 圖片Banner的文件路徑

Spring Boot 運行流程分析

image

Spring 配置

  1. server.port 配置Web端口

Spring Boot 使用ServletAPI

方式1:使用註解

  1. 啓用Servlet,註解爲@ServletComponentScan
  2. Servlet,Filter,Listener,可以使用Servlet3.x 註解:例如:@WebServlet,@WebFilter,@WebListener

方式2:Servlet < 3.0

  1. 編寫相應的接口實現類
  2. 注入到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 禁用默認異常頁面

  1. 修改配置項:server.error.whitelabel.enabled = false (默認爲True)
  2. 方式2:排除WhitelabelErrorViewConfiguration類
  3. 自定義400頁面,實現ErrorPageRegistrar接口即可
  4. Spring MVC Controller中處理異常,註解也可指定要處理的異常類型
    @ExceptionHandler
    public String error(Exception e) {
        return "file not Found!";
    }
  1. 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

  1. 在pom文件中添加AOP依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
  1. 添加切入點類
@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()));
    }
}
  1. Spring Boot Aop常用配置
    配置文件位置: AopAutoConfiguration
# 是否啓用AOP,默認啓用
spring.aop.auto=true 

# true 使用JDK代理(類需要有接口),false - cgLib代理
spring.aop.proxy-target-class=true

自定義Spring Boot Starter

  1. 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>
  1. 編寫配置類:
@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;
    }
}
  1. 編寫屬性文件配置類:
@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;
    }

}
  1. META-INF/spring.properties 中添加配置,或者使用@Impoert註解導入
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.aimilin.JedisAutoConfiguration
  1. 使用: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 日誌格式自定義

  1. 配置項 logging.file 指定日誌文件名稱
  2. 配置項 logging.path 指定日誌目錄(此時的日誌名稱爲spring.log)
  3. 日誌文件輸出,文件的默認大小爲10M,超過會自動分隔
  4. logging.pattern.console 配置控制檯輸出日誌格式
  5. logging.pattern.file 配置文件日誌輸出格式

Spring Boot 默認使用LogBack作爲日誌框架

也就是說,只需要在classpath中添加一個 logback.xml 或者logback-spring.xml 文件,就可以自定義日誌的輸出

Spring Boot 使用其他日誌的步驟

  1. pom.xml中排除默認日誌框架依賴
  2. 加入新的日誌框架依賴
  3. 添加相應的日誌配置文件到classpath中
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章