【Spring框架四】——Spring AOP 注解实现和xml方式实现1

简介: 【Spring框架四】——Spring AOP 注解实现和xml方式实现

系列文章目录

【Spring框架一】——Spring框架简介

【Spring框架二】——什么是Spring IOC、 什么是Spring 依赖注入

【Spring框架三】——Spirng IOC和DI的实现

Spring AOP 注解实现和xml方式实现

前言

Spring AOP是Spring框架中的核心内容之一,本篇博客主要讲解的是如何使用Spring Aop通过本篇博客能够对什么是Spring AOP以及如何将Spring AOP运行到具体业务有一个清晰的步骤。本篇博客主要从两个维度实现Spring AOP 一个是使用纯xml文件方式,另一个是使用纯注解的方式实现。


一、什么是Spring AOP(Aspect-Oriented Programming)

Spring AOP是面向切面编程的技术,能够对程序进行横切关注点的处理,例如日志记录、安全控制、性能统计、事物处理等。

通过AOP一方面可以将一些与业务无关、但是对业务产生重要影响的公共行为(例如事物管理、日志记录等)从业务逻辑中分离出来,这样可以使程序的模块化程度更高、同时也便于维护和扩展。


Spring AOP通过运行时的动态代理的方式,在不修改原有代码的情况下,将切面逻辑织入到目标对象中,从而实现对目标对象的增强。主要依赖与代理模式和反射机制。


备注:如果想要了解什么是代理,可以访问博主的另外两篇博客


设计模式——代理模式


Java JDK动态代理


什么是横切关注点

corss-cutting concern:指的是一个系统中存在的、多个模块都会用到的,与核心业务逻辑无关的公共关注点。例如:日志记录、性能统计、安全控制。

在传统的面向对象编程中,这些横切关注点都会分散到各个模块中,导致代码复杂、难以维护。

而AOP的目的是将这些横切关注点从核心业务逻辑中分离出来,从而使系统更易于维护和扩展。


二、Spring AOP中的基本概念

结合具体业务的示意图:addUser为原有的具体业务的实现,现在需要在其之前之后等使用Spring AOP切入一个与原有业务无关的校验安全性。

我们通过这个业务来理解Spring AOP的概念

2b44f68e8ab3470b94782ead9b2bf773.png


Cross Cutting Concern

横切性关注点:它是一种独立服务,在我们这个例子中它是检查安全性。它会遍布在系统的处理流程之中。


Aspect

切面: 对横切性关注点的模块化,图中为SecurityHandler


Advice

通知:对横切性关注点的具体实现,常见的通知类型有(Before、After、AfterReturning、AfterThrowing、Around)


Pointcut

切点:它定义了Advice应用到那些JoinPoint上,对Spring来说是方法调用

Spring只支持方法的JoinPoint,但是对于AspectJ这个点也可以是属性修改,如。


Joinpoint

连接点:在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候。 在Spring AOP中,一个连接点 总是 代表一个方法的执行。 通过声明一个org.aspectj.lang.JoinPoint类型的参数可以使通知(Advice)的主体部分获得连接点信息。


Weave

织入:将Advice应用到TargetObject上的过程叫织入,Spring支持的是动态织入


TargetObject

目标对象:目标对象是被一个或多个切面所通知的对象。


Proxy

代理:AOP代理是在目标对应和切面之间进行通信的对象;Spring AOP默认使用JDK的动态代理,它的代理是运行时创建,也可以使用CGLIB代理


Introduction

引入:引入允许将新的接口和实现引入到现有的类中,从而为类添加额外的行为。


这些核心概念共同构成了Spring AOP的基础,通过它们可以实现对横切关注点的管理和控制,从而提供横切关注点的复用和模块化。


三、使用xml文件的方式实现Spring AOP

原spring项目的代码结构


c0b64737b2244d71b12b0b618135d75d.png

pom.xml

<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.3.8</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.8</version>
        </dependency>
    <!--spring aop -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.7</version>
        </dependency>
    </dependencies>

UserManager类

package com.wangwei.springaop.service;
public interface UserManager {
   public void addUser(String username, String password);
   public void delUser(int userId);
   public int findUserById(int userId);
   public void modifyUser(int userId, String username, String password);
}

UserManagerImpl

package com.wangwei.springaop.service.impl;
import com.wangwei.springaop.service.UserManager;
public class UserManagerImpl implements UserManager {
   public void addUser(String username, String password) {
      System.out.println("---------UserManagerImpl.add()--------");
   }
   public void delUser(int userId) {
      System.out.println("---------UserManagerImpl.delUser()--------");
   }
   public int findUserById(int userId) {
      System.out.println("---------UserManagerImpl.findUserById()--------");
      return userId;
   }
   public void modifyUser(int userId, String username, String password) {
      System.out.println("---------UserManagerImpl.modifyUser()--------");
   }
}

Client类

