news 2026/4/18 3:35:27

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/4/18 10:36:13

每100步自动保存一次权重:防止意外中断导致前功尽弃

每100步自动保存一次权重&#xff1a;防止意外中断导致前功尽弃 在AI模型训练的世界里&#xff0c;最令人崩溃的瞬间是什么&#xff1f;不是参数调不好&#xff0c;也不是效果不理想——而是当你盯着GPU显存跑了整整三天&#xff0c;终于看到loss曲线开始收敛时&#xff0c;系统…

作者头像 李华
网站建设 2026/4/18 7:29:51

RPM构建中的Python版本地狱:如何正确处理%{python3_sitelib}宏

引言&#xff1a;一个真实的构建陷阱 想象这样一个场景&#xff1a;你在chroot环境中同时安装了Python 3.6.8和Python 3.11&#xff0c;python3软链接指向3.11。当你使用mock构建glusterfs的RPM包时&#xff0c;spec文件中使用了%{python3_sitelib}宏。然而&#xff0c;在构建过…

作者头像 李华
网站建设 2026/4/17 22:34:04

lora-scripts配置文件详解:my_lora_config.yaml修改要点解析

LoRA-Scripts配置文件详解&#xff1a;my_lora_config.yaml修改要点解析 在生成式AI技术飞速发展的今天&#xff0c;越来越多开发者希望借助微调手段让预训练模型具备个性化能力。然而全参数微调动辄需要数百GB显存和数天训练时间&#xff0c;对大多数个人或中小企业而言并不现…

作者头像 李华
网站建设 2026/4/17 22:58:32

C++26契约编程新特性深度解析(继承与契约协同设计)

第一章&#xff1a;C26契约编程与继承机制的融合背景C26 正式将契约编程&#xff08;Contracts&#xff09;引入语言核心特性&#xff0c;标志着从运行时断言向编译期与运行期协同验证的重大演进。这一机制允许开发者在函数接口层面声明前置条件、后置条件与类不变式&#xff0…

作者头像 李华
网站建设 2026/4/18 13:01:08

web组件化设计思想应用于lora-scripts前端重构

Web组件化设计思想应用于lora-scripts前端重构 在AIGC&#xff08;生成式人工智能&#xff09;迅速普及的今天&#xff0c;越来越多设计师、艺术家和内容创作者希望训练属于自己的风格化模型。以LoRA&#xff08;Low-Rank Adaptation&#xff09;为代表的轻量微调技术&#xff…

作者头像 李华
网站建设 2026/4/17 23:09:36

避免性能浪费!C++26下实现精准CPU亲和性的3步法则

第一章&#xff1a;C26 CPU亲和性与性能优化概览在高性能计算与实时系统开发中&#xff0c;CPU亲和性控制已成为提升程序执行效率的关键手段。C26标准正计划引入原生支持CPU亲和性的语言设施&#xff0c;使开发者能够更精细地管理线程与处理器核心之间的绑定关系&#xff0c;从…

作者头像 李华