Spring的AOP配置
- 事务控制
事务(Transaction),一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。
这里我们以取钱的例子来讲解:比如你去ATM机取1000块钱,大体有两个步骤:第一步输入密码金额,银行卡扣掉1000元钱;第二步从ATM出1000元钱。这两个步骤必须是要么都执行要么都不执行。如果银行卡扣除了1000块但是ATM出钱失败的话,你将会损失1000元;如果银行卡扣钱失败但是ATM却出了1000块,那么银行将损失1000元。
如何保证这两个步骤不会出现一个出现异常了,而另一个执行成功呢?事务就是用来解决这样的问题。事务是一系列的动作,它们综合在一起才是一个完整的工作单元,这些动作必须全部完成,如果有一个失败的话,那么事务就会回滚到最开始的状态,仿佛什么都没发生过一样。 在企业级应用程序开发中,事务管理是必不可少的技术,用来确保数据的完整性和一致性。
- 事务控制的方法
⑴使用ThreadLocal对象将Connection和当前线程绑定,从而使一个线程中只有一个能控制事务的对象。
- 动态代理
特点:字节码随用随创建,随用随加载。
作用:不修改源码的基础上,对方法增强。
⑴基于接口的动态代理
涉及的类:proxy
提供者:JDK官方
如何创建代理对象:
使用proxy类中的newproxyInstance方法
创建代理对象的要求:
被代理类最少实现一个接口,如果没有,则不能使用。
newproxyInstance方法的参数:
ClassLoader:类加载器
他是用于加载代理对象字节码的,写的是被代理对象的加载器,和被代理对象使用相同的类加载器。(固定写法)
Class[]:字节码数组
它是用于让代理对象和被代理对象有相同方法。(固定写法)
InvocationHandler:用于提供增强的代码
它是让我们写如何代理的。我们一般都是写一个该接口的实现类,通常都是匿名类,但不是必须的。
此接口的实现类都是谁用谁写。
⑵基于子类的动态代理
涉及的类:Enhancer
提供者:第三方cglib库
如何创建代理对象:
使用Enhancer类中的create方法
创建代理对象的要求:
被代理类不能是最终类
create方法的参数:
Class:字节码
用于指定被代理对象的字节码
Callback:用于提供增强的代码
它是让我们写如何代理的。我们一般都是写一个该接口的实现类,通常都是匿名类,但不是必须的。
此接口的实现类都是谁用谁写。
一般写的是该接口的子接口实现类:MethodInterceptor
- Aop的概念
面向切面编程(也叫面向方面编程):Aspect Oriented Programming(AOP),是软件开发中的一个热点,也是Spring框架中的一个重要内容。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
作用:在程序运行期间,不修改源代码对已有的方法进行增强
优势:减少重复代码,提高开发效率,方便维护
实现方式:动态代理的方式来实现。
Spring中的Aop:
⑴Aop的相关术语:
JoinPoint(连接点):指的是被增强类(业务层)的所有方法
Pointcut(切入点):业务层中被增强的方法也就是切入点
Advice(通知):拦截到JoinPoint之后需要做的事情就是通知,分为前置,后置,异常,最终,环绕通知
Introduction(引介):这是一种特殊的通知,Introduction可以在运行期间为类动态的添加一些方法或者是Field
Target(目标对象):被代理的对象
Weaving(织入):加入事务代理的过程,也就是织入
Proxy(代理):经过代理后产生的对象
Aspect(切面):切入点和通知的结合
Spring中Aop需要明确的东西:
a、开发阶段(我们程序员要做的):
⑴编写核心代码,开发的主线
⑵抽取公用代码,制作成通知。Aop编程人员的工作
⑶在配置文件,声明切入与通知间的关系,即配置切面。
- Spring中基于XML的声明式事务配置步骤
<!--spring中基于XML的声明式事务控制配置步骤
1.配置事务管理器
2.配置事务通知
此时需要导入事务的约束 tx的名称空间,同时需要aop
使用tx:advice标签配置事务通知
属性:
id:给事务起一个唯一标志
transaction-manager:给事务通知提示一个事务管理器引用
3.配置aop的通用切入点表达式
4.建立事务通知和切入点表达式的对应关系
5.配置事务的属性
在事务的通知标签内部(tx:advice)
-->
<!--1.配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--2.配置事务通知-->
<tx:advice id="txadvice" transaction-manager="transactionManager">
<!--5.配置事务属性
isolation:用于指定事务的隔离级别,默认值式DEFAULT,表示使用的是数据库的默认隔离级别
propagation:用于指定事务的传播行为,默认值是REQUIRED,表示一定会有事务,增删改的选择,查询方法可以选择SUPPORTS
read-only:用于指定事务是否只读,只有查询方法才能设置为true,默认值是false,表示读写.
timeout:用于指定事务的超时时间,默认值是-1,表示永不超时,如果设置了数值,以秒为单位
rollback-for:用于指定一个异常,当产生该异常时,事务回滚,产生其他异常时,事务不回滚 没有默认值,表示任何异常都回滚
no-rollback-for用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时,事务回滚 没有默认值,表示任何异常都回滚
-->
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" read-only="false" />
<tx:method name="find*" propagation="SUPPORTS" read-only="true"></tx:method>
</tx:attributes>
</tx:advice>
<!--配置aop-->
<aop:config>
<!--3.配置切入点表达式-->
<aop:pointcut id="pt1" expression="execution(* com.zyx.service.impl.*.*(..))"/>
<!--4.建立切入点表达和事务的关系-->
<aop:advisor advice-ref="txadvice" pointcut-ref="pt1"></aop:advisor>
</aop:config>
- Spring中基于注解的声明式事务控制
<!--spring基于注解的声明式事务控制步骤
1.配置事务管理器
2.开启spring对注解事务的支持
3.在需要事务支持的地方使用Transactional注解
-->
<!--1.配置事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--2.开启spring对注解事务的支持-->
<tx:annotation-driven transaction-manager="transactionManager">
</tx:annotation-driven>
<!--3.使用Transactional注解-->