1. Spring Boot 简介
1.1 Spring 是什么?
Spring 包括了用来简化 java 开发的多种框架,用于不同的场景,其中最为基础的是 Spring Framework,功能有:
-  IoC - 整合其他框架,Spring 两大核心技术之一 
-  AOP - 通用操作的横切处理,Spring 两大核心技术之一 
-  事务 - 无需编写代码,即可实现数据库事务管理 
-  测试 - 与测试框架集成、web 单元测试 
-  MVC - 开发 web 应用程序 
-  缓存 - 对缓存进行抽象 
-  调度 - 延时任务、定时任务 
Spring Framework 在开发中的作用:
-  分层解耦 - 让单体应用的可扩展性更强 
-  整合框架 - 整合第三方框架,使之协同工作 
-  实用技术 - 自身强大,提供各种实用功能 
1.2 Spring Boot 是什么?
Spring Boot 可以帮助我们开发【基于Spring的】、【独立的】、【生产级的】应用程序
它的主要目标是:
-  为所有 Spring 开发提供更快的入门体验 
-  开箱即用,提供了自动配置 
-  提供一系列大型项目通用的非功能性特性 -  外部化配置 
-  嵌入式服务器 
-  安全性 
-  健康检查 
-  指标 
 
-  
-  完全不需要代码生成,也不需要XML配置 
基于版本:2.6.3
1.3Spring核心
一、让Spring容器确定要加载的类
@Component
public class MyService {}二、获取Spring容器对象
ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args);三、获取Spring容器管理的对象
MyService myService = context.getBean(MyService.class);1.4入门案例
Spring Boot 提供了方便的手段来快速生成项目骨架
1)创建新模块

2)输入项目信息

3)选择项目依赖和Springboot的版本

4)创建

5)创建service包,并创建MyService类
@Component
public class MyService {
}6)在DemoApplication类中编写代码
@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        //获取Spring容器
        ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args);
        //获取容器的对象
        System.out.println(context.getBean(MyService.class));
    }
}其中 @SpringBootApplication 代表此类是 Spring Boot 程序的入口,也称为引导类 .
1.5 单元测试
Spring 可以结合 JUnit 完成单元测试,测试用例中也可以利用 @Autowired 来注入待测对象,只要它被 Spring 所管
@SpringBootTest
class DemoApplicationTests {
    @Autowired
    private MyService myService; // 注入任意由容器管理的对象
    @Test
    void test1() {
        // 使用 service
    }
}容器对象自身也可以使用 @Autowired 注入,容器类型可以使用接口类型:ApplicationContext
@SpringBootTest
class Demo1ApplicationTests {
    @Autowired
    private ApplicationContext context; // 注入容器自身
    @Test
    void test2() {
        // 使用 context
    }
}2. IoC
2.1 控制反转
刚才解耦的例子中,涉及到 Spring 的两个核心概念
-  把对象的控制权交给容器管理,称之为控制反转 
-  建立容器管理对象之间的依赖关系,称之为依赖注入 
控制反转:即用容器管理对象。原本由程序(员)干的活:对象创建、生命周期方法调用、读取外部配置等,都交给了容器负责。控制权发生了转移
IoC 容器负责管理:对象的创建权、生命周期、外部配置等
-  未应用 IoC 之前,是我们自己去创建对象、调用它们的初始化方法等 
-  应用了 IoC 之后,是由容器来创建和管理对象 
1) bean 的扫描
要把某个对象交给 Spring 管理,需要向类上标注如下注解之一
-  @Controller - 把标注的控制器类交给 Spring 管理 
-  @Service - 把标注的业务服务类交给 Spring 管理 
-  @Repository - 把标注的数据访问类交给 Spring 管理(用得少,因为与 MyBatis 整合) 
-  @Component - 不属于上述三类的用此注解 
这些注解
-  都是加在类上,不能加在接口上(没有意义) 
-  都可以用来指定 bean 的 id,如果没有指定,默认 id 为类名的小驼峰命名,例如 MyService 类的默认 id 为 myService 
隐藏的注解 @ComponentScan
-  它被包含在引导类的 @SpringBootApplication 注解内,用来扫描前面的四大注解 
-  默认扫描的范围为引导类的所在包内 
2) bean 的获取
Spring 容器启动时,会把其中的 bean 都创建准备好,如果想要主动获取这些 bean,可以使用如下方法
-  根据类型获取 bean - <T> T getBean(Class<T> requiredType)-  可以传递父类型,返回子类型 
-  可以传递接口类型,返回实现类型 
 
