SpringAOP扩展学习
一、利用AOP的思想管理JDBC事务
事务的本质:文件的备份
事务需要在业务层进行处理
1、案例:银行转账案例
- 要求:1、无报错的情况可以正常转账成功
2、 有错误的时候可以自动进行数据回滚,不写入到数据库中
包结构:
业务层接口:
public interface ServiceContoller {
void transfer() throws Exception;
}
业务层实现类:
/**
* @author Object(object_hui@sina.com)
* @description 转账业务层实现类
* @date 2020/12/22
*/
public class ServiceContollerImpl implements ServiceContoller {
private ServiceDao serviceDao = new ServiceDaoImpl();
@Override
public void transfer() throws Exception {
Connection con = ConnectionManger.getConnection();
serviceDao.transfer(con);
}
}
dao层接口:
public interface ServiceDao {
void transfer(Connection con) throws Exception;
}
dao层实现类:
/**
* @author Object(object_hui@sina.com)
* @description 转账Dao层实现类
* @date 2020/12/22
*/
public class ServiceDaoImpl implements ServiceDao {
@Override
public void transfer(Connection con) throws Exception {
//张三给李四转账200
String sql = "update account set money = money -200 where name = 'zhangsan'";
PreparedStatement ps = con.prepareStatement(sql);
ps.executeUpdate();
//手动写入错误,导致转账流程未进行完全
int a = 10/0;
sql = "update account set money = money +200 where name = 'lisi'";
ps = con.prepareStatement(sql);
ps.executeUpdate();
}
}
jdk动态代理类:
/**
* @author Object(object_hui@sina.com)
* @description jdbc动态代理
* @date 2020/12/22
*/
public class JdbcProxyTransfer implements InvocationHandler {
private Object target;
public JdbcProxyTransfer(Object target) {
this.target = target;
}
public Object getInstance(){
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Connection con = null;
try{
con = ConnectionManger.getConnection();
//设置connection不自动提交事务
con.setAutoCommit(false);
//调用目标方法
method.invoke(target,args);
//不报错就进行事务提交
con.commit();
}catch (Exception e){
e.printStackTrace();
//报错就回滚connection事务
con.rollback();
}
return null;
}
}
工具类:
/**
* @author Object(object_hui@sina.com)
* @description jdbc工具类
* @date 2020/12/22
*/
public class JDBCUtil {
public static final String url = "jdbc:mysql://localhost:3306/yx2006";
private static final String user = "root";
private static final String pwd = "111";
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection getConnection(){
Connection conn = null;
try {
conn = DriverManager.getConnection(url,user,pwd);
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
}
/**
* @author Object(object_hui@sina.com)
* @description connection管理类
* @date 2020/12/22
*/
public class ConnectionManger {
//使用单例设计模式,保证拿到的Connection对象为同一个
private static Connection con = JDBCUtil.getConnection();
private ConnectionManger(){}
public static Connection getConnection(){
return con;
}
}
测试类:
/**
* @author Object(object_hui@sina.com)
* @description 测试类
* @date 2020/12/22
*/
public class Test {
public static void main(String[] args) throws Exception {
JdbcProxyTransfer proxy = new JdbcProxyTransfer(new ServiceContollerImpl());
ServiceContoller serviceContoller = (ServiceContoller) proxy.getInstance();
serviceContoller.transfer();
}
}
2、SpringAOP的几个概念
- 目标对象(target): 被代理的对象
- 切面(Aspect):包含处理事务的类,这种类叫切面类
- 消息 (Advice): 切面类中需要执行的方法
- 连接点 (JoinPoint): 指的是被代理类中的所有方法
- 切点 (PointCut): 指的是被代理类中应用了消息的方法
- 织入(Weave):指的是把消息应用到切点的整个过程
使用xml进行aop配置
需要进行的配置信息:
1、目标对象信息
2、切面信息
3、消息信息
4、切点信息
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--目标类-->
<bean id="beiJing" class="springAop01.dynamicProxy.HeFei" />
<!--切面类-->
<bean id="security" class="springAop01.dynamicProxy.Security"/>
<!--AOP的配置-->
<aop:config>
<!--
切点:描述消息(Advice:方法上)应用在哪些方法上
expression:表达式
目的:就是为了通过表达式完成描述消息(Advice:方法上)应用在哪些方法上
execution:具体负责具体表达式的语法该怎么写
execution(找方法):
方法要素:
访问修饰符 public private
返回值类型
方法名:指定哪个类下的什么方法名
参数列表
new HeFei();
new com.bjpowernode.springAOP01.dynamicProxy.HeFei();
-->
<!--切点配置 expression表达式各种写法,用的时候直接上网搜索即可-->
<aop:pointcut id="pointCut"
expression="execution(public String springAop01.dynamicProxy.HeFei.sale(String))" />
<!--切面配置-->
<aop:aspect id="aspect" ref="security">
<!--消息配置-->
<aop:after method="security" pointcut-ref="pointCut" />
</aop:aspect>
</aop:config>
</beans>