Spring-AOP
1.AOP简介
AOP:全称:Aspect Oreinted Programming:面向切面编程
OOP:全称:Object Oreinted Programming:面向对象编程
1.1 简述
AOP含义:全称:Aspect Oreinted Programming:面向切面编程,AOP和OOP不存在谁取代谁的情况, 他们之间是相互补充,相互促进的,Aop是在不改变原有OOP类代码的前提下,对原来类的功 能进行拓展。
AOP作用:AOP作用:解决了软件工程中提出的关注点分离问题,让系统的架构变得高内聚低耦合。
AOP底层原理:动态代理(jdk动态代理和CGLib动态代理)
AOP应用:声明式事务、通用缓存、通用日志、全局异常处理。
1.2 AOP中涉及到的几个概念
通知(advice):拓展的功能称之为通知[本质:方法]
切面(aspect):通知所在的类,称之为切面[本质:类]
切入点(PointCut):用来确定对谁进行拓展的[本质:表达式]
连接点(JoinPoint):通知和目标方法的交点称之为连接点
目标对象(Tartget):目标方法所在的类的对象
织入(weaving):将通知应用到目标方法的过程,称之为织入
1.3 图解AOP的几个概念
1.4 图解AOP的底层原理
2.代理
2.1静态代理
静态代理:是指只能代理某一个接口的类对象
Payment 接口:
public interface Payment {
public void pay(double money);
}
RealPayment 实现类:
public class RealPayment implements Payment {
@Override
public void pay(double money) {
System.out.println("作为真实用户,我们只关注付了"+money);
}
}
AliPay 代理类:
public class AliPay implements Payment {
private Payment payment;
public AliPay(Payment payment) {
this.payment=payment;
}
public void beforePay() {
System.out.println("支付宝把钱从银行取出来");
}
@Override
public void pay(double money) {
beforePay();
this.payment.pay(money);
afterPay();
}
public void afterPay() {
System.out.println("支付宝把钱支付给商家");
}
}
测试代码:
@Test
public void testPay(){
AliPay aliPay = new AliPay(new RealPayment());
aliPay.pay(30);
}
2.2 动态代理
动态代理:可以代理任意接口的类对象
public class AppTest {
@Test
public void testDynamicProxy(){
/************************************************************
1.Proxy.newProxyInstance方法可以创建任意接口的代理类对象
参数:
第一个参数:被代理类的类加载器
第二个参数:被代理类的实现的接口
第三个参数: InvocationHandler接口的实现类对象,在InvocationHandler接口的实现类我们可以对被代理类
进行拓展
返回值:代理类对象
************************************************************/
// RealPayment realPayment = new RealPayment();
WeiPayImpl weiPay=new WeiPayImpl();
//代理类对象
WeiPay o = (WeiPay)Proxy.newProxyInstance(weiPay.getClass().getClassLoader(), weiPay.getClass().getInterfaces(), new MyInvocationHandler(weiPay));
o.pay(40.3);
}
@Test
public void testPay(){
AliPay aliPay = new AliPay(new RealPayment());
aliPay.pay(30);
}
}
InvocationHandler 接口实现类:
public class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler(Object target) {
this.target=target;
}
/************************************************************
method:被代理类的方法
args:调用被代理类方法的时候传递的参数
proxy:不适用,不用管。
************************************************************/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("动态代理把钱从银行取出来......");
//调用被代理的方法
Object result = method.invoke(target, args);
System.out.println("动态代理把钱付给商家......");
return result;
}
}
2.3 静态代理和动态代理的区别
相同点:
第一点:都是在不改变原有类代码的基础之上对被代理类进行拓展
第二点:都需要实现接口,都要求被代理类和代理类实现相同接口
不同点:
静态代理只能代理某一个接口的类对象,动态代理可以代理任意接口的类对象
3.切面中的五种通知
前置通知[@Before]:在目标方法执行之前执行
后置通知[@After]:无论目标方法有没有执行成功,后置通知都会执行
返回通知[@AfterReturning]:在目标方法之后,只有目标方法执行成功的情况下,返回通 知才执行
异常通知[@AfterThrowing]:在目标方法之后,只有目标方法执行出现异常的情况下,异常 通知才执行 环绕通知[@Around]:以一抵四
4.通知的底层结构
try{
try{
//前置通知
//调用目标方法
}finally {
//后置通知
}
//返回通知
}catch (){
//异常通知
}
5.切入点表达式
作用:在切面中用来定位对谁进行拓展的
语法:
execution([权限修饰符] [返回值类型] [简单类名/全类名] 方法名)
最简洁[最模糊]:
execution(* .(…))
最复杂[最精确]:
execution(public int com.atguigu.aop.CaculatorImpl.add(int,int))
切入点表达式重用: