spring核心功能:
- IOC/DI: 控制翻转/依赖注入
- AOP: 面向切面编程
- 声明式事务
spring作为一个大的容器
Core container:核心容器,启动spring的根本
IOC :控制反转
原先程序员做的主动通过new来实例对象,交给spring来负责
控制反转中的控制指的是:控制类的对象
控制反转中的反转指的是交给spring负责
IOC最大的作用:解耦
程序员不需要管理对象,解除了程序员和对象的耦合。
环境配置
导入jar包(四个核心包,一个日志包:beans,context,core,expression,logging)
在src下新建一个xml文件,spring的容器ApplicationContext,applicationContext.xml配置文件都保存在ApplicationContext容器中。
spring配置文件是基于schema(schema文件扩展名.xsd)
创建对象的三种方式
- 通过构造方法创建
无参构造创建:默认情况
有参构造创建:需要明确配置 - 实例工厂
- 静态工厂
DI:依赖注入
DI:当一个类需要依赖另一个对象,给另一个对象实例化后注入给这个对象的过程叫做依赖注入
AOP:面向切面编程(高扩展)
在程序原有纵向执行流程中,针对某一个或某一些方法添加通知,形成横切面过程就叫做面向切面编程
原有功能:切点,pointcut
前置通知:在切点之前执行的功能,before advice
后置通知:在切点之后执行的功能,after advice
如果切点执行过程当中出现了异常,会触发异常通知,throws advice
所有功能总成为切面
织入:把切面嵌入到原有功能的过程叫做织入
spring提供了两种AOP实现方式
- Schema-based
- 每个通知都需要实现接口或类。
- 配置spring配置文件时在aop:config配置
- Aspectj
- 每个通知不需要实现接口或类
- 配置spring配置文件是在aop:config的子标签aop:aspect中配置
通配符
“*”星号表示任意包下任意类的,都有切面
“(。。)”括号内点点,表示任意方法
异常通知方法(aspectj)
只有aspectj才会提供异常处理方法,所以一般在spring中不会捕获异常,不然spring不能发现异常进行事务回滚
在spring配置文件中配置:
aop:aspect的ref属性表示方法所在的类
aop:xxxx/表示通知的类型,是什么通知
method:当触发这个通知,应该调用哪个方法
使用注解(基于aspect)
spring不会自动去寻找注解,必须告诉spring哪些包下可能有注解
- 引入xmins:context
- @component
代理设计模式
- 设计模式:前人总结的一套解决特定问题的代码
- 代理设计模式优点
- 保护真实对象
- 让真实对象职责更明确
- 扩展
- 代理设计模式
- 真实对象
- 代理对象
- 抽象对象(抽象功能)
静态代理设计模式
- 由代理对象代理所有真实对象的功能
- 自己编写代理类
- 每个代理的功能需要单独编写
- 静态代理设计模式的缺点:
- 当代理功能比较多时,代理中方法需要写很多
动态代理
- 为了解决静态代理频繁编写代理功能的缺点
- 分类:
- jdk提供
- cglib动态代理
jdk动态代理
- 和cglib动态代理对比
- 优点:jdk自带,不需要额外导入jar包
- 缺点:
- 真实对象必须实现接口
- 利用反射机制效率不高
cglib动态代理
- cglib的优点:
- 基于字节码,生成真实对象的子类
- 运行效率发高于jdk动态代理
- 不需要实现接口
- 基于字节码,生成真实对象的子类
- cglib缺点
- 非jdk功能,需要额外导入jar包
- 使用spring AOP时,只要出现proxy和真实对象转换异常
- 设置为true,使用cglib
- 设置为false,使用jdk(默认值)
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspect-autoproxy>
自动注入
- 在spring配置文件中发现对象名和ref=“ID” ID名相同使用自动注入,可以不配置
- 两种配置方法
- 在中通过autowire=“”配置,只对这个生效
- 在中通过default-autowrie=“”配置,表当前文件中所有的都是全局配置内容
- autowrie=“可取值”
- default:默认值,根据全局default-autowrie=“”值,默认全局和局部都没有配置情况下相当于no
- no:不自动注入
- byname:通过名称自动注入。在spring容器中找类的id
- bytype:根据类型注入
- spring容器中不可以出现两个相同类型的
- constructor:根据构造方法注入
- 提供对应参数的构造方法(构造方法参数包含注入对象)
- 底层使用byname,构造方法参数名和其他的ID相同。
spring中加载(properities)属性文件
- 在src下新建xxx.properities文件。
- 在spring配置文件中先引入xmlns:context;在下面添加
- 如果需要记载多个配置文件逗号分割
- 添加了属性文件加载,并且在中开启自动注入注意的地方
- sqlSesssionFactoryBean的ID不能叫做sqlSessionFactory
- 修改
- 把原来通过ref引用替换value赋值,自动注入只能影响ref,不会影响value赋值
- 在被spring管理的类中通过@value(“$(key)”)取出properities中内容
-
添加注释扫描
-
在类中添加
- key和变量名可以不相同
- 变量类型任意,只要保证key对应的value能转换成这个类型就可以
-
scope属性
- 的属性
- 作用:控制对象有效范围(单例,多例等)
- 标签对应的对象默认是单例的。
- 无论获取多少次,都是同一个对象
- scope可取值
==1. singleton 默认值,单例
2. prototype 多例,多次获取重新实例化- request 每次请求重新实例化
- session每个会话对象内,对象是单例的
- application 在application对象内是单例
- global session spring推出的一个对象,依赖于spring-webmvc-portlet,类似于session
单例设计模式
- 作用:在应用程序中保证最多只有一个实例
- 好处:
- 提升运行效率
- 实现数据共享。案例application对象
- 懒汉式
- 对象只有被调用时才会去创建
- 由于添加了锁,所以导致效率低
- 饿汉式
1.解决了懒汉式中多线程访问可能出现同一个对象和效率低的问题
== 声明式事务 ==
- 编程式事务
- 由程序员编程事务控制代码
- OpenSessionView编程式事务
- 声明式事务
- 事务控制代码已经由spring写好,程序员只需声明出哪些方法需要进行事务控制和如何进行事务控制
- 声明式事务都是针对于serviceimpl类下方法的。(Serviceimpl是业务,一个业务对应一个事务,也就是说是对Serviceimpl的操作)
- 事务管理器是基于通知(advice)的。(也可以说事务是一个通知)
- 在spring配置文件中配置声明式事务
声明式事务中属性解释
- name=“”哪些方法需要有事务控制
- 支持通配符*
- readonly=“Boolean”是否是只读事务
- 如果为true,告诉数据此事务为只读事务,数据化优化,会对性能有一定提升,所以只要是查询的方法,建议使用此数据。
- 如果为false(默认值),事务需要提交的事务,建议增、删、改。
- propagation控制事务传播行为
- 当一个具有事务控制的方法被另一个有事务控制的方法调用后,需要如何管理事务(新建事务?在事务中执行?把事务挂起?报异常?)
- REQUIRED(默认值):如果当前有事务,就在事务中执行,如果当前没有事务,新建一个事务。
- SUOOORTS:如果当前有事务,就在事务中执行,如果当前没有事务,就在非事务中运行。
- MANDATRY:必须在事务内部执行,如果当前有事务,就在事务中执行,如果没有事务,报错。
- REQUIRES_NEW:必须在事务中执行,如果当前没有事务,新建事务,如果当前有事务,把当前事务挂起。
- NOT_SUPPORTED:必须在非事务下执行,如果当前没有事务,正常执行,如果当前有事务,把当前事务挂起。
- NEVER:必须在非事务状态下执行,如果当前没有事务,正常执行,如果当前有事务,报错。
- NESTED:必须在事务状态下执行,如果没有事务,新建事务,如果当前有事务,创建一个嵌套事务
- isolation=“”事务隔离级别
- 在多线程或并发访问下如何保证访问到的数据具有完整性的。
- 脏读:
- 一个事务(A)读取到另一个事务(B)中未提交的数据,另一个事务数据可能进行了改变,此时事务(A)读取的数据可能和数据库中数据是不一致的,此时认为数据是脏数据,读取数据过程叫做脏读。
- 不可重复读:
- 主要针对的是某行数据(或行中某列)
- 主要针对的操作是修改操作
- 两次读取在同一个事务内
- 当事务A第一次读取书屋后,事务B对数据A读取的数据进行修改,事务A中再次读取的数据和之前读取的数据不一致,这个过程不可重复读
- 幻读:
- 主要针对的操作是新增或删除。
- 两次事务的结果。
- 事务A按照特定条件查询出结果,事务B新增了一条符合条件的数据,事务A中查询的数据和数据库中的数据不一致的,事务A好像出现了幻觉,这种情况称问幻读。
- DEFAULT:默认值,由底层数据库自动判断应该使用什么隔离级别
- READ_UNCOMMITTED:可以读取未提交的数据,可能出现脏读,不可重复读,幻读。
- 效率最高
- READ_COMMITTED:只能=读取其他事物已提交数据,可以防止脏读,可能出现不可重复读和幻读。
- REPEATABLE_READ:读取的数据被添加锁,防止其他事物修改此数据,可以防止不可重复读,脏读,可能出现幻读。
- SERIALIZABLE:排队操作,对整个表添加锁,一个事务在操作数时,另一个事务等待事务操作完成才能操作这个表。
- 最安全的。
- 效率最低的。
- rollback-for=“异常类型全限定路径”
- 当出现什么异常时需要进行回滚。
- 建议:给定该属性值
- 手动抛异常一定要给该属性值
- no-rollback-for=“”
- 当出现什么异常时不滚回事务。
spring中常用注解
- @component创建类对象,相当于配置
- @service 与@component功能相同。
- 写在servicelmpl类上。
- @Repository与@component功能相同
- 写在数据访问层类上。
- @controller与@component功能相同
- 写在控制器类上。
- @resource(不需要写对象的get/set)
- Java中的注解
- 默认按照byname注入,如果没有名称对象,按照bytype注入
- 建议把对象名称和spring容器中对象名相同。
- @Autowired(不需要写对象的get/set)
- spring的注解
- 默认按照bytype注入
- @value()获取properties文件中内容
- @pointcut()定义切点
- @aspect()定义切面类
- @before()前置通知
- @after()后置通知
- @afterReturning()后置通知,必须切点正常执行
- @afterthrowing()异常通知
- @arround()环绕通知