news 2026/6/5 21:10:22

Spring:AOP

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Spring:AOP

AOP

什么是AOP?

不影响原来的业务实现动态增加

AOP(Aspect Oriented Programming)意味:切面编程,通过预编译方式和运行期动态代理实现程序功能的同意维护的一种技术。AOP是OOP的延续,是软件开发的热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间耦合度降低,提高程序的可重用性,同时提高了开发的效率。

Aop在Spring中的作用

提供声明式事务;允许用户自定义切面

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

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

Aop在不改变原有代码的情况下,去增加新的功能。

使用Spring实现Aop

【重点】使用AOP织入,需要导入一个依赖包!叫做织入包

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.4</version></dependency>

方式一:使用Spring的Api接口

  1. 配置AOP的约束
<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"><context:annotation-config/><context:component-scanbase-package="com.cike9"/></beans>

  1. 配置bean(容器id)
<beanid="log"class="com.cike9.log.Log"/><beanid="afterLog"class="com.cike9.log.AfterLog"/><beanid="userServiceImpl"class="com.cike9.service.UserServiceImpl"/>
  1. Spring AOP 的 XML 配置方式
<aop:config><!--切入点--><aop:pointcutid="pointcut"expression="execution(* com.cike9.service.UserServiceImpl.*(..))"/><!--执行环绕增加!--><aop:advisoradvice-ref="log"pointcut-ref="pointcut"/><aop:advisoradvice-ref="afterLog"pointcut-ref="pointcut"/></aop:config>

execution(返回值类型 包名.类名/接口名.方法名(任意的参数列表))

(…)可以代表所有参数,()代表一个参数,(,String)代表第一个参数为任何值,第二个参数为String类型.

整体代码

业务类的接口 (UserService)

publicinterfaceUserService{voidadd();voiddelete();voidupdate();voidquery();}

实际业务类(UserServiceImpl)

publicclassUserServiceImplimplementsUserService{@Overridepublicvoidadd(){System.out.println("增加了一个用户");}@Overridepublicvoiddelete(){System.out.println("删除了一个用户");}@Overridepublicvoidupdate(){System.out.println("更新用户");}@Overridepublicvoidquery(){System.out.println("查询用户");}}

横向扩展业务类(AfterLog)

