一、Spring
1.1 Web项目开发中的耦合度的问题
- 在Servlet中调用service的方法,则需要在Servlet类中通过new关键字来创建Service的实例
1 | public interface ProductService{ |
1 | public class ProductServiceImpl1 implements ProductService{ |
1 | public class ProductServiceImpl2 implements ProductService{ |
1 | public class ProductListServlet extends HttpServlet{ |
- 在service实现类中需要调用DAO中的方法,也需要在servcie实现类通过new关键字创建DAO实现类对象
- 如果使用new关键字创建对象:
- 失去了面向接口编程的灵活性
- 代码的侵入性增强(增加了耦合度)、降低了代码的灵活性
- 增强项目的扩展性
1.2 面向接口编程
面向接口编程 |
---|
解决方案
:在Servlet中定义Service接口的对象变量,不使用new关键字创建实现类对象,在servlet的实例化的时候,通过反射动态的给Service对象变量赋值。
如何实现
:Spring可以做到!!!
1.3 Spring简介
Spring是一个
轻量级的控制反转和面向切面的容器
框架,用来解决企业项目开发的复杂度问题—解耦
- 轻量级:体积小,对代码没有侵入性
- 控制反转:IoC(Inverse of Control),把创建对象的工作交由Spring完成,Spring在创建对象的时候同时可以完成对象属性赋值(DI)
- 面向切面:AOP(Aspect Oriented Programming)面向切面编程,可以在不改变原有业务逻辑的情况下实现对业务的增强
- 容器:实例的容器,管理创建的对象
1.4 Spring架构
Spring架构图
- Spring Framework是Spring生态圈最基础的项目,是其他项目的基础
1. Core Container
Spring核心容器组件,用于完成实例的创建和管理
- core
- beans 实例管理
- context 容器上下文
2. AOP、Aspects
Spring AOP组件,实现面向切面编程
- aop
- aspects
3. web
Spring web组件实际指的是SpringMVC框架,实现web项目的MVC控制
- web (Spring对web项目的支持)
- webmvc (SpringMVC组件)
4. Data Access
Spring数据访问组件,也是一个基于JDBC封装的持久层框架(即使没有mybatis,Spring也可以完成持久化操作)
- Data Access:数据访问
- Data Integeration:数据集成
5. Test
Spring的单元测试组件,提供了Spring环境下的单元测试支持
- test
1.5 Spring Framework学习路线
- 核心容器
- 核心概念(IOC、DI)
- 容器基本操作
- 整合
- 整合MyBatis
- AOP
- 核心概念
- AOP基础操作
- AOP使用开发
- 事务
- 事务实用开发
- 家族
- SpringMVC
- SpringBoot
- SpringCloud
二、Spring IoC — 基于XML
2.1 Spring框架部署(Ioc)
SpringIoC容器组件,可以完成对象的创建、对象属性的赋值、对象管理
1.创建Maven工程
- Java
- Web
2. 添加SpringIoC依赖
- core
- beans
- aop
- context
- expression
1 | <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans --> |
3. 创建Spring配置文件
通过配置文件“告诉”Spring容器创建什么对象,给对象属性赋什么值
- 在resources目录下创建名为
applicationContext.xml
的文件(文件名可以自定义,但是约定俗成通用使用这个)
1 |
|
3.1 如何定制配置文件模板
2.2 SpringIOC使用
使用SpringIOC组件创建并管理对象
1.创建一个实体类
1 | public class Student { |
2.在Spring配置文件中配置实体类
1 |
|
3.初始化Spring对象工厂,获取对象
- ClassPathXMLApplicationContext
1 | //通过Spring容器创建对象 |
2.3 IoC和DI
- IoC(Inverse of Control)控制反转,通过Spring对象工厂完成对象的创建
- DI(Dependency Injection)依赖注入,在Spring完成对象创建的统一依赖Spring容器完成对对象属性的赋值
1. IoC
当我们需要通过Spring对象工厂创建某个类的对象的时候,需要将这个对象交给Spring管理–通过bean标签配置
1 | <!--通过bean将实体类配置给Spring进行管理,id表示实体类的唯一表示--> |
2. DI
通过Spring容器给对象的属性进行赋值
1 | <!--通过bean标签将实体类配置给Spring进行管理,id表示实体类的唯一标识--> |
2.4 DI依赖注入
1.依赖注入的三种方式
Spring容器加载配置文件之后通过
反射
创建类的对象,并给属性赋值;Spring容器通过反射实现属性注入有三种方式:
- set方法助注入
- 构造器注入
- 接口注入(不常用)
2. set方法注入
在bean标签中通过配置property标签给对象属性赋值,实际上就是通过反射调用set方法完成属性的注入
简单类型及字符串
- 直接通过property标签的value属性赋值
1 | <!--通过bean标签将实体类配置给Spring进行管理,id表示实体类的唯一标识--> |
日期类型
- 方式1:在
property
标签中通过ref
引用Spring容器中的对象
1 | <!--通过bean标签将实体类配置给Spring进行管理,id表示实体类的唯一标识--> |
- 方式2:在
property
标签中添加字标签bean
来指定对象
1 | <bean id="student" class="com.qfedu.ioc.bean.Student"> |
自定义类对象属性
- 方式1:在
property
标签中通过ref
引用Spring容器中的对象
1 | <bean id="student" class="com.qfedu.ioc.bean.Student"> |
- 方式2:在
property
标签中添加字标签bean
来指定对象
1 | <bean id="student" class="com.qfedu.ioc.bean.Student"> |
集合类型
List
- List
List中的元素是字符串类型或者简单类型的封装类时 - 采用如下两种写法
1
2
3
4
5
6
7
8
9
10<!--写法1-->
<property name="hobbies" value="旅游,电影,游泳"/>
<!--写法2-->
<property name="hobbies">
<list>
<value>旅游</value>
<value>打游戏</value>
<value>Python</value>
</list>
</property>- List
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21<!--写法1 bean标签-->
<property name="hobbies">
<list>
<bean class="com.qfedu.ioc.bean.Book"/>
<bean class="com.qfedu.ioc.bean.Book"/>
<bean class="com.qfedu.ioc.bean.Book"/>
</list>
</property>
<!--写法2 引用-->
<bean id="book" class="com.qfedu.ioc.bean.Book"/>
<property name="hobbies">
<list>
<ref bean="book"></ref>
<ref bean="book"></ref>
<ref bean="book"></ref>
<ref bean="book"></ref>
</list>
</property>- List
Set
1
2
3
4
5<property name="sets">
<set>
<!--和List元素注入方式相同-->
</set>
</property>Map
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17<property name="maps">
<map>
<entry>
<key>
<value>key1</value>
</key>
<value>value1</value>
</entry>
<entry>
<key>
<value>key2</value>
</key>
<value>value2</value>
</entry>
</map>
</property>Properties:properties继承自
Hashtable类
可以直接给键值对,因为properties里面的键值对只能是字符串类型1
2
3
4
5
6<property name="properties">
<props>
<prop key="k1">aaa</prop>
<prop key="k2">bbb</prop>
</props>
</property>
3.构造器注入
简单类型、字符串、Object类型
1 | <bean id="clazz" class="com.qfedu.ioc.bean.Clazz"></bean> |
集合类型属性
类代码:
1 | public class Student{ |
配置:
1 | <bean id="stu1" class="com.qfedu.ioc.bean.Student"> |
2.5 Bean的作用域
在bean标签可以通过scope属性指定对象的的作用域
- scope=”singleton” 表示当前bean是单例模式(默认饿汉模式,Spring容器初始化阶段就会完成此对象的创建;当在bean标签中设置 lazy-init=”true”变为懒汉模式)
- scope=”prototype” 表示当前bean为非单例模式,每次通过Spring容器获取此bean的对象时都会创建一个新的对象
- 单例
1 | <bean id="book" class="com.qfedu.ioc.bean.Book" scope="singleton" lazy-init="true"></bean> |
- 多例
1 | <bean id="book" class="com.qfedu.ioc.bean.Book" scope="prototype"></bean> |
2.6 Bean的生命周期方法
- Bean类
1 | public class Book { |
- Spring配置文件
1 | <!--在bean标签中通过init-method属性指定当前bean的初始化方法,初始化方法在构造器执行之后执行--> |
2.7 自动装配
自动装配:Spring在实例化当前bean的时候从Spring容器中找到匹配的实例赋值给当前bean的属性
自动装配策略有两种:
- byName 根据当前Bean的属性名在Spring容器中寻找匹配的对象 ,如果根据name找打了bean但是类型不匹配则抛出异常
- byType 根据当前Bean的属性类型在Spring容器中寻找匹配的对象,如果根据类型找到了多个bean也会抛出异常
- byName
1 | <!--byName 根据当前bean的属性名在Spring容器中寻找匹配的对象,如果根据name找到了bean但是类型不匹配则会抛出异常--> |
- byType
1 | <!--byName 根据当前bean的属性名在Spring容器中寻找匹配的对象,如果根据name找到了bean但是类型不匹配则会抛出异常--> |
2.8 SpringIoC工作原理
三、Spring IoC-基于注解
SpringIoC的使用,需要通过xml将类声明给Spring容器进行管理,进而通过Spring工厂完成对象的创建以及属性值的注入;
Spring除了提供基于xml的配置方式,同时还提供了注解的配置:直接在实体类中添加注解声明给Spring容器管理,以简化开发步骤。
3.1 Spring 框架部署
1.创建Maven项目
略
2.添加SpringIoC依赖
1 | <dependency> |
3.创建Spring配置文件
- Spring容器初始化时,只会加载applicationContext.xml文件,在实体类中添加的注解不会被Spring扫描,所以需要在
applicationContext.xml声明Spring的扫描范围
,以达到Spring初始化扫描带有注解的实体类并完成初始化工作。
1 |
|
3.2 SpringIoC常用注解
1. @Component
- 类注解,声明此实体类被Spring容器进行管理,相当于bean标签的作用
@Component(value = "stu")
:value属性用于指定当前bean的id,相当于bean标签的id属性;value属性可以忽略不写,如果省略则当前bean的id默认为类名的首字母小写- 除了
@Component
之外,@Service
、@Controller
、@Repository
这三个注解也可以将类声明给Spring管理,但是有语义上的区别:@Controller
注解主要声明将控制器类配置给Spring管理,例如Servlet@Service
注解主要声明业务处理类配置Spring管理,Service接口的实现类@Repository
直接主要声明持久化类配置给Spring管理,DAO接口@Component
除了控制器、servcie和DAO之外的类一律使用此注解声明
2. @Scope
- 类注解,用于声明当前类单例模式还是 非单例模式,相当于bean标签的scope属性
- @Scope(“prototype”) 表示声明当前类为非单例模式(默认单例模式)
3. @Lazy
- 类注解,用于声明一个单例模式的Bean是否为懒汉模式
- @Lazy(true) 表示声明为懒汉模式,默认为饿汉模式
4. @PostConstruct
- 方法注解,声明一个方法为当前类的初始化方法(在构造器之后执行),相当于bean标签的init-method属性
5. @PreDestroy
- 方法注解,声明一个方法为当前类的销毁方法(在对象从容器中释放之前执行),相当于bean标签的destory-method属性
6. @Autowired
属性注解、方法注解(set方法),声明当前属性为自动装配,默认是byType
@Autowired(required = false)
通过required
属性来设置当前自动装配是否是必须的(默认为必须–如果在Spring容器中没有找到与属性类型相匹配的bean会抛出异常),自动装配的两种方式:- byType
- ref引用
1
2
3
4
public void setClazz( { Clazz clazz)
this.clazz = clazz;
}
7.@Resource
- 属性注解,也用于声明属性自动装配
- 默认装配方式为byName,如果根据byName没有找到对应的bean,则继续根据byType继续寻找对应的bean,根据byType也没有找到对应的bean或者找到了不止一个类型匹配的bean,则抛出异常。
四、代理设计模式
4.1 生活中的代理
代理设计模式的优点:将通用性的工作都交给代理对象完成,被代理对象只需专注自己的核心业务。
4.2 静态代理
静态代理,代理类只能够为特定的类生产代理对象,不能代理任意类
使用代理的好处:
- 被代理类中只需要关注核心业务的实现,将通用的管理型逻辑(事务处理、日志管理等操作)和业务逻辑分离
- 将通用的代码放在代理类中实现,提供了代码的复用性
- 通过在代理类中添加代码业务逻辑,实现对原有业务逻辑的扩展增强
4.3 动态代理
动态代理,几乎可以为所有的类产生代理对象
实现方式有两种:
- JDK动态代理
- CGLib动态代理
1. JDK动态代理
- JDK动态代理类实现:
1 | /** |
- 测试:
1 | public class TestDynamicProxy { |
2. CGLib动态代理
由于JDK动态代理是通过被代理类实现的接口来创建代理对象的,因此JDK动态代理只能代理实现了接口的类的对象。如果一个类没有实现任何接口,该如何产生代理对象呢?
CGLib动态代理,是通过创建被代理类的子类来创建代理对象的,因此即使没有实现任何接口的类也可以通过CGLib产生代理对象
注:
CGLib动态代理不能为final类创建代理对象,因为被final关键字修饰的类不能被继承
- 添加CGlib的依赖
1 | <!-- https://mvnrepository.com/artifact/cglib/cglib --> |
- CGLib动态代理类实现:
1 | /** |
- 测试:
1 | public class TestDynamicProxy { |
五、 Spring AOP
5.1 AOP概念
Aspect Oriented Programming ,面向切面编程,是一种利用”横切”的技术(底层实现就是动态代理),对原有的业务逻辑进行拦截,并且可以在这个拦截的横切面上添加特定的业务逻辑,对原有的业务进行增强。
基于动态代理的实现可以在不改变原有业务的情况下对业务进行增强。
5.2 Spring AOP框架部署
1. 创建Maven项目
略
2. 添加依赖
- context
- aspect
1 | <dependency> |
3.创建Spring配置文件
- 引入aop的命名空间
1 |
|
5.3 AOP配置- 语句XML
给DAO的方法添加开启事务和提交事务的逻辑
1.创建一个类,定义要添加的业务逻辑
1 | public class TxManager { |
2. 配置AOP
1 |
|
AOP开发步骤:
- 创建切面类,在切面类定义切点方法
- 将切面类配置给Spring容器
- 声明切入点
- 配置AOP的通知策略
5.4 切入点的声明
1. 各种切入点声明方式
1 | <!--使用aop:pointcut标签声明切入点:切入点可以是一个方法--> |
2. AOP使用注意事项
- 如果使用Spring AOP面向切面编程,调用切入点方法的对象必须通过Spring容器获取
- 如果一个类中的方法被声明为切入点并且织入了切点之后,通过Spring容器获取到的该类对象其实获取到的是一个该类的代理对象
- 如果一个类中的方法没有声明为切入点,通过Spring容器获取的就是这个类真实创建的对象
5.5 AOP通知策略
AOP通知策略:就是声明将切面类中的切点方法如何织入到切入点
- before
- after-returning
- after-throwing
- around
- after
1.定义切面类
1 | package com.qfedu.dao.utils; |
2. 配置切面类
1 | <aop:aspect ref="myAspect"> |
六、Spring AOP注解配置
6.1 Spring AOP注解配置框架部署
1.创建Maven工程
略
2.添加Spring依赖
- context
- aspects
3.Spring配置文件
1 |
|
6.2 AOP注解配置案例
1 | package com.qfedu.utils; |
注意:
注解使用虽然方便,但是只能在源码上添加注解,因此我们的自定义类提倡使用注解配置;但如果使用到第三方提供的类则需要通过xml配置形式完成配置。
七、Spring整合MyBatis
Spring 两大核心思想:IoC 和AOP
IoC:控制反转,Spring容器可以完成对象的创建、属性注入、对象管理等工作
AOP:面向切面,在不修改原有业务逻辑的情况下,实现原有业务的增强
7.1 Spring可以对MyBatis提供哪些支持
- IoC支持:SpringIoC可以为MyBatis完成DataSource、SQLSessionFactory、SQLSession以及DAO对象的创建。
- AOP支持:使用Spring提供的事务管理切面类完成对MyBatis数据库操作中的事务管理
7.2 Spring整合MyBatis准备工作
1.创建Maven工程
略
2.部署MyBatis框架
添加依赖
- MySQL驱动
- MyBatis
1
2
3
4
5
6
7
8
9
10
11
12
13<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>创建MyBatis配置文件mybatis-config.xml(创建配置文件之后无需进行任何配置)
1 |
|
3.部署Spring框架
- 添加依赖
1 | <dependency> |
- 创建Spring配置文件:applicationContext.xml
1 |
|
4.添加Spring整合MyBatis的依赖
- mybatis-spring 就是mybatis提供的兼容Spring的补丁
1 | <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring --> |
7.3 Spring整合MyBatis整合IoC配置
1.整合Druid连接池
- 添加druid的依赖
1 | <!--druid的依赖--> |
- 创建druid.properties属性文件
1 | druid.driver=com.mysql.jdbc.Driver |
- 在applicationContext.xml中配置DruidDataSource
1 | <!--加载durid.properties属性文件--> |
2.整合MyBatis-创建SQLSessionFactory
依赖Spring容器创建MyBatis的SQLSessionFactory对象
1 | <!--依赖Spring容器完成MyBatis的SQLSessionFactory对象的创建--> |
3. 整合MyBatis-创建Mapper
1 | <!--加载dao包中的所有DAO接口,通过sqlSessionFactory获取SQLSession,然后创建所有的DAO接口对象 |
7.4 Spring整合MyBatis整合AOP配置
使用Spring提供的事务管理切面类,完成DAO中增删改操作的事务管理