首页 > 其他分享 >Spring AOP概念及原理

Spring AOP概念及原理

时间:2024-07-30 20:39:52浏览次数:7  
标签:Spring Object 代理 public AOP 原理 method

Spring AOP(面向切面编程)

以下内容由ChatGPT生成

AOP(Aspect-Oriented Programming,面向切面编程)是一种编程范式,旨在通过分离关注点来提高程序的模块化。Spring AOP 主要用于横切关注点(如日志记录、安全、事务管理等)的实现。在 Spring 中,AOP 的主要功能是为 Bean 增强功能,如添加额外的行为。

1. 静态代理与动态代理

静态代理动态代理是实现 AOP 的两种主要方式。

静态代理

  • 在编译时就已经知道代理的目标类,代理类在代码中显式地定义。
  • 静态代理的缺点是需要为每个代理的类手动编写代理类,导致代码冗余且难以维护。

动态代理

  • 动态代理是在运行时生成代理类的,Java 中有两种实现动态代理的方式:JDK 动态代理CGLIB
  • 动态代理的优点是可以为任意接口生成代理,不需要手动编写代理类。
JDK 动态代理
  • JDK 动态代理只代理实现了接口的类。它通过 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口实现。
  • InvocationHandler 接口中定义了 invoke 方法,当代理对象调用方法时,会执行该方法。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class JdkProxyExample {
public static void main(String[] args) {
Foo foo = new FooImpl();
Foo proxyFoo = (Foo) Proxy.newProxyInstance(
Foo.class.getClassLoader(),
new Class<?>[]{Foo.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 前置增强
System.out.println("Before method: " + method.getName());
Object result = method.invoke(foo, args);
// 后置增强
System.out.println("After method: " + method.getName());
return result;
}
});
proxyFoo.doSomething();
}
}

interface Foo {
void doSomething();
}

class FooImpl implements Foo {
public void doSomething() {
System.out.println("Doing something...");
}
}
CGLIB 动态代理
  • CGLIB 动态代理通过生成目标类的子类来实现代理,因此可以代理没有接口的类。CGLIB 使用 ASM 字节码操作库来生成代理类。
  • CGLIB 的代理类重写目标类的方法,通过调用父类的 super 方法来实现对目标方法的调用。
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class CglibProxyExample {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Foo.class);
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
// 前置增强
System.out.println("Before method: " + method.getName());
Object result = proxy.invokeSuper(obj, args);
// 后置增强
System.out.println("After method: " + method.getName());
return result;
}
});
Foo fooProxy = (Foo) enhancer.create();
fooProxy.doSomething();
}
}

class Foo {
public void doSomething() {
System.out.println("Doing something...");
}
}

2. Spring AOP 实现原理

Spring AOP 支持 JDK 动态代理CGLIB 两种代理机制。

  • JDK 动态代理:当目标类实现了一个或多个接口时,Spring 默认使用 JDK 动态代理来为目标类创建代理对象。
  • CGLIB:如果目标类没有实现任何接口,Spring 则会使用 CGLIB 来生成目标类的代理对象。

Spring 使用 AopProxy 接口和其两个实现类 JdkDynamicAopProxyCglibAopProxy 来分别处理这两种代理机制。

Bean 被包装成 Proxy
  1. Spring 容器启动时,解析配置文件或注解,生成 Bean 定义信息。
  2. 在 Bean 初始化后,Spring AOP 的 BeanPostProcessor 之一(如 AbstractAutoProxyCreator 的子类)会检查该 Bean 是否需要 AOP 增强。
  3. 如果需要增强,则会生成一个代理对象,替换掉原始的 Bean。这一过程是通过调用 getProxy() 方法来完成的。
创建 Proxy 对象

AopProxy 接口定义了 getProxy() 方法:

  • JdkDynamicAopProxy:通过 JDK 动态代理的 Proxy.newProxyInstance() 方法创建代理对象。
  • CglibAopProxy:通过 CGLIB 的 Enhancer 类创建代理对象。
获取代理对象

getProxy() 方法返回代理对象。代理对象的创建是在调用 getProxy() 方法时动态生成的,并且在这个方法中处理了所有的 AOP 增强逻辑。

InvocationHandler 的实现

在 JDK 动态代理中,InvocationHandlerinvoke() 方法包含了拦截器链的逻辑。CglibAopProxy 通过 CallbackMethodInterceptor 实现类似的功能。

public class MyInvocationHandler implements InvocationHandler {
private final Object target;

public MyInvocationHandler(Object target) {
this.target = target;
}

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 前置处理
System.out.println("Before method: " + method.getName());

// 调用目标对象的方法
Object result = method.invoke(target, args);

// 后置处理
System.out.println("After method: " + method.getName());

return result;
}
}

invoke() 方法中:

  1. 执行前置增强逻辑。
  2. 使用反射调用目标对象的方法。
  3. 执行后置增强逻辑。

3. 拦截器链与方法链的执行

Spring AOP 中的拦截器链是由 AdvisorMethodInterceptor 组成的。Advisor 包含切点(Pointcut)和通知(Advice),切点定义了哪些方法需要拦截,通知则定义了拦截时执行的逻辑。

在代理对象调用方法时:

  1. AopProxy 调用链会依次调用拦截器链中的拦截器。
  2. 拦截器链通过责任链模式处理每一个拦截器。
  3. 如果拦截器链中的某个拦截器决定执行目标方法,则会调用 MethodInvocation.proceed() 方法。