publicclassAfterLogimplementsAfterReturningAdvice{// 返回值,方法,参数,目标对象publicvoidafterReturning(ObjectreturnValue,Methodmethod,Object[]args,Objecttarget)throwsThrowable{System.out.println("执行了"+method.getName()+"方法,"+"返回第结果为:"+returnValue);}}

横向扩展业务类 (Log)

publicclassLogimplementsMethodBeforeAdvice{// method:要执行的目标对象的方法// Objects:参数// 他target: 目标对象publicvoidbefore(Methodmethod,Object[]args,Objecttarget)throwsThrowable{System.out.println(target.getClass().getName()+"的"+method.getName()+"方法被执行了");}}

Spring的XML配置(applicationContext.xml)

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"><context:annotation-config/><context:component-scanbase-package="com.cike9"/><beanid="log"class="com.cike9.log.Log"/><beanid="afterLog"class="com.cike9.log.AfterLog"/><beanid="userServiceImpl"class="com.cike9.service.UserServiceImpl"/><!-- 方式一:使用原生Spring API接口 配置aop:需要导入aop的约束 --><aop:config><!--切入点--><aop:pointcutid="pointcut"expression="execution(* com.cike9.service.UserServiceImpl.*(..))"/><!--执行环绕增加!--><aop:advisoradvice-ref="log"pointcut-ref="pointcut"/><aop:advisoradvice-ref="afterLog"pointcut-ref="pointcut"/></aop:config></beans>

测试类

publicclassspring09_Test{@Testpublicvoidtest(){ApplicationContextcontext=newClassPathXmlApplicationContext("applicationContext.xml");// 动态代理的是接口,不应该写实现类这里UserServiceuserServiceImpl=(UserService)context.getBean("userServiceImpl");userServiceImpl.add();}}

可以发现扩展业务类,市集上调用的就是这两种实现接口(都是通知类型)

通过这种方式,可以找到aop下可以用的接口(方法)

方式二:自定义类实现AOP【主要是切面定义】

自定义类

packagecom.cike9.diy;publicclassDiyPointCut{voidbefore(){System.out.println("================方法执行前================");}voidafter(){System.out.println("================方法执行后================");}}

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"><context:annotation-config/><context:component-scanbase-package="com.cike9"/><beanid="log"class="com.cike9.log.Log"/><beanid="afterLog"class="com.cike9.log.AfterLog"/><beanid="userServiceImpl"class="com.cike9.service.UserServiceImpl"/><!--方式二:自定义类--><beanid="diy"class="com.cike9.diy.DiyPointCut"/><aop:config><!--自定义切面--><aop:aspectref="diy"><!--切入点--><aop:pointcutid="point"expression="execution(* com.cike9.service.UserServiceImpl.*(..))"/><!--通知 --><aop:beforemethod="before"pointcut-ref="point"/><!--在切入点之前执行通知--><aop:aftermethod="after"pointcut-ref="point"/></aop:aspect></aop:config></beans>

业务接口

publicinterfaceUserService{voidadd();voiddelete();voidupdate();voidquery();}

业务实现类

publicclassUserServiceImplimplementsUserService{@Overridepublicvoidadd(){System.out.println("增加了一个用户");}@Overridepublicvoiddelete(){System.out.println("删除了一个用户");}@Overridepublicvoidupdate(){System.out.println("更新用户");}@Overridepublicvoidquery(){System.out.println("查询用户");}}

测试类

publicclassspring09_Test{@Testpublicvoidtest(){ApplicationContextcontext=newClassPathXmlApplicationContext("applicationContext.xml");// 动态代理的是接口,不应该写实现类这里UserServiceuserServiceImpl=(UserService)context.getBean("userServiceImpl");userServiceImpl.add();}}

方式三:使用注解实现

在自定义类里面添加注解

  1. 开启直接支持!aop:aspectj-autoproxy/
  2. 切面 @Aspect
  3. 切入点 @Before(“execution(* com.cike9.service.UserServiceImpl.*(…))”)

自定义类中进行注解开发AOP

@Component("annotationPointCut")// 使用注解方式实现AOP@Aspect// 标注这个类是一个切面 相当于<aop:config><aop:aspect ref="diy"></aop:config>publicclassAnnotationPointCut{// 这里相当于切入点@Before("execution(* com.cike9.service.UserServiceImpl.*(..))")voidbefore(){//通知的方法System.out.println("================方法执行前================");}@After("execution(* com.cike9.service.UserServiceImpl.*(..))")voidafter(){System.out.println("================方法执行后================");}}

applicattionContext.xml

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd"><context:annotation-config/><context:component-scanbase-package="com.cike9"/><!--方式三:开启注解支持 JDK(默认 proxy-target-class="false") cgilib(proxy-target-class="true")--><aop:aspectj-autoproxyproxy-target-class="false"/></beans>

业务实现类

importorg.springframework.stereotype.Service;@Service("userServiceImpl")// 相当于bean配置 <bean id="userServiceImpl" class="com.cike9.service.UserServiceImpl"/>publicclassUserServiceImplimplementsUserService{@Overridepublicvoidadd(){System.out.println("增加了一个用户");}@Overridepublicvoiddelete(){System.out.println("删除了一个用户");}@Overridepublicvoidupdate(){System.out.println("更新用户");}@Overridepublicvoidquery(){System.out.println("查询用户");}}

业务接口

publicinterfaceUserService{voidadd();voiddelete();voidupdate();voidquery();}

测试

publicclassspring09_Test{@Testpublicvoidtest(){ApplicationContextcontext=newClassPathXmlApplicationContext("applicationContext.xml");// 动态代理的是接口,不应该写实现类这里UserServiceuserServiceImpl=(UserService)context.getBean("userServiceImpl");userServiceImpl.add();}}

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/30 0:51:15

GitHub镜像网站镜像策略分析:为何lora-scripts下载更快

GitHub镜像加速下的高效分发&#xff1a;解密 lora-scripts 为何下载更快 在AI开发者的日常中&#xff0c;一个再熟悉不过的场景是&#xff1a;当你准备开始训练自己的LoRA模型时&#xff0c;第一件事往往是克隆项目仓库。然而&#xff0c;面对GitHub上动辄几十秒甚至超时失败…

作者头像 李华
网站建设 2026/5/30 1:21:42

text-generation任务怎么配置?lora-scripts进阶使用说明

text-generation任务怎么配置&#xff1f;lora-scripts进阶使用说明 在大模型落地业务场景的过程中&#xff0c;一个绕不开的问题是&#xff1a;如何用有限的数据和算力&#xff0c;快速定制出符合特定需求的生成能力&#xff1f;全参数微调成本太高&#xff0c;从头训练更是不…

作者头像 李华
网站建设 2026/5/28 13:44:17

从入门到精通,C++26中CPU亲和性配置全攻略,错过等于降薪

第一章&#xff1a;C26 CPU亲和性配置概述在现代多核处理器架构中&#xff0c;合理分配线程与CPU核心的绑定关系能够显著提升程序性能。C26标准引入了对CPU亲和性&#xff08;CPU Affinity&#xff09;的原生支持&#xff0c;使开发者能够在语言层面直接控制执行上下文与特定核…

作者头像 李华
网站建设 2026/5/30 12:08:42

(C++26性能黑科技)如何通过CPU亲和性将响应速度提升40%以上?

第一章&#xff1a;C26性能黑科技概述C26 正在成为高性能计算与系统级编程的下一个里程碑&#xff0c;引入了一系列旨在压榨硬件极限的“黑科技”特性。这些新机制不仅优化了编译期行为&#xff0c;还深度增强了运行时效率&#xff0c;尤其在并发、内存访问和元编程方面实现了质…

作者头像 李华
网站建设 2026/5/31 0:32:22

lora-scripts数据预处理最佳实践:提升LoRA模型收敛速度

LoRA训练提速秘诀&#xff1a;从数据预处理入手&#xff0c;打造高效微调闭环 在AI生成内容&#xff08;AIGC&#xff09;爆发式增长的今天&#xff0c;个性化模型定制已成为开发者手中的“新生产力工具”。无论是为游戏设计专属画风&#xff0c;还是为企业构建品牌语义风格&am…

作者头像 李华