spring之AOP(面向切面编程)

news/2024/9/23 18:22:34
  1. 什么是AOP?

    AOP(Aspect Oriented Programming)意为:面向切面编程,体现了横切的思想,意思是在添加某项功能的时候,是以切面插入的方式实现的,对原有的代码不会产生改变。通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。

  2. AOP在spring中的作用:在不改变原有代码的情况下,去增加新的功能。

    • 横切关注点:跨越应用程序多个模块的方法或功能。即与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志,安全,缓存,事务等等 …
    • 切面(ASPECT):横切关注点被模块化的特殊对象。即,它是一个类。
    • 通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。
    • 目标(Target):被通知对象。
    • 代理(Proxy):向目标对象应用通知之后创建的对象。
    • 切入点(PointCut):切面通知 执行的 “地点”的定义。
    • 连接点(JointPoint):与切入点匹配的执行点。

    SpringAOP中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice:

  3. aop的实现

    • 需要导入相应的包
    <dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>xxx</version>
    </dependency>
    
    • 第一种实现方式:通过spring API 编写业务接口实现类
    //业务接口
    public interface UserService {void add();
    }
    //业务实现类
    public class UserServiceImpl implements UserService {@Overridepublic void add() {System.out.println("执行了add方法");}
    }
    
    • 编写增强类:前置和后置
    public class Log implements MethodBeforeAdvice {/*** target:目标对象* args:参数* method:目标对象的方法*/@Overridepublic void before(Method method, Object[] args, Object target) throws Throwable {System.out.println(target.getClass().getName()+"执行了"+method.getName()+"方法");}
    }
    public class AfterLog implements AfterReturningAdvice {/*** returnValue:返回值*/@Overridepublic void afterReturning(Object returnValue, Method method, Object[] objects, Object o1) throws Throwable {System.out.println("执行了"+method.getName()+"方法,返回结果"+returnValue);}
    }
    
    • 编写配置文件,要导入aop的约束
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttps://www.springframework.org/schema/aop/spring-aop.xsd"><!--注册bean--><bean id="userService" class="com.test.service.UserServiceImpl"/><bean id="log" class="com.test.log.Log"/><bean id="afterLog" class="com.test.log.AfterLog"/><!--方式一:使用原生Spring API接口 --><!--配置aop:需要导入aop的约束--><aop:config><!--切入点:expression:表达式,execution(要执行的位置! * * * * *) --><aop:pointcut id="pointcut" expression="execution(* com.test.service.UserServiceImpl.*(..))"/><!--执行环绕增加!--><aop:advisor advice-ref="log" pointcut-ref="pointcut"/><aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/></aop:config>
    </beans>
    
    • 测试
    @Test
    public void test1(){ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");UserService userService = context.getBean("userService", UserService.class);userService.add();
    }
    
    • 第二种方式:自定义类实现AOP
    public class SelfPointcut {public void before() {System.out.println("使用前");}public void after() {System.out.println("使用后");}
    }
    
    • 编写配置类
    <beans>
    <!--方式二:自定义类--><bean id="selfPointcut" class="com.test.self.SelfPointcut"/><aop:config><!--自定义切面, ref 要引用的类--><aop:aspect ref="selfPointcut"><!--切入点--><aop:pointcut id="point" expression="execution(* com.test.service.UserServiceImpl.*(..))"/><!--通知--><aop:before method="before" pointcut-ref="point"/><aop:after method="after" pointcut-ref="point"/></aop:aspect></aop:config>
    </beans>
    
    • 使用注解的方式:编写使用注解的实现类
    @Aspect// 标注此类是一个切面
    public class AnnotationPointCut {@Before("execution(* com.test.service.UserServiceImpl.*(..))")public void before(){System.out.println("方法执行前");}@After("execution(* com.test.service.UserServiceImpl.*(..))")public void after(){System.out.println("方法执行后");}
    }
    
    • 编写配置
    <!--方式三-->
    <bean id="annotationPointCut" class="com.test.self.AnnotationPointCut"/>
    <!--开启注解支持!   JDK(默认 proxy-target-class="false")   cglib(proxy-target-class="true")-->
    <aop:aspectj-autoproxy/>
    
  4. spring aop JDK动态代理和cglib动态代理的区别

    • Spring AOP 支持两种类型的动态代理:JDK 动态代理和 CGLIB 动态代理。它们之间有以下区别:

    • 基于类型:JDK 动态代理是基于接口的代理,而 CGLIB 动态代理是基于类的代理。

    • 代理对象创建:JDK 动态代理通过 Java 自带的 java.lang.reflect.Proxy 创建代理对象,该对象必须实现一个或多个接口。CGLIB 动态代理通过字节码生成技术创建代理对象,无需目标类实现接口,直接继承目标类。

    • 性能:JDK 动态代理在运行时需要使用反射,导致较低的性能。CGLIB 动态代理通过生成字节码,避免了反射,因此通常比 JDK 动态代理速度更快。

    • 对象类型:JDK 动态代理只能代理具有接口的目标对象,不适用于没有接口的类。CGLIB 动态代理可以代理任何类,包括没有实现接口的类。

    • 继承:JDK 动态代理只能代理目标对象的接口方法,不能代理其父类中的方法。CGLIB 动态代理可以代理目标类及其父类中的方法。

    • 综上所述,选择使用 JDK 动态代理还是 CGLIB 动态代理取决于具体的需求和场景。如果目标对象实现了接口并且对性能要求较高,可以选择 JDK 动态代理;如果目标对象没有实现接口或者对性能要求不那么苛刻,可以选择 CGLIB 动态代理。默认情况下,Spring AOP 使用 JDK 动态代理,但在某些情况下会自动切换到 CGLIB 动态代理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/30968.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