public class MyMethodInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
// 前置处理
System.out.println("Before method: " + invocation.getMethod().getName());

// 调用目标对象的方法
Object result = invocation.proceed();

// 后置处理
System.out.println("After method: " + invocation.getMethod().getName());

return result;
}
}

invoke() 方法中,proceed() 方法用于继续执行下一个拦截器或目标方法。如果没有其他拦截器,则执行目标方法。

总结

Spring AOP 使用代理模式实现横切关注点的管理,主要通过 JDK 动态代理和 CGLIB 动态代理实现。代理对象是通过 AopProxy 创建的,其中的 InvocationHandlerMethodInterceptor 负责执行拦截器链的逻辑。Spring AOP 提供了强大的功能来增强 Bean 的行为,使得切面逻辑与核心业务逻辑分离,提升了代码的模块化和可维护性。

标签:Spring,Object,代理,public,AOP,原理,method
From: https://www.cnblogs.com/Si-wuxie/p/18333322

相关文章

  • 窥探职业潜力的钥匙:霍兰德职业兴趣测试的10个核心原理
    简介霍兰德职业兴趣自测(Self-DirectedSearch)是由美国职业指导专家霍兰德(JohnHolland)根据他本人大量的职业咨询经验及其职业类型理论编制的测评工具。霍兰德认为,个人职业兴趣特性与职业之间应有一种内在的对应关系。根据兴趣的不同,人格可分为研究型(I)、艺术型(A)、社会型(S)、企......
  • springboot+vue基于微服务架构的设备管理系统【程序+论文+开题】-计算机毕业设计
    系统程序文件列表开题报告内容研究背景随着企业规模的不断扩大与信息化程度的日益加深,设备管理成为企业运营中不可或缺的一环。传统集中式架构的设备管理系统在面对大规模数据处理、高并发访问及系统扩展性等方面显得力不从心。微服务架构以其高度的模块化、灵活的服务部署......
  • Java跨平台原理
    Java跨平台原理Java是解释执行的,编译为中间码的编译器与平台无关,编译生成的中间码也与平台无关(一次编译,到处运行),中间码再由解释器解释执行,解释器是与平台相关的,也就是不同的平台需要不同的解释器.由源文件(.java)--->字节码文件(.class)(二进制文件)----->解释---->Unix,Win,Li......
  • 基于SpringBoot+Vue的电影院订票信息管理系统的详细设计和实现(源码+lw+部署文档+讲解
    文章目录前言详细视频演示项目运行截图技术框架后端采用SpringBoot框架前端框架Vue可行性分析系统测试系统测试的目的系统功能测试数据库表设计代码参考数据库脚本为什么选择我?获取源码前言......
  • 数据库原理实验三 数据库系统设计综合实验
    一、实验目的通过实验,使学生掌握数据库系统设计和开发的一般方法,能够设计并实现简单的数据库系统。二、实验原理1、学生选课关系数据库需求描述假设有“教师”、“学生”、“课程”三个实体,教师的基本信息包括:工号、姓名、职称、工资;课程的基本信息包括:课程号、课程名、学......
  • 基于SpringBoot+Vue的甘肃旅游管理系统的详细设计和实现(源码+lw+部署文档+讲解等)
    文章目录前言详细视频演示项目运行截图技术框架后端采用SpringBoot框架前端框架Vue可行性分析系统测试系统测试的目的系统功能测试数据库表设计代码参考数据库脚本为什么选择我?获取源码前言......
  • 达梦DM8读写分离环境搭建及原理
    达梦DM8读写分离环境搭建及原理 DM8读写分离是建立在主备基础上,搭建过程大致相同,区别如下:1、主备的dmarch.ini不同。读写分离是:ARCH_TYPE=TIMELY#即时归档类型主备是:ARCH_TYPE=REALTIME#实时归档类型2、客户端连接集群配置稍有不同。客户端主机上需要配置dm_sv......
  • 【MySQL(锁篇)】深入MySQL锁机制:从全局到行级,解锁数据库性能瓶颈(下:行锁分析实战、死锁原
    文章目录MySQL(锁篇)-全局锁、表锁、行锁(记录锁、间隙锁、临键锁、插入意向锁)、意向锁、SQL加锁分析、死锁产生原因与排查行锁分析实战1读已提交RC1.1组合一:ID是主键1.2组合二:ID唯一索引1.3组合三:ID非唯一索引1.4组合四:ID无索引2可重复读RR2.1组合五:ID主键2.2组......
  • 达梦数据库dm8版本Mpp集群原理系统架构和搭建测试
    达梦数据库dm8版本Mpp集群原理系统架构和搭建测试    当前主流的数据库系统架构有完全共享、共享存储、完全不共享和完全对等不共享几种。其中完全共享体系如SMP服务器,局限于单节点服务器,通常价格比较昂贵,其扩展性和性能受到相应的限制。共享存储体系允许系统......
  • 记一次解决SpringBoot项目由于依赖加载顺序问题导致启动报NoSuchMethodError的问题
    只发博客园,盗版必究先说背景平时我们的SpringBoot项目都是打成ExecutableJar启动应用,最近接了个技术需求,需要打成War包,将多个项目放在同一个Tomcat中运行。原本Jar包启动一切正常,但是打成WAR放Tomcat启动后报错了,异常栈如下:Causedby:org.springframework.beans.factory.......