package com.wangwei.springaop.client;
import com.wangwei.springaop.service.UserManager;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Client {
   public static void main(String[] args) {
       //读取xml配置文件,申明工厂
      BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml");
      //获取beanid为userManager的bean
      UserManager userManager = (UserManager)factory.getBean("userManager");
      userManager.addUser("wangwei", "123");
   }
}

applicationContext.xml


设置标签

<beans xmlns="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
          http://www.springframework.org/schema/beans/spring-beans.xsd
          http://www.springframework.org/schema/context
          http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
   <bean id="userManager" class="com.wangwei.springaop.service.impl.UserManagerImpl"/>
</beans>

当前运行的结果


a8d84bbb9cd540e2aefc9e264ae4d00b.png

xml方式实现Spring AOP

目前业务是需要在程序执行addUser()这个方法之前,通过Spring AOP技术切入一个检查安全性的服务。


我们的横切性关注点(Cross Cutting Concern)就是这个检查安全性的服务。

现在我们将这个横切性关注点进行模块化


创建SecurityHandler类,它就代表的是Aspect,是对横切性关注点的模块化。

package com.wangwei.springaop.service.impl;
public class SecurityHandler {
   private void checkSecurity() {
      System.out.println("-------checkSecurity-------");
   }
}

在XML配置文件中进行配置


<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/beans
          http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
   <bean id="userManager" class="com.wangwei.springaop.service.impl.UserManagerImpl"/>
   <bean id ="securityHandlerAspect" class="com.wangwei.springaop.service.impl.SecurityHandler"/>
<!--   配置切面通知和切点-->
   <aop:config>
      <aop:aspect ref="securityHandlerAspect">
         <aop:before method="checkSecurity" pointcut="execution(* com.wangwei.springaop.service.impl.UserManagerImpl.addUser(..))"/>
      </aop:aspect>
   </aop:config>
</beans>

上面的通知(advice)配置的为Before,

切点它定义了Advice应用到那些JoinPoint上,这里是通过表达式execution定位到连接点(joinPoint)

joinPoin代表一个方法的执行,这里指的是addUser()这个方法的执行。


实现效果:


9c8c0034c98c42bda88d5f6ee5281064.png

补充关于Spring AOP 切入点的表达式

切入点表达式有两部分组成:签名和指示器


签名部分指定了要匹配的连接点的方法签名。

例如:"execution(public * com.example.service…(…))"表示匹配com.example.service包中的所有公共方法。

指示器部分用于进一步细化匹配的连接点。常见的指示器包括:


execution:匹配方法执行连接点。

within:匹配指定类型内的方法执行连接点。

args:匹配参数类型符合指定类型的方法执行连接点。

annotation:匹配带有指定注解的方法执行连接点。

以下是一些切入点表达式的示例:


1.execution(public * com.example.service…(…)):匹配com.example.service包中的所有公共方法。

2.within(com.example.service.*):匹配com.example.service包中所有方法。

3.execution(* com.example.service.UserService.addUser(…)):匹配com.example.service.UserService类的addUser方法。

args(String, *):匹配第一个参数为String类型的方法。

4.annotation(org.springframework.transaction.annotation.Transactional):匹配带有@Transactional注解的方法。

切入点表达式的语法非常灵活,可以根据需要进行组合和定制,以精确地选择要应用切面的连接点。


常用表达式示例

一般用的是execution执行表达式的格式如下:

execution(modifiers-pattern? return-type-pattern declaring-type-pattern? method-name-pattern(param-pattern) throws-pattern?)

其中,各个部分的含义如下:


1.modifiers-pattern(可选):用于匹配方法的修饰符,如

public、protected等。可以使用通配符*匹配任意修饰符。

2.return-type-pattern:用于匹配方法的返回类型,可以是具体的类型或通配符*表示任意类型。

3.declaring-type-pattern(可选):用于匹配方法所在的类的类型,可以是具体的类型或通配符*表示任意类型。

4.method-name-pattern:用于匹配方法的名称,可以是具体的方法名或使用通配符

*匹配任意方法名。

5.param-pattern:用于匹配方法的参数类型,可以是具体的类型、通配符表示任意类型、…表示任意个参数、()表示一个参数,以及(*, *)表示两个参数等。

6.throws-pattern(可选):用于匹配方法可能抛出的异常类型,可以是具体的异常类型或通配符*表示任意异常。

下面是一些示例:

execution(public * com.example.service..(…)):匹配com.example.service包中的所有公共方法。

execution(* com.example.service.UserService.addUser(String, )):匹配com.example.service.UserService类的addUser方法,第一个参数为String类型,第二个参数为任意类型。

execution( com.example.service..(…) throws java.io.IOException):匹配com.example.service包中所有方法,且可能抛出java.io.IOException异常。


