Spring AOP + transaction
spring aop的底层原理就是动态代理。
spring transaction依靠于aop
弥补基础知识
静态代理and JDK动态代理
cglib代理
spring aop所使用的代理为jdk动态代理或cglib动态代理,如果不使用spring aop的话(手写aop ),可以考虑:当使用单例时尽量使用cglib动态代理(创建对象时效率低但运行效率高),相反,当使用多例时尽量使用jdk动态代理(创建对象时效率高但运行效率低)。
实现AOP的几种方法
- 徒手写(静态代理、jdk动态代理、cglib动态代理)
- xml配置文件实现(spring自动在jdk动态代理和cglib动态代理之间切换)
- 注解@Aspect实现(spring自动在jdk动态代理和cglib动态代理之间切换)
spring aop思想
切面内(代理类)包含切点(匹配)和增强(方法)。
编写步骤(注解版)
1、引入aop命名空间
xmlns:context=“http://www.springframework.org/schema/context”
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
2、开启aop注解 <aop:aspectj-autoproxy />
3、创建切面(加注解@Aspect)
4、编写增强(函数)
5、编写切点 (哪些业务方法使用函数)
@Pointcut(“execution(* cn.itcast.e_aop_anno…(…))”) 指定切入点表达式
@Before(“pointCut_()”) 前置通知: 目标方法之前执行
@After(“pointCut_()”) 后置通知:目标方法之后执行(始终执行)
@AfterReturning(“pointCut_()”) 返回后通知: 执行方法结束前执行(异常不执行)
@AfterThrowing(“pointCut_()”) 异常通知: 出现异常时候执行
@Around(“pointCut_()”) 环绕通知: 环绕目标方法执行
示例
@Component
@Aspect//指定为切面类
public class AOP {
// 指定切入点表达式,拦截哪个类的哪些方法
@Pointcut("execution(* aa.*.*(..))")
public void pt() {
}
@Before("pt()")
public void begin() {
System.out.println("开始事务");
}
@After("pt()")
public void close() {
System.out.println("关闭事务");
}
}
切点详解啊!
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern) throws-pattern?)
?号代表0或1,可以不写
“*”号代表任意类型,0或多
方法参数为…表示为可变参数
示例
<!-- 【拦截所有public方法】 -->
<!--<aop:pointcut expression="execution(public * *(..))" id="pt"/>-->
<!-- 【拦截所有save开头的方法 】 -->
<!--<aop:pointcut expression="execution(* save*(..))" id="pt"/>-->
<!-- 【拦截指定类的指定方法, 拦截时候一定要定位到方法】 -->
<!--<aop:pointcut expression="execution(public * cn.itcast.g_pointcut.OrderDao.save(..))" id="pt"/>-->
<!-- 【拦截指定类的所有方法】 -->
<!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.*(..))" id="pt"/>-->
<!-- 【拦截指定包,以及其自包下所有类的所有方法】 -->
<!--<aop:pointcut expression="execution(* cn..*.*(..))" id="pt"/>-->
<!-- 【多个表达式】 -->
<!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) || execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
<!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) or execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
<!-- 下面2个且关系的,没有意义 -->
<!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) && execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
<!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) and execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
<!-- 【取非值】 -->
<!--<aop:pointcut expression="!execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
编写步骤(xml版)
1、引入aop命名空间
xmlns:context=“http://www.springframework.org/schema/context”
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
2、配置aop(切面、切点和增强)
示例
<!--切面类-->
<bean id="aop" class="aa.AOP"/>
<!--AOP配置-->
<aop:config >
<!--定义切入表达式,拦截哪些方法-->
<aop:pointcut id="pointCut" expression="execution(* aa.*.*(..))"/>
<!--指定切面类是哪个-->
<aop:aspect ref="aop">
<!--指定来拦截的时候执行切面类的哪些方法-->
<aop:before method="begin" pointcut-ref="pointCut"/>
<aop:after method="close" pointcut-ref="pointCut"/>
</aop:aspect>
</aop:config>
spring transaction
spring事务分为编码式(与业务代码依偎在一起)和声明式(基于aop)。
声明式也包括注解方式和xml配置方式
注解@Transactional
1、开启事务注解驱动 <tx:annotation-driven />
2、配置事务控制的数据源
3、添加@Transactional到特定的方法或类上
@Transactional注解的属性列举啊!
属性名 | 说明 |
---|---|
name | 当在配置文件中有多个 TransactionManager , 可以用该属性指定选择哪个事务管理器。 |
propagation | 事务的传播行为,默认值为 REQUIRED。 |
isolation | 事务的隔离度,默认值采用 DEFAULT。 |
timeout | 事务的超时时间,默认值为-1。如果超过该时间限制但事务还没有完成,则自动回滚事务。 |
read-only | 指定事务是否为只读事务,默认值为 false;为了忽略那些不需要事务的方法,比如读取数据,可以设置 read-only 为 true。 |
rollback-for | 用于指定能够触发事务回滚的异常类型,如果有多个异常类型需要指定,各类型之间可以通过逗号分隔。 |
no-rollback- for | 抛出 no-rollback-for 指定的异常类型,不回滚事务。 |
propagation配置的是一个事务的传播性问题,所谓事物传播性就是被调用者的事务与调用者的事务之间的关系
propagation有那些配置项罗列出来啊!
示例
<tx:annotation-driven />
<bean id="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
那就关注这一点吧
Spring事务管理器的接口是org.springframework.transaction.PlatformTransactionManager,通过这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,但是具体的实现就是各个平台自己的事情了。
不同的事务管理器管理不同的数据资源DataSource
help列举一下哈:
DataSourceTransactionManager --> JDBC
HibernateTransactionManager --> Hibernate
JpaTransactionManager --> JPA
JtaTransactionManager --> 原生API事务