Spring
第1章 Spring 概述
1.1 Spring 框架是什么
- spring全家桶:spring, springmvc, spring boot,spring cloud
- spring:用来减小企业级开发的难度。方便项目模块之间的管理、类与类之间的管理,帮助开发人员创建对象,管理对象之间的关系。通过配置来实现。
- spring核心是IOC(控制反转) AOP(面向切面编程)。模块之间 、类之间 的解耦合。关系松散一些。
- 注意点:maven是管理资源jar包。spring是管理项目内部模块和类之间的依赖。
- IoC 使得主业务在相互调用过程中,不用再自己维护关系了,即不用再自己创建要使用的对象了。而是由 Spring容器统一管理,自动“注入”,注入即赋值。
- AOP 使得系统级服务(事务、权限、日志)得到了最大复用,且不用再由程序员手工将系统级服务“混杂”到主业务逻辑中了,而是由 Spring 容器统一完成“织入”。
1.2 Spring优点?
Spring 是一个框架,是一个半成品的软件。有 20 个模块组成。它是一个容器管理对象,容器是装东西的,Spring 容器不装文本,数字。装的是对象。Spring 是存储对象的容器。
- 轻量:Spring 核心功能的所需的 jar 总共在 3M 左右。Spring 框架运行占用的资源少,运行效率高。不依赖其它jar包。
- 针对接口编程,解耦合:Spring 提供了 Ioc 控制反转,由容器管理 对象、对象的依赖关系。原来在程序代码中的对象创建方式,现在由容器完成。对象之间的依赖解耦合。
- AOP编程支持:开发人员可以从繁杂的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。
- 集成各种优秀框架:Spring 像插线板一样,其他框架是插头。加入方便,移除也方便(Struts,Hibernate、MyBatis
1.3 Spring的体系结构
Spring 由 20 多个模块组成,它们可以分为数据访问/集成(Data Access/Integration)、Web、面向切面编程(AOP, Aspects)、提供JVM的代理(Instrumentation)、消息发送(Messaging)、核心容器(Core Container)和测试(Test)。
第二章 IOC控制反转
- 控制:创建对象 、对象属性赋值 、对象之间的关系管理
- 反转:把原来开发人员的管理、创建对象的权限转移到代码之外的容器实现。
- 容器:一个服务器软件。 一个框架。
- 正转:由开发人员在代码中,使用new构造方法创建对象 开发人员主动管理对象
- 依赖:classA 类中含有 classB 的实例,在 classA 中调用 classB 的方法完成功能,即 classA对 classB 有依赖。
- 注入:注入就是设值。
- 依赖注入 DI: 是指程序运行过程中,若需要调用另一个对象协助时,无须在代码中创建被调用者,而是依赖于外部容器,由外部容器创建后传递给程序。依赖注入对调用者与被调用者几乎没有任何要求,完全支持对象之间依赖关系的管理。
- spring使用依赖注入DI实现了IOC
- Spring 容器是一个超级大工厂,负责创建、管理所有的 Java 对象,这些 Java 对象被称为 Bean。Spring 容器管理着容器中 Bean 之间的依赖关系,Spring 使用“依赖注入”的方式来管理 Bean 之间的依赖关系。使用 IoC 实现对象之间的解耦和。
java中创建对象的方式有哪些?
1.构造方法:new Student()
2.反射(spring底层创建对象的原理)
3.序列化:对象保存在磁盘中 序列化读取
4.克隆
5.IOC:容器创建对象
6.动态代理jdk
ioc的体现(servlet):
1: 创建MyServlet1类 extend HttpServelt
2: 在web.xml 注册servlet,
使用<servlet-name> myservlet </servlet-name>
<servelt-class>com.bjpwernode.controller.MyServlet1</servlet-class>
3. 没有创建 Servlet对象, 没有 MyServlet myservlet = new MyServlet()
4. Servlet 是Tomcat服务器它为你创建的。 Tomcat也称为容器。
Tomcat作为容器:里面存放的有Servlet对象, Listener , Filter对象
2.1 开发工具准备
- 开发工具:idea2017 以上
- 依赖管理:maven3 以上
- jdk:1.8 以上
- maven本地仓库:
2.2 Spring第一个程序
项目名:01–primary
目录:D:\IDEA\JavaProjects\01–primary
IDEA创建流程:
2.2.1.新建一个空maven -> 选择
2.2.2.引入maven的pom.xml
<!--spring的依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!--插件-->
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
2.2.3.定义接口和实现类
//接口
public interface SomeService {
void doSome();
}
//实现类
public class SomeServiceImpl implements SomeService {
public SomeServiceImpl() {
super();
System.out.println("SomeServiceImpl无参数构造方法");
}
@Override
public void doSome() {
System.out.println("====业务方法doSome()===");
}
}
2.2.4.创建spring配置文件
在 src/main/resources/目录现创建一个 xml 文件,文件名可以随意,但 Spring 建议的名称为applicationContext.xml。spring 配置中需要加入约束文件才能正常使用,约束文件是 xsd 扩展名。xsd在写入配置文件时可以自动生成。
<!--
spring配置文件
1.<bean/>:用于定义一个实例对象。一个实例对应一个bean元素。
id:Bean实例的唯一标识,程序通过id属性访问Bean,Bean与Bean间的依赖关系也是通过id属性关联的
class:指定Bean所属类,只能是类 不能是接口(因为spring是反射机制)
spring是把创建好的对象放入map中,springMap.put(id的值,对象);
2.spring-beans.xsd 是约束文件,和mybatis指定 dtd是一样的
-->
<!--自定义的SomeServiceImpl类-->
<bean id="someService" class="com.bjpowernode.service.impl.SomeServiceImpl"></bean>
<!--这是一个非自定义的类对象-->
<bean id="myDate" class="java.util.Date"></bean>
2.2.5. 定义测试类
public class MyTest {
@Test
//旧版本使用new实例化创建对象 来使用
public void test01(){
SomeService service = new SomeServiceImpl();
service.doSome();
//无参构造函数是会执行的。且执行在setter getter 之前。
}
<!--
输出结果:
SomeServiceImpl无参数构造方法
---------业务方法dosome()-----
-->
@Test
public void test02(){
//指定spring配置文件的位置和名称
String resource = "applicationContext.xml";
//创建spring容器对象 ApplicationContext
//ClassPathXmlApplicationContext表示从类路径中加载spring的配置文件 是从target/classes加载的
ApplicationContext ac = new ClassPathXmlApplicationContext(resource);
//从spring容器中获取对象,使用id
SomeService service = (SomeService) ac.getBean("someService");//按id值获取
//执行对象的业务方法
service.doSome();
}
<!--
输出结果:
SomeServiceImpl无参数构造方法
---------业务方法dosome()-----
-->
@Test
public void test03(){
String resource = "applicationContext.xml";
//使用spring提供的对象,获取容器中定义的对象的数量
ApplicationContext ac = new ClassPathXmlApplicationContext(resource);
int nums = ac.getBeanDefinitionCount();
System.out.println("容器中定义的对象数量:"+nums);
//容器中每个定义对象的名称
String[] names = ac.getBeanDefinitionNames();
for(String name:names){
System.out.println("容器名称:"+name);
}
}
<!--
输出结果:
SomeServiceImpl无参数构造方法
容器中定义的对象数量:2
容器名称:someService
容器名称:myDate
-->
@Test
public void test04(){
String resource = "applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(resource);
Date my =(Date) ac.getBean("myDate");//获取到了日期的类对象
System.out.println("Date:"+my);
}//非自定义类也可以-->jar包的,别人写好的。下载在本地的,maven中导入的。
}
<!--
输出结果:
SomeServiceImpl无参数构造方法
Date:Sun Nov 07 12:13:08 CST 2021
-->
* spring默认创建对象的时间:在创建spring的容器时,会创建配置文件中的所有的对象。
* spring创建对象:默认调用的是无参数构造方法。
2.2.6 使用spring创建非自定义类对象
2.2.7 容器的接口和实现类(重要理解!!)
String resource = "applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(resource);
SomeService service = (SomeService)ac.getBean("someService");
service.doSome();
2.3 基于xml的DI
2.3.1 注入分类
bean 实例在调用无参构造器创建对象后,就要对 bean 对象的属性进行初始化。初始化
是由容器自动完成的,称为注入。根据注入方式的不同,常用的有两类:set 注入、构造注入
实际项目中set注入占80%。
2.3.1.1 set注入
set 注入也叫设值注入是指,通过 setter 方法传入被调用者的实例。这种注入方式简单、
直观,因而在 Spring 的依赖注入中大量使用。
- spring会执行实体类中的 无参构造方法。并且无参构造方法先于set方法执行。
A.简单类型
1》创建实体类
public class Student {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setEmail(String email) {
//方法的参数是不能少的
System.out.println("我没有写email属性 但是有set方法 我也可以正常执行。");
//因为bean的set注入时 找的是setter方法,不是实体类属性。
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
2》配置applicationContext.xml
<!--
声明student对象
di:给属性赋值 注入:就是赋值的意思
简单类型:java的 基本数据类型、字符串, 都是 简单类型。
1.set注入(设值注入):spring调用类的set方法,可以在set方法中完成属性赋值
(1.)简单类型的set注入
<bean id="xx" class="yyy">
<property name="属性名字" value="此属性的值"/>
一个property只能给一个属性赋值
</bean>
2.构造注入(后面介绍)
-->
<bean id="myStudent" class="com.bjpowernode.ba01.Student">
<property name="name" value="李四"></property>
<property name="age" value="13"></property>
<property name="email" value="123456@qq.com"></property>
</bean>
3》测试类
public class MyTest{
@Test
public void test01(){
String config = "ba01/applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(config);
//从容器中获取Student
Student myStudent = (Student)ac.getBean("myStudent");
System.out.println("Student对象="+myStudent);
<!--
输出结果:
我没有写email属性 但是有set方法 我也可以正常执行。(setEmail方法会被配置文件执行)
Student对象=Student{
name='李四', age=13}(实体类返回的toString方法)
-->
}
}
注意:这个地方意外发现了一个大坑。默认spring的配置文件是在红色的target/classes/resources/找的。但是没有自动生成。
解决方法:点击 File -> Project Structure,选择Modules -> Paths -> Output Paths
修改为 applicationContext.xml 文件所在目录。
B 引用类型
当指定 bean 的某属性值为另一 bean 的实例时,通过 ref 指定它们间的引用关系。ref的值必须为某 bean 的 id 值。
//学生实体类
public class Student {
private String name;
private int age;
//声明一个引用类型
private School school;
//name、age、school的setter方法 代码中有,此处省略。
@Override
public String toString() {
return "Stud