【SSH快速进阶】——Spring AOP原理及其实现

简介:   上篇文章简单总结了一下静态代理以及JDK和Cglib两种方式实现的动态代理。由此也延伸出了一个重要的编程思想:AOP。

 上篇文章简单总结了一下静态代理以及JDK和Cglib两种方式实现的动态代理。由此也延伸出了一个重要的编程思想:AOP。


AOP原理


 AOP(Aspect Oriented Programming):面向切面编程。利用AOP可以对业务逻辑中的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。


 AOP主要面向独立的服务,跟业务没有任何关系,通常会遍布在系统的任何角落,如系统的日志、权限检查等服务。


 在Spring 的AOP中,有如下概念:


39.png



 上图中,每部分的解释如下:


 Cross cutting concern

 横切性关注点,一种独立服务,它会遍布在系统的处理流程中(比如日志服务、权限检查等)


 Aspect

 对横切性关注点的模块化(如果横切服务要运行,就必须放在一个类里,可以把它看做是Aspect)


 Advice

 对横切性关注点的具体实现(包括before、after、throwing等),比如在用户操作之前检查用户权限(before);在生成订单之后记录日志(after);在某个方法抛异常之后进行异常处理(throwing)等。


 Pointcut

 它定义了Advice应用到哪些JoinPoint上(即应用到哪些类的那些方法上),对Spring来说是方法调用。动态代理中,会把服务加到所有方法上,但在实际应用中可能不会把服务加到所有的方法上,AOP中就可以定义切入点,即进行过滤,AOP服务加到哪些方法上。


 JoinPoint

 Advice在应用程序上执行的点或时机(比如在类A的a()方法执行之前执行某个操作,或修改类A的b属性时触发某个操作),Spring只支持方法的JoinPoint,Aspecj可以支持可以使属性修改的JoinPoint。Advice执行在JoinPoint上。



Spring AOP实现


 Spring AOP实现步骤大致如下:


 1、Spring jar包的依赖


SPRING_HOME/dist/spring.jar
SPRING_HOME/lib/log4j/log4j-1.2.14.jar
SPRING_HOME/lib/jakarta-commons/commons-logging.jar
SPRING_HOME/lib/aspectj/*.jar


  2、首先在Spring配置文件中启用Aspect对Annotation的支持:


<aop:aspectj-autoproxy/>


  3、定义Aspect


import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Before;
@Aspect
public class SecurityHandler {
  @Pointcut("execution(* add*(..))")
  private void addMethod(){}
  /**
   * 在【* add*(..)】匹配的方法执行之前执行
   */
  @Before("addMethod()")
  private void checkSecurityBeforeAdd(){
    System.out.println("----Before Add:checkSecurity-----");
  }
  /**
   * 在【* add*(..)】匹配的方法执行之后执行
   */
  @After("addMethod()")
  private void addLogAfterAdd(){
    System.out.println("----After Add:addLog-----");
  }
  /**
   * 在【* add*(..)】匹配的方法执行报异常之后执行
   */
  @AfterThrowing("addMethod()")
  private void addLogAfterThrowing(){
    System.out.println("----After Throwing:Throwing-----");
  }
}


 上面的SecurityHandler 类就是权限检查的服务,可以定义在某些方法执行之前、某些方法执行之后等时间点切入该服务。


 @Aspect

 在SecurityHandler类上打上@Aspect注解,就说明它是上面图中的Cross cutting concern经过封装后的模块了,Spring容器加载该类的时候会把它里面定义的所有横切性服务(Advice)都应用到相应的方法(Pointcut)上。


 @Pointcut

 上面例子中@Pointcut标记的方法名称是addMethod,且该方法是一个没有参数和返回值的空方法,该方法可以看做就是一种标记,不进行调用。("execution(* add*(..))") 定义的就是过滤要添加横切性服务的一些方法的条件。具体解释是:第一个*匹配所有类型返回值的方法;第二个*匹配所有方法头带“add”的方法;..表示匹配有参数和无参数的方法都满足条件。更多过滤条件请见Spring Framework开发手册,小编也特意为大家截了张图:点这里看大图


 @Before、@After、@Throwing

 上面例子中其余三种Advice:@Before、@After、@Throwing,大家看注释应该也就看明白了,这是三个执行时机,分别会在目标方法执行前、执行后、报异常后执行。需要注意的是注解后面括号里的内容必须要是@Pointcut定义的方法名称,说明这三个时机执行的Advice都为该方法服务。



 3、客户端调用AOP 服务


public static void main(String[] args) {
  String[] configurations=new String[]{"applicationContext-bean.xml"};
  beanFactory=new ClassPathXmlApplicationContext(configurations);
  UserManager userManager=(UserManager)beanFactory.getBean("userManager");
  userManager.addUser(new User("Danny","12456")); 
}


  以上是用注解的形式来配置的AOP服务,当然也可以用配置文件来配,用配置文件配的时候,上面第2步骤可以省略。

  代理类:


