课程介绍
- Spring
- SpringMvc 代替Servlet
- Mybatis 代替JDBC
- SSM整合
- SpringBoot
- 单体稻草项目
- 微服务(SpringCloud)
- 微服务组件(Redis,ES,Kafka)
什么是框架
框架就是第三方编写的项目半成品
使用上也是下载一些jar包到本地
为什么需要框架
将一些本来很复杂的操作简化
使用框架时,前期先不纠结内部原理和源码
Spring概述
什么是Spring
实现IOC和DI工具
IOC:控制翻转
普通的主动控制:需要什么对象时自己实例化
IOC控制翻转:需要什么从Spring容器中取
Spring提供了"Spring容器"
为什么需要Spring
将程序中所有需要的组件(对象)都保存在Spring容器中
在需要的时候获得,如果Spring容器中保存的对象变化,获得的代码不不需要修改的
这样就能提高程序的可维护性和可扩展性
怎么使用Spring
创建一项目
pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>SpringDay01</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<!-- 设置 JDK 版本为 1.8 -->
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<!-- 设置编码为 UTF-8 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
</properties>
<dependencies>
<!-- Spring Context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies>
</project>
新建一个类(简单的就行)
public class Stu {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Stu{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
使用Spring的第一个步骤
新建一个类,我们暂时名称为Config
//Spring框架的配置类
public class Config {
/**
* @Bean 注解的方法:
* 表示这个方法的返回值会注入到Spring容器中
* 注入的对象,可以在该方法中创建并赋值
* 这个方法的方法名默认情况下是这个对象的ID(名字)
* @return
*/
@Bean
public Stu student(){
Stu stu=new Stu();
stu.setName("曹操");
stu.setAge(60);
return stu;
}
}
第二个步骤
新建一个测试类,从Spring容器中获得这个对象
public class SpringTest {
public static void main(String[] args) {
//想启用Spring还需要依据我们编写的Spring配置类来创建对象
AnnotationConfigApplicationContext ctx=
new AnnotationConfigApplicationContext(Config.class);
//实例化上面对象参数是配置类的反射
//原因是反射中包含这个类中所有内容的信息,方便Spring处理
//将对象从Spring容器中获取
//现在用两个参数,第一个参数是获取对象的id
//第二个参数是获取对象的类型
Stu caocao=ctx.getBean("student",Stu.class);
//输出这个对象
System.out.println(caocao);
ctx.close();
}
}
习题
按照上面的步骤
将你同桌的同学信息注入到Spring容器中
并编写测试类获取输出
Junit 单元测试
什么是Junit
java 单元(unit) 测试
代替我们编写的main方法对我们编写的代码进行测试
为什么需要Junit
我们每测试一个代码都需要编写一个main方法比较麻烦
Junit可以一个类编写多个测试方法
测试类和我们的程序类分离
而且Junit可以有更详细的测试报告
怎么去使用
pom.xml文件中导入依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>
在test文件夹下新建测试类
新建的类中使用@Test表示要测试的方法
//这是一个测试类
//类名是随意的
public class TestCase {
//要想可以测试,编写一个注解
//@Test标注的方法就是一个可以进行测试的方法
@Test
public void test(){
System.out.println("hello");
}
//一个测试类中可以编写多个测试方法
@Test
public void springTest(){
AnnotationConfigApplicationContext ctx=
new AnnotationConfigApplicationContext(Config.class);
Stu caocao=ctx.getBean("student",Stu.class);
System.out.println(caocao);
ctx.close();
}
}
Junit提供了测试之前和测试之后运行代码的注解
能够减少测试前和测试后一定会运行的代码
我们现在的代码中
AnnotationConfigApplicationContext ctx=
new AnnotationConfigApplicationContext(Config.class);
是测试前运行的
ctx.close();
是测试后运行的
可以将他们简化
//这是一个测试类
//类名是随意的
public class TestCase {
AnnotationConfigApplicationContext ctx;
//@Before注解的方法会在具体测试代码运行之前运行
@Before
public void init(){
ctx=new AnnotationConfigApplicationContext(Config.class);
System.out.println("Before");
}
//@After注解的方法会在具体测试代码运行之后运行
@After
public void destroy(){
ctx.close();
System.out.println("After");
}
//要想可以测试,编写一个注解
//@Test标注的方法就是一个可以进行测试的方法
@Test
public void test(){
System.out.println("hello");
}
//一个测试类中可以编写多个测试方法
@Test
public void springTest(){
// AnnotationConfigApplicationContext ctx=
// new AnnotationConfigApplicationContext(Config.class);
Stu caocao=ctx.getBean("student",Stu.class);
System.out.println(caocao);
// ctx.close();
}
}
java程序类规范
java bean实际上时java程序中对类约定的定义规则
是一套规范,有了这套规范,方便使用和交流
- 所有类必须定义在包里
- 除非特殊原因一定要有无参构造
- 要实现序列化接口
- 所有属性需要使用getXxx和SetXxx的规则
JavaBean有哪些规范?
- 实现Serializable接口
- 提供无参构造器
- 为私有属性提供 getter / setter /isXXX 方法
- 可以有少量的业务实现
Spring的组件扫描
使用组件扫描注入对象
我们之前的案例中使用的是@Bean来进行的注入
这种注入是需要编写代码的
如果需要实例化后为属性赋值或者类似操作,我们可以使用@Bean来注入到Spring容器
但是有些类没有需要赋值的属性,那么使用@Bean注入就比较麻烦了
可以使用@Component(英文:“组件”)
来标记在需要注入的类上,这样Spring内部可以自动注入
注入对象的id名是类名首字母小写的状态
例如:DragonBlade —> dragonBlade
但是如果类名是连续两个或以上的大写字母,那么id就是类名
例如:AWPGun —> AWPGun
注意光在类上加注解是不够的
还需要在Config类上加扫描的注解
小结组件扫描注入过程
1.在要注入的类上加注解@Component
2.注意类名生成的ID
3.别忘了在Config类上编写@ComponentScan扫描目标包
Spring提供多种注解注入对象
@Component
@Controller
@Service
等多种注解都可以响应组件扫描将这个类注入到Spring容器
一个功能分这么多注解的原因并不是注解的功能不同
区别仅在于他们单词的意思不同
我们使用的时候根据当前类的角色使用不同单词来注入
自定义组件的id
使用@bean注入时可以使用下面的方法自定义注入Spring容器的id
@Bean("caocao")
使用@Component以及其他可以组件注入的注解时
使用下面方法自定义注入Spring容器的id
@Component("db")
习题:
将之前编写的习题同桌同学的信息对象id自定义为"classmate"
组件扫描:
定义一个Axe(斧子类)
其中有固定的属性值为:private String name=“斧子”;
以及toString方法
使用组件扫描相关知识注入这个对象
并在测试类中获得并输出
可以自定义id:例如:fuzi
Spring容器对Bean的管理策略
为了丰富Spring对注入的对象管理和使用,Spring提供了
一系列管理策略
管理Bean的作用域
什么是作用域
我们将Spring中Bean的作用域分为两种
1.单例(singleton):
当前这个注入的对象在Spring容器中只有1个
无论何时获取,均获得这同一个对象
Spring默认情况下管理Bean就是单例的
2.原型(prototype):
原型模式下,我们使用的注入只是一个模板
每次获得对象时,新实例化对象返回给我们的调用
所以每次获得得对象不是同一对象,互相没有关联
单例的好处:
节省内存,但是不能记录不同的属性或状态
原型的好处:
可以获得不同的对象,保存不同的属性或状态,但是频繁获取会制造过多对象,浪费内存
设置方式:
单例是默认的,无需设置
原型模式
@Bean注入
@Bean("caocao")
@Scope("prototype")//原型
public Stu student(){
Stu stu=new Stu();
stu.setName("曹操");
stu.setAge(60);
return stu;
}
组件扫描
@Component("db")
@Scope("prototype")//原型
public class DragonBlade {
....
}
懒惰初始化
单例下我们在实例化Spring容器时就会自动创建单例的对象
如果程序中不使用这个对象,反而会造成内存的浪费
我们怎么弥补这个缺点呢?(这个情况只针对单例的对象)
使用懒惰初始化
懒惰初始化就是在程序使用到这个对象时在实例化这个对象的策略
一般用于不确定是否使用的对象使用注解
@Lazy
@Bean注入方式
@Bean("caocao")
//@Scope("prototype")
@Lazy//懒惰加载
public Stu student(){
Stu stu=new Stu();
stu.setName("曹操");
stu.setAge(60);
return stu;
}
组件扫描注入方式
@Component("db")
//@Scope("prototype")
@Lazy//懒惰初始化
public class DragonBlade {
...
}
习题:
创建一个新的包 包中新建一个类(Soldier)士兵
类中有属性姓名和血型,编写无参构造,和get\set\toString
创建Config类使用@Bean注入两个士兵 分别是"瑞恩",“A型” “花木兰”,“O型”
1.编写测试类 在测试类中获得瑞恩和花木兰对象 并输出测试 观察测试结果
2.将花木兰设置为懒惰初始化 并输出测试 观察测试结果
3.将瑞恩设置为原型模式 可以尝试获得多个瑞恩对象,并输出测试 观察测试结果
最后使用组件扫描注入两把武器,分别是AK47类和KAR98K,代码参照青龙偃月刀
,自行编写测试
使用@Import导入其它配置文件
在实际开发中
一个项目可以有多个配置类
程序运行时他们都需要加载
最简单的办法就是在ACAC构造方法里使用,分割编写多个配置类的反射
例如
ctx=new AnnotationConfigApplicationContext(
Config.class, Config2.class);
但是上面的代码在新增更多配置类时还是需要维护的
name我们可以在某个配置类中通过添加@Import注解的方式,不修改具体代码来添加配置类
@ComponentScan("cn.tedu.hero")
@Import({Config2.class})//同时加载Config2这个类中的Spring配置
public class Config {
....
}
Spring框架技术概要
我们学习Spring分一下几个模块
1.IOC控制反转
2.DI依赖注入
3.AOP面向切面编程(项目阶段讲)
依赖的概念
依赖就是某个业务(方法)在执行时需要使用到其它物料(对象)
执行这个业务的对象和需要用到的物料就叫做依赖关系
人写字业务依赖笔对象
关羽完成战斗业务需要青龙偃月刀
依赖关系在程序中声明
执行业务的类中声明被依赖对象类型的属性
上面的文字转换成代码如下
public class Hero implements Serializable {
private String name;
private int power;
//在Hero类中声明了一个DragonBlade类型的属性
//表示Hero类依赖DragonBlade
private DragonBlade dragonBlade;
public void fight(){
// 战斗业务......
}
}
在测试类中,将执行业务的对象和被依赖对象建立依赖关系
将青龙偃月刀赋值到关羽的青龙偃月刀属性中
代码如下
@Test
public void fightTest(){
Hero h=ctx.getBean("guanYu",Hero.class);
DragonBlade db=ctx.getBean("blade",DragonBlade.class);
h.setDragonBlade(db);
h.fight();
}
输出结果
关羽使用青龙偃月刀战斗
习题:
新建一个包
创建一个Person(人)类
人类有String name属性
还有Pen pen(钢笔)属性 这个Pen类是自己创建的,name就是钢笔,toString方法返回"钢笔"
还有一个写字方法write()
这个写字方法输出"<谁>使用<什么笔>写字"
最后新建一个测试类
在测试类中从Spring容器中获得人和笔,将笔对象赋值为人的笔类型的属性之后调用write方法
可以下载了