1、AOP
1.1、什么是AOP
AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
AOP是OOP的延续,是软件开发中的一个热点,也是Sping框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
1.1.1、AOP的作用
作用:在程序运行期间,在不修改源码的情况下对方法进行功能增强。
优势:减少重复代码,提高开发效率,并且便于维护。
- 伴随着AOP时代的降临,可以从各个行业的标准化、规范化开始入手,一步一步将所有共性功能逐一开发完毕,最终以功能组合来完成个别业务模块乃至整体业务系统的开发
- 目标:将软件开发由手工制作走向半自动化/全自动化阶段,实现“插拔式组件体系结构”搭建
1.1.2、AOP优势
- 提高代码的可重用性
- 业务代码编码更简洁
- 业务代码维护更高效
- 业务功能扩展更便捷
1.1.3、AOP 的底层实现
实际上,AOP 的底层是通过 Spring 提供的的动态代理技术实现的。在运行期间,Spring通过动态代理技术动态的生成代理对象,代理对象方法执行时进行增强功能的介入,在去调用目标对象的方法,从而完成功能的增强。
1.1.4、 AOP 的动态代理技术
常用的动态代理技术
JDK 代理 : 基于接口的动态代理技术
cglib 代理:基于父类的动态代理技术
1.1.4.1、基于JDk实现动态代理
代码语言:javascript复制static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
//返回指定接口的代理类的实例,该接口将方法调用分派给指定的调用处理程序。
/**
newProxyInstance,方法有三个参数:
loader: 用哪个类加载器去加载代理对象
interfaces/:动态代理类需要实现的接口
h:动态代理方法在执行时,会调用h里面的invoke方法去执行
*/
/**
* ClassLoader loader 类加载器,用于加载代理对象的字节码
* Class<?>[] interfaces 字节码数组,用于让代理对象和被代理对象有相同的方法
* InvocationHandler h 处理方法,用于方法增强
*/
//2.invoke
Object invoke(Object proxy, 方法 method, Object[] args) //处理代理实例上的方法调用并返回结果。
/**
* Object proxy 被代理的类
* Method method 被代理类的方法
* Object[] args 方法参数
*/
①目标类接口
代码语言:javascript复制public interface TargetInterface {
public void method();
}
②目标类
代码语言:javascript复制public class Target implements TargetInterface {
@Override
public void method() {
System.out.println("Target running....");
}
}
③动态代理代码
代码语言:javascript复制Target target = new Target(); //创建目标对象
//创建代理对象
TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(target.getClass()
.getClassLoader(),target.getClass().getInterfaces(),new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("前置增强代码...");
Object invoke = method.invoke(target, args);
System.out.println("后置增强代码...");
return invoke;
}
}
);
④ 调用代理对象的方法测试
代码语言:javascript复制// 测试,当调用接口的任何方法时,代理对象的代码都无序修改
proxy.method();
1.1.4.2、cglib 的动态代理
①目标类
代码语言:javascript复制public class Target {
public void method() {
System.out.println("Target running....");
}
}
②动态代理代码
代码语言:javascript复制Target target = new Target(); //创建目标对象
Enhancer enhancer = new Enhancer(); //创建增强器
enhancer.setSuperclass(Target.class); //设置父类
enhancer.setCallback(new MethodInterceptor() { //设置回调
@Override
public Object intercept(Object o, Method method, Object[] objects,
MethodProxy methodProxy) throws Throwable {
System.out.println("前置代码增强....");
Object invoke = method.invoke(target, objects);
System.out.println("后置代码增强....");
return invoke;
}
});
Target proxy = (Target) enhancer.create(); //创建代理对象
③调用代理对象的方法测试
代码语言:javascript复制//测试,当调用接口的任何方法时,代理对象的代码都无序修改
proxy.method();
1.1.4.3、AOP 相关概念
Spring 的 AOP 实现底层就是对上面的动态代理的代码进行了封装,封装后我们只需要对需要关注的部分进行代码编写,并通过配置的方式完成指定目标的方法增强。
在正式讲解 AOP 的操作之前,我们必须理解 AOP 的相关术语,常用的术语如下:
- Target(目标对象):代理的目标对象
- Proxy (代理):一个类被 AOP 织入增强后,就产生一个结果代理类
- Joinpoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点–>可以被拦截的方法
- Pointcut(切入点):所谓切入点是指我们要对哪些 Joinpoint 进行拦截的定义 ---->我们自己要拦截的方法
- Advice(通知/ 增强):所谓通知是指拦截到 Joinpoint 之后所要做的事情就是通知 -->拦截后进行的操作
- Aspect(切面):是切入点和通知(引介)的结合 —>拦截的方法与拦截后的操作的结合
- Weaving(织入):是指把增强应用到目标对象来创建新的代理对象的过程。spring采用动态代理织入,而AspectJ采用编译期织入和类装载期织入