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中

猜你喜欢

转载自blog.csdn.net/afgasdg/article/details/79758674