目录
相关文章
|
12月前
|
安全 Java Ruby
我尝试了所有后端框架 — — 这就是为什么只有 Spring Boot 幸存下来
作者回顾后端开发历程,指出多数框架在生产环境中难堪重负。相比之下,Spring Boot凭借内置安全、稳定扩展、完善生态和企业级支持,成为构建高可用系统的首选,真正经受住了时间与规模的考验。
772 2
|
12月前
|
XML 安全 Java
使用 Spring 的 @Aspect 和 @Pointcut 注解简化面向方面的编程 (AOP)
面向方面编程(AOP)通过分离横切关注点,如日志、安全和事务,提升代码模块化与可维护性。Spring 提供了对 AOP 的强大支持,核心注解 `@Aspect` 和 `@Pointcut` 使得定义切面与切入点变得简洁直观。`@Aspect` 标记切面类,集中处理通用逻辑;`@Pointcut` 则通过表达式定义通知的应用位置,提高代码可读性与复用性。二者结合,使开发者能清晰划分业务逻辑与辅助功能,简化维护并提升系统灵活性。Spring AOP 借助代理机制实现运行时织入,与 Spring 容器无缝集成,支持依赖注入与声明式配置,是构建清晰、高内聚应用的理想选择。
923 0
|
XML JSON Java
Spring框架中常见注解的使用规则与最佳实践
本文介绍了Spring框架中常见注解的使用规则与最佳实践,重点对比了URL参数与表单参数的区别,并详细说明了@RequestParam、@PathVariable、@RequestBody等注解的应用场景。同时通过表格和案例分析,帮助开发者正确选择参数绑定方式,避免常见误区,提升代码的可读性与安全性。
|
11月前
|
安全 前端开发 Java
《深入理解Spring》:现代Java开发的核心框架
Spring自2003年诞生以来,已成为Java企业级开发的基石,凭借IoC、AOP、声明式编程等核心特性,极大简化了开发复杂度。本系列将深入解析Spring框架核心原理及Spring Boot、Cloud、Security等生态组件,助力开发者构建高效、可扩展的应用体系。(238字)
|
11月前
|
消息中间件 缓存 Java
Spring框架优化:提高Java应用的性能与适应性
以上方法均旨在综合考虑Java Spring 应该程序设计原则, 数据库交互, 编码实践和系统架构布局等多角度因素, 旨在达到高效稳定运转目标同时也易于未来扩展.
873 8
|
12月前
|
监控 Kubernetes Cloud Native
Spring Batch 批处理框架技术详解与实践指南
本文档全面介绍 Spring Batch 批处理框架的核心架构、关键组件和实际应用场景。作为 Spring 生态系统中专门处理大规模数据批处理的框架,Spring Batch 为企业级批处理作业提供了可靠的解决方案。本文将深入探讨其作业流程、组件模型、错误处理机制、性能优化策略以及与现代云原生环境的集成方式,帮助开发者构建高效、稳定的批处理系统。
938 1
|
安全 Java 微服务
Java 最新技术和框架实操:涵盖 JDK 21 新特性与 Spring Security 6.x 安全框架搭建
本文系统整理了Java最新技术与主流框架实操内容,涵盖Java 17+新特性(如模式匹配、文本块、记录类)、Spring Boot 3微服务开发、响应式编程(WebFlux)、容器化部署(Docker+K8s)、测试与CI/CD实践,附完整代码示例和学习资源推荐,助你构建现代Java全栈开发能力。
1116 1
|
缓存 安全 Java
Spring 框架核心原理与实践解析
本文详解 Spring 框架核心知识,包括 IOC(容器管理对象)与 DI(容器注入依赖),以及通过注解(如 @Service、@Autowired)声明 Bean 和注入依赖的方式。阐述了 Bean 的线程安全(默认单例可能有安全问题,需业务避免共享状态或设为 prototype)、作用域(@Scope 注解,常用 singleton、prototype 等)及完整生命周期(实例化、依赖注入、初始化、销毁等步骤)。 解析了循环依赖的解决机制(三级缓存)、AOP 的概念(公共逻辑抽为切面)、底层动态代理(JDK 与 Cglib 的区别)及项目应用(如日志记录)。介绍了事务的实现(基于 AOP
518 0
|
Cloud Native Java API
Java Spring框架技术栈选和最新版本及发展史详解(截至2025年8月)-优雅草卓伊凡
Java Spring框架技术栈选和最新版本及发展史详解(截至2025年8月)-优雅草卓伊凡
1814 0
|
缓存 安全 Java
第五章 Spring框架
Spring IOC(控制反转)通过工厂模式管理对象的创建与生命周期,DI(依赖注入)则让容器自动注入所需对象,降低耦合。常见注解如@Component、@Service用于声明Bean,@Autowired用于注入。Bean默认单例,作用域可通过@Scope配置,如prototype、request等。Spring通过三级缓存解决循环依赖问题,但构造函数循环依赖需用@Lazy延迟加载。AOP通过动态代理实现,用于日志、事务等公共逻辑。事务通过@Transactional实现,需注意异常处理及传播行为。
177 0