什么是AOP
aop:Aspect oriented Programming 面向切面编程,区别于我们熟知的oop面向对象,aop是对于oop的一种补充。oop是一种垂直的继承关系,子类继承父类,可以避免大多数的重复代码,但是有一些重复代码的问题,无法通过继承解决,比如说A类是父类,B、C是子类,A类已有的方法,B、C不需要重复去实现,但是如果A里的不同方法里面有重复代码,该如何解决呢?
比如:在A类中有aA和aB两个方法,aA中有一个System.currentTimeMillis()记录方法执行性能的代码,aB也有一个这样的代码,这显然不能通过继承解决,这个时候就要用到AOP了。
AOP就是为了解决这类问题而诞生的
实现原理
动态代理
自定义实现AOP
利用上一篇博客提到的转账demo基础上,通过aop框架实现事务控制
TransationManager 事务控制管理器
public class TransationManager {
// ioc 反射注入set方法,实例化ConnectionUtils
ConnectionUtils connectionUtils;
public void setConnectionUtils(ConnectionUtils connectionUtils){
this.connectionUtils=connectionUtils;
}
// 开启手动提交事务
public void beginTransation() throws SQLException {
connectionUtils.getCurrentConnection().setAutoCommit(false);
}
// 提交事务
public void commitTransation() throws SQLException {
connectionUtils.getCurrentConnection().commit();
}
// 回滚事务
public void rollbackTransation() throws SQLException {
connectionUtils.getCurrentConnection().rollback();
}
}
ProxyFactory 动态代理工厂
动态代理的实现有两种一种是JDKproxy一种是CGLIB,此处以jdkproxy为例
public class ProxyFactory {
TransationManager transationManager;
public void setTransationManager(TransationManager transationManager){
this.transationManager=transationManager;
};
public Object getJDKProxy(Object object){
// 创建动态代理对象
return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
try{
// 打印被代理的对象
System.out.println(object.getClass());
// 打印被代理对象的执行方法
System.out.println(method.getName());
// 答应被代理对象的方法参数
for (int i = 0; i <objects.length; i++) {
System.out.println(objects[i].toString());
}
// 开启手动提交事务
transationManager.beginTransation();
// 执行方法
Object invoke = method.invoke(object, objects);
// 提交事务
transationManager.commitTransation();
return invoke;
}catch (Exception e){
// 回滚事务
System.out.println("执行回滚");
transationManager.rollbackTransation();
return null;
}
}
});
}
}
Beans.xml
在上一版ioc基础上,添加上我们新的bean
<?xml version="1.0" encoding="UTF-8" ?>
<beans>
<!--动态代理-->
<bean id="proxyFactory" class="utils.ProxyFactory">
<property name="TransationManager" ref="transationManager"></property>
</bean>
<bean id="bankService" class="bank.service.impl.BankServiceImpl">
<property name="BankDao" ref="bankDao"></property>
</bean>
<!--事务控制-->
<bean id="transationManager" class="utils.TransationManager">
<property name="ConnectionUtils" ref="connectionUtils"></property>
</bean>
<bean id="bankDao" class="bank.dao.BankDao">
<property name="ConnectionUtils" ref="connectionUtils"></property>
</bean>
<bean id="connectionUtils" class="utils.ConnectionUtils"></bean>
</beans>
测试
为了检验我们的事务控制是否真的有效,在BankServiceImpl的转账方法里面添加一个错误代码,用来检验是否回滚
测试test方法
@Test
public void transationTest() throws SQLException {
ProxyFactory proxyFactory = (ProxyFactory) BeanFactory.getBean("proxyFactory");
BankService bankService = (BankService) BeanFactory.getBean("bankService");
BankService jdkProxy = (BankService) proxyFactory.getJDKProxy(bankService);
Boolean transfer = jdkProxy.transfer("6029621011001", "6029621011000", 100);
}
当前余额
执行结果f
余额
执行了回滚,且余额没有变化,没有发生一个变多,而另一个没有减少的情况,事务有效