AOP原理和事务
- AOP
- AOP底层原理
- 比如下面的代码案例手动模拟AOP
- 动态代理详解
- JDK动态代理
- 具体实现
AOP
AOP底层原理
当实现了AOP,Spring会根据当前的bean创建动态代理(运行时生成一个代理类)
面试题:为什么执行方法的时候,会执行切面里的通知方法?
比如下面的代码案例手动模拟AOP
- 模拟切面类
@Component
public class LogAspect {public void logBefore() {System.out.println("aop前置通知");}public void logAfter(){System.out.println("aop后置通知");}public void logReturn(){System.out.println("aop返回通知");}public void logThrowting(){System.out.println("aop异常通知");}}
- 动态代理类
@Component
public class ProxyUserService extends UserService {@Autowiredprivate LogAspect logAspect;@Overridepublic String add() throws InterruptedException {String result = null;try {//调用切面类-前置通知logAspect.logBefore();//调用目标方法result = super.add();//调用切面类返回通知logAspect.logReturn();} catch (Exception e) {//调用切面类-异常通知logAspect.logThrowting();e.printStackTrace();} finally {//调用切面类-后置通知logAspect.logAfter();}return result;}
}
为什么断点可以进入切面类中的通知方法中?
从上述代码中可以看到,在AOP动态代理中,在Spring代理类中,帮我们调用了切面中的前置通知,后置通知、返回通知、异常通知这些通知方法,所以断点可以进入。
动态代理详解
- jdk动态代理
- cglib动态代理
JDK动态代理
JDK动态代理是基于接口的
- 核心代码
第一个参数:类加载器
第二个参数:需要代理的接口
第三个参数:InvocationHandler(调用程序处理器,必须重写invoke方法)
Proxy.newProxyInstance(TestJdkProxy.class.getClassLoader(),UserService.class.getInterfaces(),new MyHandler(new UserService()));
具体实现
- 接口
public interface IUserService {void add();
}
- 实现类
public class UserService implements IUserService{@Overridepublic void add() {System.out.println("添加用户");}
}
- 自定义一个InvocationHandler(目的是优化代码降低耦合,提高代码维护性)
public class MyHandler implements InvocationHandler {Object target;public MyHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("执行前置通知");//执行目标方法Object returnValue = method.invoke(target, args);System.out.println("执行后置通知");return returnValue;}
}
- 测试
@Component
public class TestJdkProxy{public void test(){IUserService instance = (IUserService) Proxy.newProxyInstance(TestJdkProxy.class.getClassLoader(),UserService.class.getInterfaces(),new MyHandler(new UserService()));instance.add();}
}