一,Aop是什么
Aop是Spring框架的第二大核心(第一是ioc)。
Aop是一个面向切面编程。那什么是面相切片编程呢,也就是一类特定问题,就比如拦截器什么的就是一个切面,当然拦截器也是Aop思想的一种实现。简单说Aop也就是对某一类事情的集中处理。
1.1Aop的优势
1,不用修改源代码就可以进行功能增强或者改变。
2,减少了重复代码
3,提高开发效率
4,维护方便
二,Aop核心概念
切面:定义了横切关注点的行为和通知,也就是告诉程序哪里需要增强。(切点+通知)
切点:指定切面的应用范围,定义了那些连接点会被该切面所影响。
连接点:程序执行过程中的某个特定点,如方法调用和异常抛出。
通知:具体要做那些工作,也就是把共性功能体现为一个方法。
2.1通知类型
Spring中的Aop通知类型有以下几种:此类标注的通知方法在目标方法前后都被执行
• @Around:环绕通知,此类标注的通知方法在目标方法前后都被执行
• @Before:前置通知,此类标注的通知方法在目标方法前都被执行
• @After:后置通知,此类标注的通知方法在目标方法后都被执行,无论是否有异常都会执行
• @AfterReturning:返回后通知,此类标注的通知方法在目标方法前后都被执行,有异常不会执行
• @AfterThrowing:异常后通知,此注解标注的通知方法发生异常后执行
三,Aop原理
3.1代理模式
代理模式也就是提供了一个代理类,让我们在调用目标方法的时候,不在对目标方法直接调用,而是通过代理来间接调用。就比如艺人的经纪人一样的。
也主要分为两种:
静态代理:由程序员创建代理类或特定⼯具⾃动⽣成源代码再对其编译,在程序运⾏前代理类的 .class⽂件就已经存在了。
动态代理:在程序运行的时候,运用反射机制创建而成。
3.1.1静态代理
也就好比你去租房子这个房子的中介早就分好了一样。
流程也就是定义接口,好比定义中介要做的事情,
实现接口,也就是房东出租房子,
代理,中介帮忙买房子,
使用,也就是挂到租借中心
这样一看,这都是定的,如果想修改就很不方便,所以日常开发也见不到这种。
3.1.2动态代理
动态这时我们就不需要对每个目标创建一个单独的代理,而是推迟到程序运行时由jvm来实现。
房屋这边就比如你去了租房才给你分配中介,而不是这个房子必须那个中介。
动态代理这边常见的实现方式有两种:
JDK动态代理
CGLIB动态代理
这边主说CGLIB。因为JDK有一个致命问题就是只能代理实现了接口的类。
CGLIB动态实现步骤:
1. 定义⼀个类(被代理类)
2. ⾃定义MethodInterceptor 并重写intercept ⽅法, intercept ⽤于增强⽬标⽅法,和JDK动态代理中的invoke ⽅法类似
3. 通过Enhancer类的create()创建代理类
要注意的是这边使用CGLIB要添加依赖:
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
代码实现:⾃定义MethodInterceptor:方法拦截器
public class CGLIBInterceptor implements MethodInterceptor {
//⽬标对象, 即被代理对象
private Object target;
public CGLIBInterceptor(Object target){
this.target = target;
}
@Override
public Object intercept(Object o, Method method, Object[] objects,
MethodProxy methodProxy) throws Throwable {
// 代理增强内容
System.out.println("我是中介, 开始代理");
//通过反射调⽤被代理类的⽅法
Object retVal = methodProxy.invoke(target, objects);
//代理增强内容
System.out.println("我是中介, 代理结束");
return retVal;
}
}
创建代理类:
public class DynamicMain {
public static void main(String[] args) {
HouseSubject target= new RealHouseSubject();
HouseSubject proxy= (HouseSubject)
Enhancer.create(target.getClass(),new CGLIBInterceptor(target));
proxy.rentHouse();
}
}
解释一下这两个:
MethodInterceptor用于增强目标方法。
Enhancer.create()⽤来⽣成⼀个代理对象。