Aop之研究
1.AOP是什么?
- 面向切面编程
- 散布在在各个代码中,其实是针对同一个功能的代码就是切面。
- 就是不改变源代码,给程序添加功能。
- 典型的装饰者模式。给代码直接加外挂、
2.Aop的术语
- 连接点:执行过程中明确的点,一般是方法的调用。
- Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式
- Advice(增强):AOP在特定的切入点上执行的增强处理,有
- before(前置),
- after(后置),
- afterReturning(返回)
- ,afterThrowing(异常)
- around(环绕)
- weave(织入):将切面应用到目标对象并导致代理对象创建的过程
- Aspect(切面):通常是一个类,里面可以定义切入点和增强
- 目标对象(Target Object): 包含连接点的对象。也被称作被通知或被代理对象。POJO
3.Aop实现的原理
- 利用继承方式,在子类实现增强功能。
- 利用接口形式,使用代理方式实现增强功能。
- 静态代理
- 动态代理
- 动态代理是实现JDK里的InvocationHandler接口的invoke方法,但注意的是代理的是接口,也就是你的业务类必须要实现接口,通过Proxy里的newProxyInstance得到代理对象。
- 还有一种动态代理CGLIB,代理的是类,不需要业务类继承接口,通过派生的子类来实现代理。通过在运行时,动态修改字节码达到修改类的目的。
- 静态代理和动态代理的区别?
- 程序员创建或由特定工具自动生成源代码,编译过程。在程序运行前,代理类的.class文件就已经存在了。
- 动态代理类的字节码在程序运行时由Java反射机制动态生成
- 静态代理通常只代理一个类
- 静态代理事先知道要代理的是什么
- 动态代理是代理一个接口下的多个实现类
- 动态代理不知道要代理什么东西,只有在运行时才知道
4.Aop的应用,具体功能如下:
Authentication 权限
Caching 缓存
Context passing 内容传递
Error handling 错误处理
Lazy loading 延时加载
Debugging 调试
logging, tracing, profiling and monitoring 记录跟踪 优化 校准
Performance optimization 性能优化
Persistence 持久化
Resource pooling 资源池
Synchronization 同步
Transactions 事务
5.Spring 利用aop管理数据库事务
- 事务的边界在哪里?(以登录操作为例)
- 在Service方法,一开始打开数据库事务
- Service方法执行成功,提交数据事务
- 中间出现异常,回滚数据库事务
- 典型的aop的环绕增强
Spring中常用事务的传播机制(事务类型):
-
所谓事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。
-
在TransactionDefinition定义中包括了如下几个表示传播行为的常量:
TransactionDefinition.PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。
TransactionDefinition.PROPAGATION_REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。
TransactionDefinition.PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。TransactionDefinition.PROPAGATION_NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。
Spring中常用事务的隔离级别:
-
ISOLATION_DEFAULT:用底层数据库的默认隔离级别,数据库管理员设置什么就是什么
-
ISOLATION_READ_UNCOMMITTED(未提交读):最低隔离级别、事务未提交前,就可被其他事务读取(会出现幻读、脏读、不可重复读)
-
ISOLATION_READ_COMMITTED(提交读):一个事务提交后才能被其他事务读取到(该隔离级别禁止其他事务读取到未提交事务的数据、所以还是会造成幻读、不可重复读)、sql server默认级别
-
ISOLATION_REPEATABLE_READ(可重复读):可重复读,保证多次读取同一个数据时,其值都和事务开始时候的内容是一致,禁止读取到别的事务未提交的数据(该隔离基本可防止脏读,不可重复读(重点在修改),但会出现幻读(重点在增加与删除))(MySql默认级别,更改可通过set transaction isolation level 级别)
-
ISOLATION_SERIALIZABLE(序列化):代价最高最可靠的隔离级别(该隔离级别能防止脏读、不可重复读、幻读)
- 丢失更新:两个事务同时更新一行数据,最后一个事务的更新会覆盖掉第一个事务的更新,从而导致第一个事务更新的数据丢失,这是由于没有加锁造成的;
- 幻读:同样的事务操作过程中,不同时间段多次(不同事务)读取同一数据,读取到的内容不一致(一般是行数变多或变少)。
- 脏读:一个事务读取到另外一个未提及事务的内容,即为脏读。
- 不可重复读:同一事务中,多次读取内容不一致(一般行数不变,而内容变了)。
幻读与不可重复读的区别:幻读的重点在于插入与删除,即第二次查询会发现比第一次查询数据变少或者变多了,以至于给人一种幻象一样,而不可重复读重点在于修改,即第二次查询会发现查询结果比第一次查询结果不一致,即第一次结果已经不可重现了。
数据库隔离级别越高,执行代价越高,并发执行能力越差,因此在实际项目开发使用时要综合考虑,为了考虑并发性能一般使用提交读隔离级别,它能避免丢失更新和脏读,尽管不可重复读和幻读不能避免,但可以在可能出现的场合使用悲观锁或乐观锁来解决这些问题。