一、Spring概述
1.1 web项目开发中的耦合问题
在web项目中,servlet调用service,service调用DAO,都需要通过new关键字创建实现类对象,弊端如下:
- 失去了面向对象接口变成的灵活性
- 代码的侵入性增强(增加了耦合度),降低了代码的灵活性
解决方案:在servlet中定义Service接口的对象变量,不使用new关键字创建实现类对象,在servlet实例化的时候,通过反射动态的给Service对象变量赋值。
1.2 Spring介绍
Spring是一个
轻量级的控制反转和面向切面的容器
框架,用来解决企业项目开发的复杂度问题-解耦
- 轻量级:体积小,对代码没有侵入性
- 控制反转:IoC(Inverse of Control)把创建对象的工作交由Spring操作,Spring在创建对象的同时可以完成对象属性赋值(DI)
- 面向切面:AOP(Asperct Oriented Programming)面向切面编程,可以在不改变原有业务逻辑的情况下实现对业务的增强。
- 容器:实例的容器,管理创建的对象
1.3 Spring架构
-
Spring架构图
1.3.1 Core Container
Spring容器组件,用于完成实力的创建和管理
Core:核心
Beans : 实例管理
Context:容器上下文
SpEL:表达式
1.3.2 AOP、Aspects
Spring AOP组件,实现面向切面编程
- AOP:面向切面实现
- Aspects:面向切面机制
1.3.3 web
Spring web组件实际指的是SpringMVC框架,实现web项目的MVC控制
- web:Spring对web项目的支持
- webmvc(SpringMVC)
1.3.4 Data Access
Spring数据访问组件,也是一个基于JDBC封装的持久层框架,即使没有mybatis,spring也可以完成持久化操作
- tx
1.3.5 Test
Spring单元测试组件,提供了Spring环境下的单元测试支持
- test
二、Spring IoC
2.1 Spring框架部署(IoC)
Spring IoC容器组件,可以完成对象的创建、对象属性赋值、对象管理
2.1.1 创建Maven
- java工程
- web工程
2.1.2 添加SpringIoC依赖
- core
- beans
context
:此依赖中包含core和beans包,所以只引入一个依赖即可
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.25.RELEASE</version>
</dependency>
2.1.3 创建Spring配置文件
通过配置文件,控制容器创建对象,对属性赋值
- 在resource目录下创建名为applictionContext.xml的文件(文件名可以自定义)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 对于一个xml文件如果作为框架的配置文件,需要遵守框架的配置规则 -->
<!-- 通常一个框架为了让开发者能够正确的配置,都会提供xml规范文件 (dtd\xsd)-->
</beans>
2.2 Spring IoC的使用
使用SpringIoC组件创建并管理对象
2.2.1 创建实体类
package com.feng.ioc.bean;
import java.util.Date;
/**
* @program: spring-ioc-demo1
* @description: 学生实体类
* @author: FF
* @create: 2024-12-04 18:53
**/
public class Student {
private String stuNum;
private String stuName;
private int stuAge;
private Date enterenceTime;//学生的入学日期
public String getStuNum() {
return stuNum;
}
public String getStuName() {
return stuName;
}
public int getStuAge() {
return stuAge;
}
public Date getEnterenceTime() {
return enterenceTime;
}
public void setStuNum(String stuNum) {
this.stuNum = stuNum;
}
public void setStuName(String stuName) {
this.stuName = stuName;
}
public void setStuAge(int stuAge) {
this.stuAge = stuAge;
}
public void setEnterenceTime(Date enterenceTime) {
this.enterenceTime = enterenceTime;
}
@Override
public String toString() {
return "Student{" +
"stuNum='" + stuNum + '\'' +
", stuName='" + stuName + '\'' +
", stuAge=" + stuAge +
", enterenceTime='" + enterenceTime + '\'' +
'}';
}
}
2.2.2 在Spring配置文件中配置实体类
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 对于一个xml文件如果作为框架的配置文件,需要遵守框架的配置规则 -->
<!-- 通常一个框架为了让开发者能够正确的配置,都会提供xml规范文件 (dtd\xsd)-->
<!--通过bean标签将实体类配置给Spring进行管理.id表示实体类的唯一标识-->
<bean id="student" class="com.feng.ioc.bean.Student">
<property name="stuNum" value="2"/>
<property name="stuName" value="小帅"/>
<property name="stuAge" value="20"/>
</bean>
</beans>
2.2.3 初始化Spring对象工厂,获取对象
-
ClassPathXmlApplicationContext
package com.feng.ioc.test;
import com.feng.ioc.bean.Student;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @program: spring-ioc-demo1
* @description: 测试类
* @author: FF
* @create: 2024-12-04 19:03
**/
public class Test2 {
public static void main(String[] args) {
// 通过Spring容器创建Student对象
//1.初始化Spring容器
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//2.通过Spring容器,获取Student对象
Student student = (Student) classPathXmlApplicationContext.getBean("student");
System.out.println(student);
}
}
2.3 IoC和DI
- IoC控制反转,通过Spring工厂完成对象的创建
- DI 依赖注入,在Spring完成对象创建的同时,依赖Spring容器完成对象属性的赋值
2.3.1 IoC
当我们需要Spring对象工厂创建某个类的实例时,需要将这个类交给Spring管理–通过bean标签配置
<bean id="date" class="java.util.Date"/>
<bean id="student" class="com.feng.ioc.bean.Student">
</bean>
2.3.2 DI
通过Spring容器给创建的对象属性赋值
<bean id="date" class="java.util.Date"/>
<bean id="student" class="com.feng.ioc.bean.Student">
<property name="stuNum" value="2"/>
<property name="stuName" value="小帅"/>
<property name="stuAge" value="20"/>
<property name="enterenceTime" ref="date"/>
</bean>
2.4 DI依赖注入
2.4.1 依赖注入的三种方式
Spring容器加载配置文件后,通过反射创建类的对象,并给属性赋值。
Spring容器通过反射实现属性注入有两种方式:
- set方法注入
- 构造器注入
- 接口注入
2.4.2 set方法注入
bean标签中的通过配置标签给属性赋值,也就是通过反射的set方法注入
简单类型及字符串类型
直接通过property标签的value属性赋值
<bean id="student" class="com.feng.ioc.bean.Student">
<property name="stuNum" value="2"/>
<property name="stuName" value="小帅"/>
<property name="stuAge" value="20"/>
<property name="weight" value="20"/>
</bean>
日期对象
- 方式一:在property标签中通过ref引用Spring容器中的一个对象
<bean id="date" class="java.util.Date"/>
<bean id="student" class="com.feng.ioc.bean.Student">
<!--日期类型赋值-->
<property name="enterenceTime" ref="date"/>
</bean>
- 方式二:在property标签中添加子标签bean来指定对象
<bean id="student" class="com.feng.ioc.bean.Student">
<!--日期类型赋值-->
<!--<property name="enterenceTime" ref="date"/>-->
<property name="enterenceTime">
<bean class="java.util.Date"/>
</property>
</bean>
自定义对象类型
- 方式一:在property标签中通过ref引用Spring容器中的一个对象
<bean id="clazz" class="com.feng.ioc.bean.Clazz">
<property name="cid" value="1"/>
<property name="cname" value="计算机应用01班"/>
</bean>
<bean id="student" class="com.feng.ioc.bean.Student">
<property name="clazz" ref="clazz"/>
</bean>
方式二:在property标签中添加子标签bean来指定对象
<bean id="student" class="com.feng.ioc.bean.Student">
<property name="clazz" >
<bean class="com.feng.ioc.bean.Clazz">
<property name="cid" value="01"/>
<property name="cname" value="计算机"/>
</bean>
</property>
</bean>
集合类型
-
list:
-
List:List中是字符串或简单类型的封装
<property name="hobbies" value="吃饭,喝酒"/>
-
List:List中的元素是对象类型
<property name="clazzes"> <list> <bean class="com.feng.ioc.bean.Clazz"> <property name="cid" value="1"/> <property name="cname" value="计算机"/> </bean> <bean class="com.feng.ioc.bean.Clazz"> <property name="cid" value="2"/> <property name="cname" value="计算机2"/> </bean> </list> </property>
-
-
Set:与List方式相同,将标签改为标签
<property name="clazzes"> <set> <bean class="com.feng.ioc.bean.Clazz"> <property name="cid" value="1"/> <property name="cname" value="计算机"/> </bean> <bean class="com.feng.ioc.bean.Clazz"> <property name="cid" value="2"/> <property name="cname" value="计算机2"/> </bean> </set> </property>
- Map:—
<property name="map"> <map> <entry key="1" value="map1"/> <entry key="2" value="map2"/> </map> </property>
- Properties
<property name="properties"> <props> <prop key="1">value1</prop> <prop key="2">value2</prop> </props> </property>
2.4.3 构造器注入
简单类型、字符串、对象
<bean id="date" class="java.util.Date"/>
<bean id="clazz" class="com.feng.ioc.bean.Clazz">
<property name="cid" value="1"/>
<property name="cname" value="计算机应用01班"/>
</bean>
<!--构造器注入-->
<bean id="student" class="com.feng.ioc.bean.Student">
<constructor-arg value="1001"/>
<constructor-arg value="小明"/>
<constructor-arg value="18"/>
<constructor-arg value="55.5"/>
<constructor-arg ref="date"/>
<constructor-arg ref="clazz"/>
</bean>
集合类型
<!--构造器注入-->
<bean id="student" class="com.feng.ioc.bean.Student">
<constructor-arg>
<list>
<value>吃饭</value>
<value>喝酒</value>
</list>
</constructor-arg>
<constructor-arg>
<list>
<bean class="com.feng.ioc.bean.Clazz">
<property name="cid" value="101"/>
<property name="cname" value="计算机"/>
</bean>
</list>
</constructor-arg>
<constructor-arg>
<set>
<value>抽烟</value>
<value>烫头</value>
</set>
</constructor-arg>
<constructor-arg>
<map>
<entry key="1" value="map1"/>
<entry key="2" value="map2"/>
</map>
</constructor-arg>
<constructor-arg>
<props>
<prop key="3">prop3</prop>
<prop key="4">prop4</prop>
</props>
</constructor-arg>
</bean>
<value>烫头</value>
</set>
</constructor-arg>
<constructor-arg>
<map>
<entry key="1" value="map1"/>
<entry key="2" value="map2"/>
</map>
</constructor-arg>
<constructor-arg>
<props>
<prop key="3">prop3</prop>
<prop key="4">prop4</prop>
</props>
</constructor-arg>
</bean>
2.5 Bean的作用域
在bean标签中,可以通过scope属性,指定对象的作用域
- scope = singleton 单例模式(默认饿汉模式,Spring容器初始化阶段会完成此对象创建)
- lazy-init = true — 懒汉模式
- scope = prototype 多例模式
2.6 Bean的生命周期
在bean标签中通过init-method属性,指定当前bean的初始化方法,初始化方法在构造器执行之后执行
通过destroy-method属性,指定当前bean的销毁方法,销毁方法在对象销毁之前执行
2.7 自动装配
自动装配(autowire):Spring在实例化当前bean时,从容器中找到匹配的实例,赋值给当前bean的属性
autowire=“byName”:根据bean属性名
autowire=“byType”:根据bean属性类型