一、Spring概述
1.1 web项目开发中代码的耦合问题
1.2 面向接口编程
在Servlet中定义Service接口的变量,不适用new关键字创建实现类对象,在Servlet类的对象被创建时,通过反射创建Service的实现类对象并赋值给Servlet的Service变量。
通过反射动态给Servlet中的Service属性赋值、Service中的DAO属性赋值我们做不到,Spring可以做到!
1.3 Spring介绍
Spring是一个
轻量级的控制反转和面向切面的容器
框架,用来解决企业项目开发的复杂度问题——解耦Spring两大核心思想:IoC和AOP
- IoC
- AOP
- 轻量级:体积小,对项目代码没有侵入性
- 控制反转:IoC(Inverse of Control),把创建对象、给对象属性赋值的工作交由Spring完成;Spring在通过反射创建对象的同时可以给属性赋值(DI:依赖注入)
- 面向切面:AOP(Aspect Oriented Programming)面向切面编程,可以在不改变原有业务代码的前提下进行业务的增强(原理:动态代理)
- 容器:实例对象,Spring不仅可以创建对象,还可以对创建的对象进行管理。
1.4 Spring架构
Spring Framework 基础架构
- Core Container
- Spring容器组件,用于完成对象的创建和管理
- 核心jar包:
- spring-core
- spring-beans 实例管理
- spring-context 容器上下文
- AOP,Aspects
- Spring AOP 组件,实现AOP面向切面编程
- 核心jar包:
- spring-aop
- spring-aspects
- Data Access
- Spring数据访问组件,基于对JDBC的封装实现持久化操作
- 事务管理jar:
- spring-tx
- Spring MVC
- Spring web组件,实现web项目的MVC控制
- 核心jar包:
- web
- webmvc
- Test
- Spring 测试组件,用于Spring环境下的单元测试
- 核心jar包:
- junit
- spring-test
二、Spring IoC
Spring IoC 容器组件,可以通过反射技术完成对象的创建、对象属性赋值以及对象管理等功能
2.1 Spring框架部署(IoC)
2.1.1 创建Maven工程
- Java
- web
2.1.2 添加SpringIoC依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.15</version>
</dependency>
2.1.3 创建Spring配置文件
- 在resources目录创建名为
applicationContext.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">
</beans>
2.2 Spring IoC使用
2.2.1 创建实体类
/**
* @Description 图书实体类
* @Author 千锋涛哥
* 公众号: Java架构栈
*/
public class Book {
private int bookId;
private String bookName;
private String bookAuthor;
private double bookPrice;
private Date bookDate;
}
2.2.2 将实体类配置到Spring容器
- 在Spring配置文件applicationContext.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">
<!--通过bean标签,将类配置给Spring管理-->
<bean id="book" class="com.qfedu.entity.Book"></bean>
</beans>
2.2.3 通过Spring工厂获取对象
//1.初始化Spring容器,加载配置文件
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
//2.通过Spring容器根据配置bean的id获取对象
Book book1 = (Book) context.getBean("book");
2.3 Spring依赖注入(DI)
通过Spring容器在创建对象的同时,可以给对象的属性赋值
依赖注入(DI Dependency Injection)——依赖Spring容器工厂给创建的对象的属性注入值
2.3.1 IoC和DI的区别
- IoC表示使用Spring容器工厂进行对象的创建
- DI是Spring在对象创建的过程中根据配置提供的数据,通过反射技术给对象的属性赋值
2.3.2 DI三种方式
-
set方法注入:通过反射调用属性的set方法进行属性赋值
- 需要提供无参构造器
- 需要提供属性的set方法
<bean id="date" class="java.util.Date"></bean> <bean id="book" class="com.qfedu.entity.Book"> <property name="bookId" value="1"/> <property name="bookName" value="Java程序设计"/> <property name="bookAuthor" value="王二狗"/> <property name="bookPrice" value="2.2"/> <property name="bookDate" ref="date"/> </bean>
-
构造器注入:通过反射调用有参构造器创建对象并给属性赋值
- 需要提供有参构造器
- constructor-arg标签设置参数要与构造器参数顺序一致,如果不一致需要通过index属性指定赋值给第一个参数(从0开始)
<bean id="date" class="java.util.Date"></bean> <bean id="book" class="com.qfedu.entity.Book"> <constructor-arg value="1" index="0"/> <constructor-arg value="谭浩强" index="2"/> <constructor-arg value="C语言程序设计" index="1"/> <constructor-arg value="56.66" index="3"/> <constructor-arg ref="date" index="4"/> </bean>
-
接口注入
2.3.3 不同类型属性值的注入
public class ClassA {
private int attr1;
private String attr2;
private Data attr3;
private List<String> attr4;
private List<Book> attr5;
private Set<String> attr6;
private Set<Book> attr7;
private Map<String ,String> attr8;
private Properties attr9;
private Book attr10;
}
<bean id="date" class="java.util.Date">
<property name="year" value="122"/> <!-- 设置基于1900年的偏移年份 -->
<property name="month" value="1"/> <!-- 设置0-11 -->
<property name="date" value="17"/>
</bean>
x`<bean id="classB" class="com.qfedu.entity.ClassB"></bean>
<bean id="classA" class="com.qfedu.entity.ClassA">
<!-- 1.简单类型:直接通过value赋值,可以自动实现类型转换 -->
<property name="attr1" value="12"/>
<!-- 2.字符串类型:直接通过value赋值 -->
<property name="attr2" value="helloworld"/>
<!-- 3.日期类型: 可以通过bean标签构造一个Date对象,也可以通过ref属性引用一个已经存在的对象-->
<!-- <property name="attr3" ref="date"/>-->
<property name="attr3">
<bean class="java.util.Date">
<property name="year" value="122"/> <!-- 设置基于1900年的偏移年份 -->
<property name="month" value="1"/> <!-- 设置0-11 -->
<property name="date" value="17"/>
</bean>
</property>
<!-- 4.List集合 -->
<property name="attr4">
<list>
<value>aaa</value>
<value>bbb</value>
<value>ccc</value>
</list>
</property>
<property name="attr5">
<list>
<bean class="com.qfedu.entity.ClassB"/>
<bean class="com.qfedu.entity.ClassB"/>
<bean class="com.qfedu.entity.ClassB"/>
</list>
</property>
<!-- 5.Set集合 -->
<property name="attr6">
<set>
<value>aaa</value>
<value>bbb</value>
<value>ccc</value>
</set>
</property>
<property name="attr7">
<set>
<bean class="com.qfedu.entity.ClassB"/>
<bean class="com.qfedu.entity.ClassB"/>
<bean class="com.qfedu.entity.ClassB"/>
</set>
</property>
<!--6.Map映射集合-->
<property name="attr8">
<map>
<entry>
<key>
<!-- map的key可以是各种类型,如果是对象类型使用bean标签,如果是字符串类型使用value标签 -->
<!-- <bean></bean> -->
<value>key1</value>
</key>
<!-- map的value也可以是各种类型,如果是对象类型使用bean标签,如果是字符串/简单类型使用value标签 -->
<!-- <bean></bean> -->
<value>value1</value>
</entry>
<entry>
<key><value>key2</value></key>
<bean class="com.qfedu.entity.ClassB"></bean>
</entry>
</map>
</property>
<!-- 7.Properties映射集合:是特殊的Map、key和value都必须是String-->
<property name="attr9">
<props>
<prop key="key1">value1</prop>
<prop key="key2">value2</prop>
</props>
</property>
<!-- 8.自定义类对象 -->
<!--<property name="attr10" ref="classB"></property> -->
<property name="attr10">
<bean class="com.qfedu.entity.ClassB"/>
</property>
</bean>