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 2:27:26

C语言嵌入式设备运行微型版lora-scripts设想

C语言嵌入式设备运行微型版lora-scripts设想 在工业控制现场&#xff0c;一台老旧的PLC控制器正通过OTA接收一个新的模型包——不是整套神经网络&#xff0c;而是一个仅380KB的.safetensors文件。几秒后&#xff0c;这台原本只能执行固定逻辑的设备突然开始生成符合工厂视觉风格…

作者头像 李华
网站建设 2026/4/18 2:32:49

编译期优化如何影响运行启动?深度解析C++启动性能的隐性杀手

第一章&#xff1a;编译期优化如何影响运行启动&#xff1f;深度解析C启动性能的隐性杀手在现代C开发中&#xff0c;编译期优化常被视为提升程序性能的利器。然而&#xff0c;过度或不当的优化可能在无形中增加程序的启动开销&#xff0c;成为运行初期的“隐性杀手”。这些影响…

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

【C++量子计算模拟精度突破】:揭秘高精度仿真的5大核心技术

第一章&#xff1a;C量子计算模拟精度突破概述随着量子算法复杂度的提升&#xff0c;传统浮点运算在模拟量子态演化时逐渐暴露出精度不足的问题。C凭借其底层内存控制与高性能计算能力&#xff0c;成为实现高精度量子模拟器的理想语言。通过引入任意精度算术库与优化复数运算&a…

作者头像 李华
网站建设 2026/4/18 2:25:03

C++26标准深度解析:CPU亲和性API设计背后的性能哲学

第一章&#xff1a;C26标准中的CPU亲和性演进C26 标准在系统级编程能力上迈出了重要一步&#xff0c;特别是在多核处理器调度优化方面引入了对 CPU 亲和性的原生支持。这一特性允许开发者更精细地控制线程在特定 CPU 核心上的执行&#xff0c;从而提升缓存局部性、降低上下文切…

作者头像 李华
网站建设 2026/4/18 2:31:18

消费级显卡也能跑LoRA训练?RTX 3090/4090实测效果曝光

消费级显卡也能跑LoRA训练&#xff1f;RTX 3090/4090实测效果曝光 在AI生成内容&#xff08;AIGC&#xff09;迅速普及的今天&#xff0c;越来越多的个人开发者和小型团队希望定制属于自己的图像风格或语言模型。然而&#xff0c;传统全量微调动辄需要数万甚至数十万元的专业GP…

作者头像 李华