-  
-  根据 id 获取 bean - Object getBean(String name)
-  根据 id 获取 bean(带类型转换) - <T> T getBean(String name, Class<T> requiredType)
getBean 例子
@Component
public class MyService1 {
}测试
@Test
@DisplayName("测试两种不同 getBean")
public void test01() {
    MyService1 bean1 = context.getBean(MyService1.class);
    Assertions.assertNotNull(bean1);
    MyService1 bean2 = context.getBean("myService1", MyService1.class);
    Assertions.assertNotNull(bean2);
}3) bean 的 scope
Spring 支持五种作用域,后三种在 web 环境才生效
-  singleton - 容器内同 id 的 bean 只有一个实例(默认) 
-  prototype - 每次使用该 bean 时会创建新的实例 
-  request - 在 web 环境中,每个请求范围内会创建新的实例 
-  session - 在 web 环境中,每个会话范围内会创建新的实例 
-  application- 在 web 环境中,每个应用范围内会创建新的实例 
以上五种作用域,配合 @Scope 注解来进行配置
singleton 例子
@Component
@Scope("singleton") // 不加一样
public class MyService2 {
}测试1
@Test
@DisplayName("测试 scope=singleton 的特征")
public void test02() {
    MyService2 bean1 = context.getBean("myService2", MyService2.class);
    MyService2 bean2 = context.getBean("myService2", MyService2.class);
    Assertions.assertEquals(bean1, bean2);
}  测试2
@Test
@DisplayName("测试 scope=singleton 的特征(不同容器)")
public void test03() {
    ConfigurableApplicationContext context1 = SpringApplication.run(Demo1Application.class);
    ConfigurableApplicationContext context2 = SpringApplication.run(Demo1Application.class);
    MyService2 bean1 = context1.getBean("myService2", MyService2.class);
    MyService2 bean2 = context2.getBean("myService2", MyService2.class);
    Assertions.assertNotEquals(bean1, bean2);
}prototype 例子
@Component
@Scope("prototype")
public class MyService3 {
}测试
@Test
@DisplayName("测试 scope=prototype 的特征")
public void test04() {
    MyService3 bean1 = context.getBean(MyService3.class);
    MyService3 bean2 = context.getBean(MyService3.class);
    Assertions.assertNotEquals(bean1, bean2);
}4) bean 的初始化与销毁
-  标注了 @PostConstruct 的方法是初始化方法,会在 bean 被创建之后调用 
-  标注了 @PreDestroy 的方法是销毁方法,singleton 的 bean 的销毁方法会在容器关闭前被调用 
初始化例子
@Component
public class MyService4 {
    private boolean initialized = false;
    @PostConstruct
    public void init() {
        initialized = true;
    }
    public boolean isInitialized() {
        return initialized;
    }
}测试
@Test
@DisplayName("测试 init-method 的特征")
public void test05() {
    MyService4 bean = context.getBean(MyService4.class);
    Assertions.assertTrue(bean.isInitialized());
}销毁例子
@Component
public class MyService5 {
    private boolean destroyed = false;
    @PreDestroy
    public void destroy() {
        destroyed = true;
    }
    public boolean isDestroyed() {
        return destroyed;
    }
}测试
@Test
@DisplayName("测试 destroy-method 的特征")
public void test06() {
    // 当前容器 close 会导致测试错误,因此新建一个容器来测试 close
    ConfigurableApplicationContext context = SpringApplication.run(Demo1Application.class);
    MyService5 bean = context.getBean(MyService5.class);
    context.close();
    Assertions.assertTrue(bean.isDestroyed());
} 延迟初始化例子
-  默认情况下 singleton 的 bean 是容器创建时,就会创建 
-  如果希望用到时才创建,可以使用 @Lazy注解标注在类上来延迟创建
@Component
@Lazy
public class MyService6 {
    public static boolean isConstructed = false;
    public MyService6() {
        isConstructed = true;
    }
}
5) 管理第三方的 bean
如果要管理的对象来自于第三方,这时是无法用 @Component 等注解来实现的,解决方法要用到 @Bean
管理第三方 bean 例子
已知 DruidDataSource 基本用法如下
1. 创建 druid 连接池对象
DruidDataSource dataSource = new DruidDataSource();2. 设置连接池属性
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/test?useSSL=false&useUnicode=true&characterEncoding=UTF-8");
dataSource.setUsername("root");
dataSource.setPassword("root");
dataSource.setMaxActive(3);
dataSource.setMinIdle(1);
dataSource.setInitialSize(1);3. 初始化方法
dataSource.init();4. 销毁方法
dataSource.close();尝试用 Spring 管理它,并设置其初始化和销毁方法,连接信息注意改为自己的
1)pom.xml
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.16</version>
</dependency>
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>2)Demo1Application.java
@SpringBootApplication
public class Demo1Application {
       @Bean
    public DruidDataSource dataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        // 2. 设置连接池属性
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/aaaa?useSSL=false&useUnicode=true&characterEncoding=UTF-8");
        dataSource.setUsername("root");
        dataSource.setPassword("1234");
        dataSource.setMaxActive(3);
        dataSource.setMinIdle(1);
        dataSource.setInitialSize(1);
        return dataSource;
    }
    // ...
@Bean 标注的方法放在引导类中,它返回的对象由 Spring 管理,如果未加指定,则使用方法名作为 bean 的 id
3)测试
@Test
@DisplayName("测试 @Bean 的特征")
public void test08() {
    System.out.println(context.getBean(DataSource.class));
}注意
-  对于 @Bean 来说,销毁方法如果不设置,默认会找名为 close 或 shutdown 的方法当做销毁方法 
关注我不迷路,持续更新中.....










