一、AOP简介
1.1概念:
AOP:Aspect Oriented Programming面向切面编程,是OOP面向对象编程的一种补充。将程序中交叉业务逻辑(事务、日志)代码提取出来,封装成切面,由AOP容器在适当时机(位置)将封装的切面动态的织入到具体业务逻辑中。但需要注意的是:AOP不是Spring特有的。
1.2 应用场合
适用于具有横切逻辑的场合,如事务管理、日志记录、性能监测、异常通知、访问控制等
1.3 作用
1.不改变原有代码的基础上动态添加新的功能
2.模块化
1.3 术语
连接点 Joinpoint:程序执行的某个特定位置,如方法调用前、方法调用后、方法抛出异常时、方法调用前后等;
切入点 Pointcut:定位查找到需要的连接点,即切点;
增强 Advice:也称为通知,在切点上执行的一段程序代码,用来实现某些功能;
目标对象 Target :将执行增强处理的目标类(这个地方可以理解为被代理类,因为被代理对象执行增强后,就会产生个一代理Proxy,所以这个目标对象可以理解为被代理对象);
织入 Weaving:将增强添加到目标类具体切入点上的过程;
代理 Proxy:一个类被织入增强后,会产生一个代理类;
切面 Aspect:切点和增强的组合;
引介 Introduction: 也称为引入
二、实现原理
2.1 回顾:代理模式
概念:为其他对象提供一种代理,以控制对这个对象的访问,起到中介的作用 通过代理对象访问目标对象,可以增强额外的操作,扩展目标对象的功能。
2.2 分类:
静态代理:1.代理类是程序员创建或工具生成;2.所谓静态就是程序运行之前就已经存在代理类的字节码文件;基主要的缺点是:代理对象需要和目标对象实现相同的接口,如果接口增加方法,目标对象和代理对象都要维护
动态代理:代理类是程序在运行期间由JVM根据反射等机制动态生成的,自动生成代理类和代理对象;所谓动态就是指在程序运行前不存在代理类的字节码文件
三、切面编程代码理解:
下面的代码是代理的具体代码,是在静态代理的基础上,把需要交叉的代码(如日志,事务等)增强到切片上,然后将切片织入到具体类的切点上。
1.首先创建一个接口,并实现这个接口,实现的接口是被代理类。代码如下:
// TODO: 2021/6/24 一个接口
public interface AopNumInterFace {
int showAge();
}
2.接口的实现类,也是被代理对象的类
// TODO: 2021/6/24 接口的实现类
public class AopNumClass implements AopNumInterFace {
@Override
public int showAge() {
System.out.println("this is show Age");
return 10;
}
}
3.创建代理类(代理类把交叉的代码提取出来,统一放入到了一个方法中,可以把这个集中处理交叉业务逻辑的方法看成是一个切片)
/**
* ClassName: AopNumClassImpl;
* User: FWJWORK;
* PackageName: aop1.impl;
* Date:2021/6/24;
* Time:11:11;
* Descritpion: 这是一个代理类,实现接口AopNumInterFace,在这里主要是交叉的代码集中放在一个方法当中
* 其主要作用是,当交叉代码需要侯改的时候,只需要在集中的方法中修改即可。使代码变得更简洁!
*/
public class AopNumClassImpl implements AopNumInterFace {
// TODO: 2021/6/24 下面的对象是被代理类对象,他和代理类对象必须实现同一个对象
private AopNumClass aopNumClass = new AopNumClass();
@Override
// TODO: 2021/6/24 重写接口的方法
public int showAge() {
try {
Method showAge = aopNumClass.getClass().getMethod("showAge");
Integer invoke = (Integer) invoke(showAge);
return invoke;
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return 0;
}
// TODO: 2021/6/24 学习的核心,所有交叉的内容可以集中在这在这个方法当中,此方法采用了反射,得到实现类的结构信息的方法结构,再对
// TODO: 2021/6/24 被代理对象进行驱动
public Object invoke(Method method, Object... args) {
System.out.println(method.getName() + ",start at:[" + new Date().getTime() + "]");
try {
Object invoke = method.invoke(aopNumClass, args);
return invoke;
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
}
4.通过代理类来执行被代理类
@Test
public void test40() {
// TODO: 2021/6/24 实例化一个代理类
AopNumClassImpl aopNumClass = new AopNumClassImpl();
// TODO: 2021/6/24 执行代理类中的方法,通过执行方法,被代理类中实现接口方法被驱动
int i = aopNumClass.showAge();
// TODO: 2021/6/24 被代理类通过反射的方法得到结果值
System.out.println(i);
}
三、总结
此节的学习,主要对AOP(面向切面)有个初步的了解,可以将交叉业务逻辑的代码统一集中管理,通过对目标对象(被代理对象)执行增强后,产生一个代理对象(Proxy),执行增强后的被代理对象,会使代理对象中增加一个切片(用于集中管理交叉业务逻辑的代码),通过织入让被代理对象更加完善业务逻辑。