识别与防御CSRF漏洞

识别与防御CSRF漏洞 CSRF(Cross-Site Request Forgery,跨站请求伪造),通常也被称为“一键攻击”或“会话劫持”,其缩写为CSRF或XSRF,是一种针对网站的恶意利用技术。尽管名字听起来与跨站脚本(XSS)相似,但两者在本质上是截然不同的。XSS主要依赖于用户对站点的信任,而…

Linux查看一个目录下占用磁盘最多的文件或目录

想要找到占用磁盘最多的文件或目录,可以使用du和sort命令: du -h /path/to/directory | sort -rh | head -n 10其中:du -h /path/to/directory 用于计算指定目录下的所有文件和子目录的大小,并以人类可读的格式显示。 sort -rh 用于按磁盘使用情况的大小(逆序)对输出进行…

mybatisPlus多数据源的使用使用 lambdaQuery 导致多数据源失效

依赖<dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId><version>3.5.2</version></dependency>配置文件:spring:datasource:type: com.alibaba.druid.pool.Drui…

什么? 20分钟,构建你自己的LLaMA3应用程序! | 京东云技术团队

4月19日,Meta发布了最新的大语言模型LLaMA3,具体包括一个 8B 模型和一个 70 B 模型,上下文长度支持8K, 被誉为史上最强开源大语言模型,开源社区的“重磅炸弹”,效果直指GTP4。在诸多评测任务上,LLaMA3都有非常炸裂的效果。 8B模型在多项指标中超越了Gemma 7B和Mistral 7…

第三代长安75p安装三方软件

前言 长安的车机系统是 长安与腾讯联合且基于安卓自研的 梧桐车联系统。此系统极为封闭,默认情况下,不允许安装除了车机本身应用商店之外的三方软件。 除此之外,车机内置的软件版本都特别低(比如高德),且不支持升级,只能等待整个车机系统连带升级,遗憾的是他们通常好几…

启停openGauss

启停openGauss 启动openGauss以操作系统用户omm登录数据库主节点。使用以下命令启动openGauss。 gs_ctl start -D /opt/data说明: 如果提示找不到gs_ctl,请检查是否source过环境变量文件(默认是~/.bashrc),若不想source环境变量文件也可以手动切换到安装路径下执行该命令。…

c++-----declval

std::declval 基本概念和常规实例std::decval–C++新标准中出现的函数模板,没有函数体(只有声明、没有实现),无法调用,一般用于与decltype,sizeof等关键字配合来进行类型推导、占用内存空间计算等 查看源码: add_rvalue_reference:是C++标准库中的类模板,他的能力是给进一…

Entity Framework Core中的并发处理

1.常见的并发处理策略 要了解如何处理并发,就要知道并发的一般处理策略 悲观并发策略 悲观并发策略,正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守悲观的态度,因此,在整个数据处理过程中,将数据处于锁定状态。悲观并发策略…