Spring概述
Spring全家桶:spring、springmvc、spring boot、spring cloud
spring:出现是在2002左右,解决企业开发的难度。减轻对项目模块之间的管理。
类和类之间的管理,帮助开发人员创建对象,管理对象之间的关系。
spring核心技术:ioc、aop。能实现模块之间,类之间的解耦合。
依赖:classa中使用了classb的属性或者方法,叫做classa依赖classb
spring官网:spring.io
spring优点
轻量
Spring框架使用的jar都比较小,一般在1M以下或者几百kb。Spring核心功能的所需的jar总共在3M左右。
Spring框架运行占用的资源少,运行效率高。不依赖其他jar
针对接口编程,解耦合
Spring提供了loc控制反转,由容器管理对象,对象的依赖关系。原来在程序代码中的对象创建方式,现在由容器完成。对象之间的依赖解耦合。
AOP编程的支持
通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过AOP轻松应付
在Spring中,开发人员可以从繁杂的事务管理代码中解脱出来,通过声明方式灵活地进行事务的管理,提高开发效率和质量。
方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,相反Spring可以降低各种框架的使用难度,Spring提供了对各种优秀框架(如Struts、Hibernate、MyBatis)等的直接支持。简化框架的使用。Spring像插线板一样,其他框架是插头,可以容易的组合到一起。需要使用哪个框架,就把这个插头放入插线板,不需要可以轻易的移除。
Spring体系结构
框架怎么学:框架是一个软件,是其他人写好的软件。
1)知道框架能做什么,mybatis–访问数据库,对表中的数据执行增删改查。
2)框架的语法,框架要完成一个功能,需要一定的步骤支持的。
3)框架的内部实现,框架的内部怎么做,原理是什么。
4)通过学习,实现一个属于自己的框架。
Spring的核心功能 ioc
ioc(Inversion of Control):控制反转,是一个理论,概念,思想。
描述的是:把对象的创建,赋值,管理工作都交给代码之外的容器实现,也就是对象的创建是由其他的外部资源完成。
控制:创建对象,对象的属性赋值,对象之间的关系管理。
反转:把原来的开发人员管理,创建对象的权限转移给代码之外的容器实现,由容器代替开发人员管理对象,创建 对象,给属性赋值。
正转:由开发人员在代码中,使用new构造方法创建对象,开发人员主动管理对象。
public static void main(String args[]){
Student student=new Student(); //在代码中,创建对象。 -- 正转
}
容器:是要给服务器软件,一个框架(spring)
为什么要使用ioc:目的就是减少对代码的改动,也能实现不同的功能。实现解耦合。
Java中创建对象由哪些方式:
1、构造方法,new Student()
2、反射
3、序列化
4、克隆
5、ioc:容器创建对象
6、动态代理
ioc的体现:
servlet 1:创建类继承HTTP Servlet
2:在web.xml 注册servlet,使用的是:
<servlet-name>myservlet</servlet-name>
<servlet-class>com.hr.MyServlet</servlet-class>
3:没有创建Servlet对象,没有 MyServlet myservlet = new MyServlet();
4:Servlet 是Tomcat服务器它给你创建的。Tomcat也称为容器
Tomcat作为容器:里面存放的有Servlet对象, Listener , Filter对象
IoC的技术实现,
DI 是ioc的技术实现
DI(Dependency Injection):依赖注入,只需要在从程序中提供要使用的对象的名称就可以了,至于对象如 何在容器中创建,赋值,查找都由容器内部实现。
Spring是使用的di实现了ioc的功能,spring底层创建对象,使用的是反射机制。
spring是一个容器,管理对象,给属性赋值,底层是反射创建对象。
Spring第一个例子
使用的ioc,由spring创建对象
实现步骤:
1、创建maven项目
2、加入maven的依赖
spring的依赖,版本5.2.5版本
junit依赖
3、创建类(接口和他的实现类)
和没有使用框架一样,就是普通的类
4、创建spring需要使用的配置文件
声明类的信息,这些类由spring创建和管理
5、测试spring创建的。
@Test
public void test02(){
//使用spring容器创建的对象
//1.指定spring配置文件的名称
String config="beans.xml";
//2.创建表示spring容器的对象,ApplicationContext
//ApplicationContext就是表示spring容器,通过容器获取对象使用对象了
//ClassPathXmlApplicationContext:表示从类路径中加载spring的配置文件
ApplicationContext ac=new ClassPathXmlApplicationContext(config);
//从容器中获取某个对象,你要调用对象的方法
//getBean("配置文件中的bean的id值")
SomeService someService = (SomeService) ac.getBean("someService");
//使用spring创建好的对象,调用方法
someService.doSome();
}
spring 默认创建对象的时间:在创建spring的容器时,会创建配置文件中的所有对象
spring创建对象:默认调用的是无参数构造方法
通过方法获取spring容器中Java对象的信息
@Test
public void test03(){
String config="beans.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(config);
//使用spring 提供的方法,获取容器中定义的对象的数量
int nums=ac.getBeanDefinitionCount();
System.out.println("容器中定义的对象的数量"+nums);
//使用spring提供的方法,获取容器中对象的名称,返回会是一个数组
String[] names = ac.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
}
创建非自定义的类对象
首先要在beans.xml中<beans>
标签中配置
<bean id="mydate" class="java.util.Date" />
跟自定义对象不同的是,路径要写为已经写好的路径
测试非自定义类对象
@Test
public void test04(){
String config="beans.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(config);
//使用getBean()
Date mydate = (Date) ac.getBean("mydate");
System.out.println(mydate.getTime());
}
基于XML的DI
注入:就是赋值的意思
简单类型:spring中规定Java的基本数据类型和spring都是简单类型
di:给属性赋值
1、set注入(设值注入):spring调用类的set方法,你可以在set方法中来完成属性赋值
1)简单类型的set注入
<bean id="xx" class="yyy">
<property name="属性名字" value="此属性的值" />
一个property只能给一个属性赋值
<property ... >
</bean>
2、引用类型的set注入:spring调用类的set方法
<bean id="xxx" class="yyy">
<property name="属性名称" ref="bean的id(对象的名称)">
</bean>
简单类型设值注入
实例:
<!--给student实体类赋值-->
<bean id="myStudent" class="com.hr.qjw.ba01.Student" >
<property name="name" value="李四" />
<property name="age" value="21" />
</bean>
通过实体类student类中的set设置注入,通过set类中的set方法,将值赋给变量
需要实体类中必须有set方法,否则会报错
设置注入只是去调用了对应的set方法,有没有对应的属性不会报错
引用类型设值注入
实例
<bean id="myStudent" class="com.hr.qjw.ba02.Student" >
<property name="name" value="李四" /> <!--setName("李四")-->
<property name="age" value="21" /> <!-- setAge(21)-->
<!-- 引用类型-->
<property name="School" ref="mySchool" />
</bean>
<!-- 声明School对象-->
<bean id="mySchool" class="com.hr.qjw.ba02.School">
<property name="name" value="河北软件职业"/>
<property name="address" value="保定"/>
</bean>
构造注入
构造注入:spring调用类有参数构造方法,在创建对象的同时,在构造方法中给属性赋值。
构造注入使用<constructor-arg>
标签
<constructor-arg>
标签:一个<constructor-arg>
表示构造方法一个参数。
<constructor-arg
>标签属性:
name:表示构造方法的形参名
index:表示构造方法的参数的位置,参数从左往右是 0,1,2的顺序
value:构造方法的形参类型是简单类型的,使用value
ref:构造方法是引用类型的,使用ref
三种构造注入方法的实例
<!-- 声明School对象-->
<bean id="myXueXiao" class="com.hr.qjw.ba03.School">
<property name="name" value="清华大学"/>
<property name="address" value="北京"/>
</bean>
<!-- 使用name属性实现构造注入-->
<bean id="myStudent" class="com.hr.qjw.ba03.Student" >
<constructor-arg name="myname" value="ccl" />
<constructor-arg name="myage" value="20" />
<constructor-arg name="myschool" ref="myXueXiao" />
</bean>
<!-- 使用index属性-->
<bean id="myStudent2" class="com.hr.qjw.ba03.Student" >
<constructor-arg index="0" value="hxy"/>
<constructor-arg index="1" value="19"/>
<constructor-arg index="2" ref="myXueXiao"/>
</bean>
<!-- 使用index省略-->
<bean id="myStudent3" class="com.hr.qjw.ba03.Student" >
<constructor-arg value="hxy"/>
<constructor-arg value="19"/>
<constructor-arg ref="myXueXiao"/>
</bean>
前面两种的方法,bean标签里面的顺序不规定,但是第三种index省略必须要保持顺序符合index 0,1,2的顺序才可以
创建文件对象
<!-- 创建File,使用构造注入-->
<bean id="myfile" class="java.io.File">
<constructor-arg name="parent" value="D:\Project\spring-course\ch02-di-xml"/>
<constructor-arg name="child" value="readme.txt"/>
</bean>
引用类型自动注入
使用的规则常用的是byName,byType
byName
1、byName(按名称注入):Java类中引用类型的属性名和spring容器中(配置文件)<bean>
的id名称一样,
且数据类型是一致的,这样的容器中的bean,spring能够赋值给引用类型。
语法规则:
<bean id="xx" class="yyy" autowire="byName">
简单类型属性赋值
</bean>
实例:
<!-- byName-->
<bean id="myStudent" class="com.hr.qjw.ba04.Student" autowire="byName">
<property name="name" value="李四" /> <!--setName("李四")-->
<property name="age" value="21" /> <!-- setAge(21)-->
<!-- 引用类型-->
<!-- <property name="School" ref="mySchool" />-->
</bean>
<!-- 声明School对象-->
<bean id="school" class="com.hr.qjw.ba04.School">
<property name="name" value="清华大学"/>
<property name="address" value="北京"/>
</bean>
声明的对象id要与数据类型的变量名相同
byType
2、byType(类型注入):Java类中引用类型的数据类型和spring容器中(配置文件)<bean>
的class属性
是同源关系的,这样的bean能够赋值给引用类型
同源就是一类的意思:
1、Java类中引用类型的数据类型和bean的class的值是一样的。
2、Java类中引用类型的数据类型和bean的class的值是父子类关系的。
3、Java类中引用类型的数据类型和bean的class的值接口和实现类关系的。
语法规则:
<bean id="xx" class="yyy" autowire="byType">
简单类型属性赋值
</bean>
注意:在byType中,在xml配置文件中声明bean只能有一个符合条件的
多余一个是错误的
实例:
1、Java类中引用类型的数据类型和bean的class的值是一样的。
<bean id="myStudent" class="com.hr.qjw.ba05.Student" autowire="byType">
<property name="name" value="李四" /> <!--setName("李四")-->
<property name="age" value="21" /> <!-- setAge(21)-->
</bean>
<!-- 声明School对象-->
<bean id="mySchool" class="com.hr.qjw.ba05.School">
<property name="name" value="人民大学"/>
<property name="address" value="北京"/>
</bean>
2、Java类中引用类型的数据类型和bean的class的值是父子类关系的。
<bean id="myStudent" class="com.hr.qjw.ba05.Student" autowire="byType">
<property name="name" value="李四" /> <!--setName("李四")-->
<property name="age" value="21" /> <!-- setAge(21)-->
</bean>
<!--声明School子类-->
<bean id="primarySchool" class="com.hr.qjw.ba05.primarySchool">
<property name="name" value="河北软件"/>
<property name="address" value="保定"/>
</bean>
primarySchool是School的子类,所以也可以通过自动引用注入
基于注解的DI
通过注解完成Java对象创建,属性赋值。
使用注解的步骤:
1、加入maven的依赖 spring-context,在你加入spring-context的同时, 间接加入spring-aop的依赖。
使用注解必须使用spring-aop依赖
2、在类中加入spring的注解(多个不同功能的注解)
3、在spring的配置文件中,加入一个组件扫描器的标签,说明注解在你的项目中的位置
学习的注解:
1、@Component
2、@Respotory
3、@Service
4、@Controller
5、@Value
6、@Autowired
7、@Resource
@Component:创建对象的,等同于<bean>
的功能
属性:value 就是对象的名称,也就是bean的id值,
value的值是唯一的。创建的对象在整个spring的容器中就一个
位置:在类的上面
@Component(value = “myStudent”)等同于
<bean id="myStudent" class="com.hr.qjb.ba01.Student" />
spring中和@Component功能一致,创建对象的注解还有:
1、@Repository(用来持久层类的上面):放在dao的实现类上面,
表示创建dao对象,dao对象是能访问数据库的。
2、@Service(用在业务层类的上面):放在Service的实现类上面,
创建service对象,service对象是做业务处理,可以有事务等供你的。
3、@Controller(用在控制器的上面):放在控制器(处理器)类的上面,创建控制器对象的,
控制器对象,能够接受用户提交的参数,显示请求的处理结果
以上三个注解的使用语法和@Component一样的。都能创建对象,但是这三个注解还有额外的功能
@Repository、@Service、@Controller是给项目的对象分层的。
@Component 会用到的地方:以上三个类上面都不是的地方,而且需要创建对象的地方使用
@Component用法
使用value属性,指定对象名称
@Component(value = “myStudent”)
省略value
@Component(“myStudent”)
不指定对象名称,由spring提供默认名称:类名的首字母小写
@Component
声明组件扫描器(component-scan),组件就是Java对象
base-package:指定注解在你的项目中的包名
component-scan工作方式:spring会扫描遍历base-package指定的包
把包中和子包中的所有类,找到类中的注解,按照注解的功能创建对象,或给属性赋值。
加入了component-scan标签,配置文件的变化:
1、加入一个新的约束文件spring-context.xsd
2、给这个新的约束文件起个命名空间的名称
<context:component-scan base-package="com.hr.qjb.ba01"/>
指定多个包的三种方式
<!-- 第一种方式:使用多次组件扫描器,制定不同的包-->
<context:component-scan base-package="com.hr.qjb.ba01"/>
<context:component-scan base-package="com.hr.qjb.ba02"/>
<!-- 第二种方式:使用分隔符(;或,)分割多个包名-->
<context:component-scan base-package="com.hr.qjb.ba01;com.hr.qjb.ba02"/>
<!-- 第三种方式:指定父包-->
<context:component-scan base-package="com.hr.qjb"/>
简单类型赋值
@Value:简单类型的属性赋值
属性:value 是String类型的,表示简单类型的属性值
位置:1、在属性定义的上面,无需set方法,推荐使用
2、在set方法的上面
//用在属性上
@Value(value = "小龙女")
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
//用在set上
@Value("2323")
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
引用类型赋值
@Autowired:spring框架提供的注解,实现应用类型的赋值。
spring中通过注解给引用类型赋值,使用的是自动注入原理,支持byName,byType
@Autowired:默认使用的是byType自动注入
位置:1、在属性定义的上面,无需set方法,推荐使用
2、在set方法的上面
引用类型byType注入
@Component("mySchool")
public class School {
@Value("河北软件")
private String name;
@Value("保定")
private String address;
public void setName(String name) {
this.name = name;
}
public void setAddress(String address) {
this.address = address;
}
@Override
public String toString() {
return "School{" +
"name='" + name + '\'' +
", address='" + address + '\'' +
'}';
}
首先要用@Component给这个类型创建对象
@Autowired
private School school;
之后在定义的属性上面加上注解@Autowired 因为默认是byType类型注入,则会去找与之类型相同的类注入
引用类型byName注入
如果要使用byName方式,需要做的是:
1、在属性上面加入@Autowired
2、在属性上面加入@Qualifier(value=“bean的id”):表示使用指定名称的bean完成赋值。
@Autowired
@Qualifier("mySchool")
private School school;
@Autowired意思为要自动找,@Qualifier是按byName去查找类
@Autowired的属性:
属性:required ,是要给boolean类型的默认true
required=true :表示引用类型赋值失败,程序报错,并终止执行。
required=false :引用类型如果赋值失败,程序正常执行,引用类型是null
推荐为true,因为如果找不到的时候会报错,这样可以及时调试,不让漏洞太大
@Resource
@Resource:来自jdk中的注解,spring框架提供了对这个注解的功能支持,可以使用它给引用类型赋值
使用的也是自动注入原理,支持byName,byType,默认是byName
位置:1、在属性定义的上面,无需set方法,推荐使用
2、在set方法的上面
@Resource
private School school;
如果byName找不到,则会使用byType去找
@Resource只是用byName方式,需要增加一个属性name
name的值是bean的id(名称)
@Resource(name = "mySchool")
private School school;
xml配置文件和注解的对比
如果经常改则尽量使用xml配置文件,因为只需要去改一下配置文件,而不需要去改代码
如果不会经常去改则可以使用注解
junit
junit:单元测试,一个工具类库,做测试方法使用的。
单元:指定的是方法,一个类中有很多方法,一个方法称为单元。
使用单元测试:
1、需要加入junit依赖
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
2、创建测试用作用的类:叫做测试类
src/test/java目录中创建类
3、创建测试方法
1)public方法
2)没有返回值 void
3)方法名称自定义,建议名称是test+你要测试方法名称
4)方法没有参数
5)方法的上面加入@Test,这样的方法是可以单独执行的,不用使用main方法
多个配置优势
1、每个文件的大小比一个文件要小很多,效率高
2、避免多人竞争带来的冲突。
如果你的项目有多个模块(相关的功能在一起),一个模块一个配置文件。
学生考勤模块一个配置文件 ,张三
学生成绩一个配置文件, 李四
多文件的分配方式:
1、按功能模块,一个模块一个配置文件
2、按类的功能,数据库相关的配置一个文件配置文件,做事务的功能一个配置文件,做service功能的一个配置文件等
包含关系的配置文件:
spring-total表示主配置文件:包含其他的配置文件的。主配置文件一般是不定义对象的
语法:<import resource="其他配置文件的路径" />
关键字:“classpath:” 表示类路径(class文件所在的目录),在spring的配置文件中要指定其他文件的位置
需要使用classpath,告诉spring到哪去加载读取文件
实例:
<!-- 加载的是文件列表-->
<import resource="classpath:ba06/spring-school.xml"/>
<import resource="classpath:ba06/spring-student.xml" />
<!-- 在包含关系的配置文件中,可以使用通配符(*:表示任意字符)
注意:主的配置文件名称不能包含在通配符的范围内(不能叫spring-total.xml)
-->
<import resource="classpath:ba06/spring-*.xml" />
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L72JBT49-1629774381245)(image\多个配置文件.png)]
多个配置文件的时候,可以设置一个主配置文件,去定义其他配置文件都属于哪个模块
学生成绩一个配置文件, 李四
多文件的分配方式:
1、按功能模块,一个模块一个配置文件
2、按类的功能,数据库相关的配置一个文件配置文件,做事务的功能一个配置文件,做service功能的一个配置文件等
包含关系的配置文件:
spring-total表示主配置文件:包含其他的配置文件的。主配置文件一般是不定义对象的
语法:<import resource="其他配置文件的路径" />
关键字:“classpath:” 表示类路径(class文件所在的目录),在spring的配置文件中要指定其他文件的位置
需要使用classpath,告诉spring到哪去加载读取文件
实例:
<!-- 加载的是文件列表-->
<import resource="classpath:ba06/spring-school.xml"/>
<import resource="classpath:ba06/spring-student.xml" />
<!-- 在包含关系的配置文件中,可以使用通配符(*:表示任意字符)
注意:主的配置文件名称不能包含在通配符的范围内(不能叫spring-total.xml)
-->
<import resource="classpath:ba06/spring-*.xml" />
多个配置文件的时候,可以设置一个主配置文件,去定义其他配置文件都属于哪个模块