目录
一、Spring概述
1、ocp开闭原则
-
什么是ocp?
-
ocp是软件七大原则中最基本的一个原则:开闭原则
-
对扩展开放,对修改关闭
-
-
ocp开闭原则的核心?
-
只要你在扩展系统功能的时候,没有修改以前的代码。
-
-
当程序功能扩展的时候,如果动了之前稳定的程序,修改之前的程序都需要重新测试。
2、依赖倒置原则(DIP原则)
-
什么叫符合依赖倒置原则?
-
上层 不再 依赖于下层了 ,表示符合依赖倒置原则。
-
-
依赖倒置原则的核心是什么?
-
提倡面向接口编程,面向抽象编程,不面向具体编程。
-
3、控制反转IoC
-
当前程序 即违背了ocp、又违背了DIP,怎么办?
-
采用“控制反转“
-
控制反转:IoC(Inversion of control)
-
-
-
反转的两件事?
-
不在程序中采用硬编码的方式创建对象(new 对象不管了)
-
不在程序中采用硬编码的方式维护对象的关系(对象之间关系的维护权,不管了)
-
4、Spring框架
-
spring框架实现了控制反转IoC的这种思想
-
帮你new对象
-
可以帮助你维护对象和对象之间的关系
-
-
spring是一个实现了IoC思想的容器
-
控制反转的实现方式
-
依赖注入(Dependency Injection 简称DI)
-
-
控制反转是思想:依赖注入是这种思想的具体实现。
-
依赖注入DI,包括两种:
-
第一种:set注入
-
第二种:构造方法注入
-
-
依赖注入 中 “依赖”?“注入”?
-
依赖:A对象和B对象的关系
-
注入:是一种手段,通过手段,可以让A对象和B对象产生关系。注入包括:set注入和构造注入
-
-
依赖注入:
-
对象A和对象B之间的关系,靠注入来实现,包括set注入和构造方法注入。
-
-
注意术语:
-
OcP
-
DIP
-
IoC
-
DI
-
二、Spring学习
-
第一个spring程序
-
1、添加spring-context的依赖
-
2、定义bean
-
3、编写spring的配置文件,放到类的根路径下
-
-
ApplicationContext:应用程序上下文
-
Spring容器
-
Spring对IoC的实现
-
控制反转是一种思想。
-
控制反转是为了降低程序耦合度,提高程序扩展力,达到OCP原则,达到DIP原则。
-
控制反转,反转的是什么?
-
将对象的创建权利交出去,交给第三方容器负责。
-
将对象和对象之间关系的维护权交出去,交给第三方容器负责。
-
-
控制反转这种思想如何实现呢?
-
DI(Dependency Injection):依赖注入
-
-
依赖注入常见的实现方式包括两种:
-
第一种:set注入
-
第二种:构造注入
-
-
set注入
-
需要配置property标签
-
name的值:set的方法名,去掉set,首字母小写
-
ref:翻译为引用 ref后面指定的是bean的id
-
简单类型set注入: value
-
-
构造方法注入
-
配置constructor标签
-
index:参数下标
-
ref:引用 ref后面指定的是bean的id
-
-
通过源码分析得知,简单类型包括:
-
基本数据类型
-
基本数据类型对应的包装类
-
String或其他的CharSequence子类
-
Number子类
-
Date子类
-
Enum子类
-
URI
-
URL
-
Temporal子类
-
Locale
-
Class
-
另外还包括以上简单值类型对应的数组类型。
-
-
Spring管理数据源:
-
所有提供connection对象的,都是数据源
-
实现:javax.sql.DataSource
-
-
数组注入
-
通过<array>标签
-
-
list注入
-
通过<list>标签
-
-
map注入
-
通过<map>标签注入
-
-
properties注入
-
properties的key和value都是String类型的
-
通过<props>标签注入
-
-
注入null和空字符串
-
注入null
-
第一种:不给属性赋值
-
第二种:<null/>
-
-
注入空字符串
-
value不填写值
-
<value/>
-
-
-
p标签注入
-
基于set方法
-
第一步 在spring配置文件中配置配标签
-
第二步 使用p标签 P:"属性值"
-
-
c命名空间注入
-
基于构造方法
-
第一步 在spring配置文件中配置配标签
-
第二步 使用p标签
-
-
util命名空间
-
使用util命名空间可以让配置复用。
-
使用util命名空间的前提是:
-
在spring配置文件头部添加配置信息
-
-
-
基于xml的自动装配
-
UserService Bean中需要添加autowire="byName",表示通过名称进行装配。
-
通过set方法对属性赋值。id填写set方法的名称,去掉set 首字母小写
-
-
spring引入外部属性配置文件
-
配置spring的context命名空间
-
使用context:properties-placeholder 引入文件
-
Spring的bean的作用域 单例和多例
-
spring默认情况下如何管理bean的
-
默认是单例的(singleton) 在spring上下文初始化的时候实例化。
-
-
当将bean的scope属性 设置为prototype(原型):
-
bean是多例的 在spring初始化上下文的时候,不会初始化这些prototype的bean
-
每次调用getBean方法是,实例化bean对象。
-
-
scope属性的值
-
singleton:单例
-
prototype:多例
-
request:一次请求 一个bean
-
session:一次会话 一个bean
-
global session:portlet应用中专用的。
-
application:一个应用对应一个Bean
-
websocket:一个websocket生命周期对应一个Bean
-
自定义scope:很少使用
-
GoF之工厂模式
-
设计模式:一种可以被重复利用的解决方案
-
简单工厂模式
-
简单工厂模式是 工厂方法模式的特殊实现
-
又被称为:静态工厂方法模式
-
-
简单工厂模式的优点:
-
客户端程序不需要关心对象的创建细节,需要哪个对象时,只需要向工厂索要即可,初步实现了责任的分离。客户端只负责“消费”,工厂负责“生产”。生产和消费分离。
-
-
简单工厂模式的缺点:
-
缺点1:工厂类集中了所有产品的创造逻辑,形成一个无所不知的全能类,有人把它叫做上帝类。显然工厂类非常关键,不能出问题,一旦出问题,整个系统瘫痪。
-
缺点2:不符合OCP开闭原则,在进行系统扩展时,需要修改工厂类。
-
-
工厂方法模式:Factory Mrthod Pattern
-
工厂方法模式的优点:
-
一个调用者想创建一个对象,只要知道其名称就可以了。
-
扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。
-
屏蔽产品的具体实现,调用者只关心产品的接口。
-
-
工厂方法模式的缺点:
-
每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
-
-
-
bean的获取方式
-
第一种:构造方法
-
第二种:简单工厂模式
-
静态方法指定: factory-method
-
-
第三种:工厂模式
-
实例方法指定:factory-bean factory-method
-
-
第四种:实现 FactoryBean接口
-
通过FactoryBean这个工厂Bean主要是对普通Bean加工处理
-
-
BeanFactory和FactoryBean的区别?
-
BeanFactory
-
“bean工厂”,负责创建Bean对象,是Spring IoC容器的顶级对象。
-
-
FactoryBean
-
是一个Bean,辅助Spring实例化其他Bean对象的一个Bean。
-
Spring中Bean可以分为两种:
-
普通Bean
-
工厂Bean(辅助Spring实例化其他Bean对象的一个Bean。)
-
-
-
Bean的生命周期
-
粗略的五步来分的话:
-
第一步:实例化bean(无参数构造方法)
-
第二步:给Bean的属性赋值(set方法)
-
第三步:初始化bean(init方法)
-
第四步:使用Bean
-
第五步:销毁Bean (destory方法 )
-
-
.castvar 快速类型转换
-
bean的生命周期七步来分:
-
实现BeanPostProcessor类,并且重写before和after方法:
-
添加的两步:bean的init初始化方法之前!!
-
第一步:实例化bean(无参数构造方法)
-
第二步:给Bean的属性赋值(set方法)
-
第三步:bean后处理器的before方法
-
第四步:初始化bean(init方法)
-
第五步:bean后处理器的after方法
-
第六步:使用bean
-
第七步:销毁Bean (destory方法 )
-
-
bean的生命周期十步
-
添加的三步在哪里?
-
点位1:在“”bean后处理器 before之前
-
检查bean是否实现了Aware相关的接口,如果实现了接口中的方法,spring容器调用方法的目的是:给你传递一些参数,方便使用
-
-
点位2:在“”bean后处理器 before之后
-
InitializingBean接口
-
-
点位3:使用bean之后,销毁bean之前
-
DisPosableBean接口
-
-
-
添加三个点位的特点:是否实现了某些特定接口。
-
-
spring容器只对singleton的bean进行完整的生命周期管理
spring的循环依赖
-
在singleton+setter模式下,不会出现问题,spring是怎么应对?
-
spring对bean管理主要分为两个阶段:
-
第一阶段:在spring容器加载的时候实例化bean,只要任意一个bean实例化之后,马上“曝光”。
-
第二阶段:bean“曝光”之后,进行属性的赋值
-
核心解决方案:bean的实例化和属性赋值分两个阶段
-
-
-
spring的scope属性,两个类都是property时,会报错。
-
构造注入产生的循环依赖无法解决的,编写代码时要注意!!
Spring的注解开发
-
注解回顾
-
Target注解:设置Component注解可以出现的位置,ElementType.TYPE表示Component注解只能用在类和接口上。
-
Retention注解:
设置Component注解的保持性策略,RetentionPolicy.RUNTIME可以被反射机制读取。
-
-
声明bean的注解,常用有哪些
-
@Component 组件 下面三个注解父类 都引用了这个组件
-
@Controller 控制器
-
@Service 业务
-
@Repository 仓库 数据库
-
-
怎么使用注解?
-
1、加入aop的依赖
-
2、配置文件中加入context的命名空间
-
3、配置要扫描的包
-
4、在bean上使用注解
-
-
手动指定名字,就是指定的名字,默认是首字母变小写
-
如果是多个包怎么办?有两种解决方案:
-
第一种:在配置文件中指定多个包,用逗号隔开。
-
第二种:指定多个包的共同父包。
-
-
选择性实例化
-
use-default-filters="false"
-
表示所有声明bean的注解全部失效
-
-
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
-
表示只有Controller进行实例化
-
-
-
负责依赖注入的注解
-
@Value
-
当属性的类型是简单类型时,可以使用@Value注解进行注入。
-
-
@Autowired和@Qualifier
-
翻译为:自动连线的 自动装配
-
可以放在 属性、构造方法、set方法、构造方法参数上
-
用来注入非简单类型,单独使用Autowired类型是根据类型自动装配。
-
根据名字自动装配:Autowired+Qualifier注解
-
当带参数的构造方法只有一个,@Autowired注解可以省略。
-
-
@Resource
-
出现在 FIELD和 set方法上
-
默认byName注入,没有指定name时把属性名当做name,根据name找不到时,才会byType注入。byType注入时,某种类型的Bean只能有一个。
-
-
GoF代理模式
-
在java程序中代理模式作用?
-
控制访问:保护目标对象
-
商家不让用户访问厂家
-
-
功能增强:完成目标对象的调用时,附加一些其他的功能。
-
-
代理类完成的功能?
-
调用目标对象的目标方法
-
功能进行增强
-
-
代理模式中三个角色
-
目标对象
-
代理对象
-
目标对象和代理对象的公共接口
-
-
为什么目标对象和代理对象有公共接口呢?
-
对于客户端程序来说,客户端无法察觉的,客户端在使用代理对象的时候就像是使用目标程序。
-
-
类与类之间的关系
-
泛化关系:继承 is a
-
关联关系:has a
-
泛华关系的耦合度高于关联关系,优先选择使用关联关系
-
-
静态代理:
-
自己编写接口的代理类
-
-
动态代理:
-
在程序运行阶段,动态的生成代理类,减少代理类的数量,解决代码复用问题。
-
-
jdk动态代理:
-
Proxy的newProxyInstance(类加载器,代理类实现的接口,调用处理器)
-
第一个参数:ClassLoader
-
类加载器, 目标类和代理类的类加载器使用同一个。
-
-
第二个参数:
-
代理类实现的接口
-
-
第三个参数:调用处理器 InvocationHandler
-
接口,在调用处理器编写的是:增强代码
-
-
-
InvocationHandler接口,invoke方法三个参数:
-
第一个参数:Object proxy。
-
代理对象。设计这个参数只是为了后期的方便,如果想在invoke方法中使用代理对象的话,尽管通过这个参数来使用。
-
-
第二个参数:Method method
-
目标方法,要执行的目标方法就是它。
-
-
第三个参数:Object[] args。
-
目标方法调用时要传的参数。
-
-
-
方法调用四要素:
-
哪个方法
-
调用哪个对象的
-
传什么参数
-
返回什么值
-
面向切面编程AOP
-
Aop:
-
面向切面编程,面向方面编程
-
-
Spring的AOP使用的动态代理是:JDK动态代理 + CGLIB动态代理技术
-
交叉业务:
-
日志、事务管理、安全等被称为:交叉业务
-
-
用一句话总结AOP:将与核心业务无关的代码独立的抽取出来,形成一个独立的组件,然后以横向交叉的方式应用到业务流程当中的过程被称为AOP。
-
AOP的优点:
-
第一:代码复用性增强。
-
第二:代码易维护。
-
第三:使开发者更关注业务逻辑。
-
-
Aop的七大术语:
-
连接点JoinPoint:
-
在程序执行流程中,可以织入切面的位置
-
方法的执行前后,异常抛出等位置
-
-
切点Pointcut:
-
真正织入切面的方法(本质是方法)
-
-
通知Advice:
-
具体的增强的代码
-
例如:事务代码,日志代码,安全代码,统计时长的代码。
-
-
切面Aspect:
-
切点+通知
-
-
-
基于aspectj的aop注解开发
-
添加依赖
-
配置spring的xmlns文件路径
-
配置bean
-
添加@Aspect
-
添加切点表达式
-
spring配置文件中启动自动代理
-
true 为 cglib动态代理
-
false 为 jdk动态代理(默认)没有接口时,自动选择cglib动态代理。
-
-
Spring事务
-
什么是事务?
-
-
在一个业务流程当中,通常需要多条DML(insert delete update)语句共同联合才能完成,这多条DML语句必须同时成功,或者同时失败,这样才能保证数据的安全。
-
多条DML要么同时成功,要么同时失败,这叫做事务。
-
事务:Transaction(tx)
-
-
事务的四个处理过程:
-
-
第一步:开启事务 (start transaction)
-
第二步:执行核心业务代码
-
第三步:提交事务(如果核心业务处理过程中没有出现异常)(commit transaction)
-
第四步:回滚事务(如果核心业务处理过程中出现异常)(rollback transaction)
-
-
事务的四个特性:
-
A 原子性:事务是最小的工作单元,不可再分。
-
C 一致性:事务要求要么同时成功,要么同时失败。事务前和事务后的总量不变。
-
I 隔离性:事务和事务之间因为有隔离性,才可以保证互不干扰。
-
D 持久性:持久性是事务结束的标志。
-
-
spring实现事务的两种方式:
-
编程式事务
-
编写代码方式管理事务
-
-
声明式事务
-
基于注解方式
-
基于XML配置方式
-
-
-
事务传播行为:
-
service类中有a方法和b方法,a方法上有事务,b方法上也有事务,当a方法执行过程中调用b方法
-
REQUIRED:没有就新建,有就加入
-
SPPORTS: 有就加入,没有就不管了
-
MANDATORY : 有就加入,没有就抛异常
-
REQUIRES_NEW : 不管有没有,直接开启一个新的事务,新的事务和之前的事务不存在嵌套关系,之前的事务被挂起。
-
NOT_SUPPORTED : 不支持事务,存在就挂起
-
NEVER: 不支持事务,存在就抛异常
-
NESTTED : 有事务的话,就在这个事务里再嵌套一个完全独立的事务,嵌套的事务可以独立的提交和回滚。没有事务就和REQUIRED一样
-
-
-
事务的隔离级别:
-
类似教室A和教室B之间的墙,隔离级别越高表示墙体越厚,隔音效果越好。
-
事务不隔离带来的问题?
-
脏读:读到没有提交的到数据库的数据
-
不可重复读:在同一个事务中,第一次和第二次读到的数据不一样
-
幻读:读到的数据是假的
-
-
事务隔离级别的四个级别:
-
读未提交:READ_UNCOMMITED
-
存在脏读问题,读到其他事务没有保存的数据
-
-
读已提交:READ_COMMIT
-
解决了脏读问题,存在不可重复读的问题
-
-
可重复读:REPEATANLE_READ
-
解决了不可重复读,只要当前事务,读到的数据一直都是一样的,存在幻读问题。
-
-
序列化:SERILIZABLE
-
解决了幻读问题,事务排队执行,不支持并发
-
-
-
MVC三层架构
-
表示层 (web层)-> 调 service 层 -> 调dao层(Mapper)