public class SecurityHandler{
  private void checkSecurity(){
    System.out.println("----checkSecurity-----");
  }
}


  以上是用注解的形式来配置的AOP服务,当然也可以用配置文件来配,用配置文件配的时候,上面第2步骤可以省略。

  代理类:

public class SecurityHandler{
  private void checkSecurity(){
    System.out.println("----checkSecurity-----");
  }
}


  配置文件:


<bean id="securityHandler" class="com.danny.spring.SecurityHandler"/>
<aop:config>
  <aop:aspect id="securityAspect" ref="securityHandler">
    <aop:pointcut id="addMethod" expression="execution(* add*(..))"/>
    <aop:before method="checkSecurity" pointcut-ref="addMethod"/>
  </aop:aspect>
</aop:config>


  如果把这种思想运用到项目中,与业务不相干的服务都用AOP切入,极大地减小了服务与业务的耦合,提升了开发效率。

相关文章
|
9月前
|
缓存 Java 开发者
【Spring】原理:Bean的作用域与生命周期
本文将围绕 Spring Bean 的作用域与生命周期展开深度剖析,系统梳理作用域的类型与应用场景、生命周期的关键阶段与扩展点,并结合实际案例揭示其底层实现原理,为开发者提供从理论到实践的完整指导。
1052 22
|
9月前
|
人工智能 Java 开发者
【Spring】原理解析:Spring Boot 自动配置
Spring Boot通过“约定优于配置”的设计理念,自动检测项目依赖并根据这些依赖自动装配相应的Bean,从而解放开发者从繁琐的配置工作中解脱出来,专注于业务逻辑实现。
2944 0
|
9月前
|
XML 安全 Java
使用 Spring 的 @Aspect 和 @Pointcut 注解简化面向方面的编程 (AOP)
面向方面编程(AOP)通过分离横切关注点,如日志、安全和事务,提升代码模块化与可维护性。Spring 提供了对 AOP 的强大支持,核心注解 `@Aspect` 和 `@Pointcut` 使得定义切面与切入点变得简洁直观。`@Aspect` 标记切面类,集中处理通用逻辑;`@Pointcut` 则通过表达式定义通知的应用位置,提高代码可读性与复用性。二者结合,使开发者能清晰划分业务逻辑与辅助功能,简化维护并提升系统灵活性。Spring AOP 借助代理机制实现运行时织入,与 Spring 容器无缝集成,支持依赖注入与声明式配置,是构建清晰、高内聚应用的理想选择。
826 0
|
监控 安全 Java
Spring AOP实现原理
本内容主要介绍了Spring AOP的核心概念、实现机制及代理生成流程。涵盖切面(Aspect)、连接点(Join Point)、通知(Advice)、切点(Pointcut)等关键概念,解析了JDK动态代理与CGLIB代理的原理及对比,并深入探讨了通知执行链路和责任链模式的应用。同时,详细分析了AspectJ注解驱动的AOP解析过程,包括切面识别、切点表达式匹配及通知适配为Advice的机制,帮助理解Spring AOP的工作原理与实现细节。
1627 13
|
8月前
|
XML Java 数据格式
《深入理解Spring》:AOP面向切面编程深度解析
Spring AOP通过代理模式实现面向切面编程,将日志、事务等横切关注点与业务逻辑分离。支持注解、XML和编程式配置,提供五种通知类型及丰富切点表达式,助力构建高内聚、低耦合的可维护系统。
|
8月前
|
XML Java 测试技术
《深入理解Spring》:IoC容器核心原理与实战
Spring IoC通过控制反转与依赖注入实现对象间的解耦,由容器统一管理Bean的生命周期与依赖关系。支持XML、注解和Java配置三种方式,结合作用域、条件化配置与循环依赖处理等机制,提升应用的可维护性与可测试性,是现代Java开发的核心基石。
|
8月前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
752 2
|
9月前
|
Java 数据库连接 网络安全
SSH框架的核心原理与工作流程解析
以上描述了SSH框架中各个部分的职责和大致的工作流程,详细运作时还涉及更多的组件和配置细节,每个部分都有相应的最佳实践和性能调优策略,但这些都建立在理解其核心原理基础之上。
615 11
|
存储 人工智能 自然语言处理
RAG 调优指南:Spring AI Alibaba 模块化 RAG 原理与使用
通过遵循以上最佳实践,可以构建一个高效、可靠的 RAG 系统,为用户提供准确和专业的回答。这些实践涵盖了从文档处理到系统配置的各个方面,能够帮助开发者构建更好的 RAG 应用。
6851 117