第七章节 spring AOP(上)

简介: 第七章节 spring AOP(上)

前言

Aspect Oriented Programming ,面向切面编程

1、AOP概念

Aspect Oriented Programming ,面向切面编程

1.1、目前流行的AOP框架

AOP 框架 说明
SpringAOP 是一款基于 AOP 编程的框架,它能够有效的减少系统间的重复代码,达到松耦合的目的。Spring AOP 使用纯 Java 实现,不需要专门的编译过程和类加载器,在运行期间通过代理方式向目标类植入增强的代码。Spring AOP 支持 2 种代理方式,分别是基于接口的 JDK 动态代理和基于继承的 CGLIB 动态代理。
AspectJ 是一个基于 Java 语言的 AOP 框架,从 Spring 2.0 开始,Spring AOP 引入了对 AspectJ 的支持。AspectJ 扩展了 Java 语言,提供了一个专门的编译器,在编译时提供横向代码的植入。

1.2、AOP术语

名称 说明
Joinpoint(连接点) AOP 的核心概念,指的是程序执行期间明确定义的一个点,例如方法的调用、类初始化、对象实例化等。在 Spring 中,连接点则指可以被动态代理拦截目标类的方法。
Pointcut(切入点) 又称切点,指要对哪些 Joinpoint 进行拦截,即被拦截的连接点。
Advice(通知) 指拦截到 Joinpoint 之后要执行的代码,即对切入点增强的内容。
Target(目标) 指代理的目标对象,通常也被称为被通知(advised)对象。
Weaving(织入) 指把增强代码应用到目标对象上,生成代理对象的过程。
Proxy(代理) 指生成的代理对象。
Aspect(切面) 切面是切入点(Pointcut)和通知(Advice)的结合。

1.3、Advice(增强处理)

通知 说明
before(前置通知) 通知方法在目标方法调用之前执行
after(后置通知) 通知方法在目标方法返回或异常后调用
after-returning(返回后通知) 通知方法会在目标方法返回后调用
after-throwing(抛出异常通知) 通知方法会在目标方法抛出异常后调用
around(环绕通知) 通知方法会将目标方法封装起来

1.4、AOP类型

1.4.1、动态 AOP

动态 AOP 的织入过程是在运行时动态执行的。其中最具代表性的动态 AOP 实现就是 Spring AOP,它会为所有被通知的对象创建代理对象,并通过代理对象对被原对象进行增强。

相较于静态 AOP 而言,动态 AOP 的性能通常较差,但随着技术的不断发展,它的性能也在不断的稳步提升。

动态 AOP 的优点是它可以轻松地对应用程序的所有切面进行修改,而无须对主程序代码进行重新编译。

1.4.2、静态 AOP

静态 AOP 是通过修改应用程序的实际 Java 字节码,根据需要修改和扩展程序代码来实现织入过程的。最具代表性的静态 AOP 实现是 AspectJ。

相较于动态 AOP 来说,性能较好。但它也有一个明显的缺点,那就是对切面的任何修改都需要重新编译整个应用程序。

1.5、在 Spring 框架中使用 AOP的优势

1、提供声明式企业服务;

2、允许用户实现自定义切面。在某些不适合用 OOP 编程的场景中,采用 AOP 来补充。

3、可以对业务逻辑的各个部分进行隔离,从而使业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时也提高了开发效率。

2、Spring AOP

代理技术 描述
JDK 动态代理 Spring AOP 默认的动态代理方式,若目标对象实现了若干接口,Spring 使用 JDK 的 java.lang.reflect.Proxy 类进行代理。
CGLIB 动态代理 若目标对象没有实现任何接口,Spring 则使用 CGLIB 库生成目标对象的子类,以实现对目标对象的代理。

2.1、连接点

Spring AOP 只支持一种连接点类型:方法调用

2.2、通知类型

通知类型 接口 描述
前置通知 org.springframework.aop.MethodBeforeAdvice 在目标方法执行前实施增强。
后置通知 org.springframework.aop.AfterAdvice 在目标方法执行后实施增强。
后置返回通知 org.springframework.aop.AfterReturningAdvice 在目标方法执行完成,并返回一个返回值后实施增强。
环绕通知 org.aopalliance.intercept.MethodInterceptor 在目标方法执行前后实施增强。
异常通知 org.springframework.aop.ThrowsAdvice 在方法抛出异常后实施增强。
引入通知 org.springframework.aop.IntroductionInterceptor 在目标类中添加一些新的方法和属性。

2.3、切面类型

在 Spring AOP 中,切面可以分为三类:一般切面、切点切面和引介切面。

切面类型 接口 描述
一般切面 org.springframework.aop.Advisor Spring AOP 默认的切面类型。

由于 Advisor 接口仅包含一个 Advice(通知)类型的属性,而没有定义 PointCut(切入点),因此它表示一个不带切点的简单切面。

这样的切面会对目标对象(Target)中的所有方法进行拦截并织入增强代码。由于这个切面太过宽泛,因此我们一般不会直接使用。
切点切面 org.springframework.aop.PointcutAdvisor Advisor 的子接口,用来表示带切点的切面,该接口在 Advisor 的基础上还维护了一个 PointCut(切点)类型的属性。使用它,我们可以通过包名、类名、方法名等信息更加灵活的定义切面中的切入点,提供更具有适用性的切面。
引介切面 org.springframework.aop.IntroductionAdvisor Advisor 的子接口,用来代表引介切面,引介切面是对应引介增强的特殊的切面,它应用于类层面上,所以引介切面适用 ClassFilter 进行定义。

2.3.1、 一般切面开发例子

package com.xxxx.spring.dao;
public interface NewsDAO {
    public void insert();
    public void delete();
    public void update();
    public void select();
}
package com.xxxx.spring.dao.impl;
import com.xxxx.spring.dao.NewsDAO;
public class UserDAOImpl implements NewsDAO {
    @Override
    public void insert() {
        System.out.println("执行UserDAOImpl的insert()方法");
    }
    @Override
    public void delete() {
        System.out.println("执行UserDAOImpl的delete()方法");
    }
    @Override
    public void update() {
        System.out.println("执行UserDAOImpl的update()方法");
    }
    @Override
    public void select() {
        System.out.println("执行UserDAOImpl的select()方法");
    }
}
package com.xxxx.spring.advice;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class NewsDAOAdvice implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("执行前置操作.....");
    }
}
<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <!--代理目标-->
    <bean id="newsDAO" class="com.xxxx.spring.dao.impl.UserDAOImpl"/>
    <!--定义前置增强-->
    <bean id="newsDAOAdvice" class="com.xxxx.spring.advice.NewsDAOAdvice"/>
    <!--生成代理对象-->
    <bean id="newsDAOProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!--设置代理目标-->
        <property name="target" ref="newsDAO"/>
        <!--实现接口-->
        <property name="proxyInterfaces" value="com.xxxx.spring.dao.NewsDAO"/>
        <!--增强bean名称-->
        <property name="interceptorNames" value="newsDAOAdvice"/>
    </bean>
</beans>

Java测试代码:

ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("newsdao.xml");
NewsDAO newsDAOProxy = classPathXmlApplicationContext.getBean("newsDAOProxy", NewsDAO.class);
newsDAOProxy.delete();
newsDAOProxy.insert();

2.3.2、 PointcutAdvisor 的 AOP 开发(带切点的切面)

Spring 提供了多个 PointCutAdvisor 的实现,其中常用实现类如如下。

  • NameMatchMethodPointcutAdvisor:指定 Advice 所要应用到的目标方法名称,例如 hello* 代表所有以 hello 开头的所有方法。
  • RegExpMethodPointcutAdvisor:使用正则表达式来定义切点(PointCut),RegExpMethodPointcutAdvisor 包含一个 pattern 属性,该属性使用正则表达式描述需要拦截的方法。
package com.xxxx.spring.dao.impl;
import com.xxxx.spring.dao.NewsDAO;
public class NewsDAOImpl implements NewsDAO {
    @Override
    public void insert() {
        System.out.println("执行UserDAOImpl的insert()方法");
    }
    @Override
    public void inserts() {
        System.out.println("执行UserDAOImpl的inserts()方法");
    }
    @Override
    public void delete() {
        System.out.println("执行UserDAOImpl的delete()方法");
    }
    @Override
    public void update() {
        System.out.println("执行UserDAOImpl的update()方法");
    }
    @Override
    public void select() {
        System.out.println("执行UserDAOImpl的select()方法");
    }
}
package com.xxxx.spring.advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class NewsDAOAroundAdvice implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("before");
        Object proceed = invocation.proceed();
        System.out.println("after");
        return proceed;
    }
}
<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <!--代理目标-->
    <bean id="newsDAO" class="com.xxxx.spring.dao.impl.NewsDAOImpl"/>
    <!--定义前置增强-->
    <bean id="newsDAOAdvice" class="com.xxxx.spring.advice.NewsDAOAroundAdvice"/>
    <!--定义切面-->
    <bean id="pointCutAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
        <!--<property name="patterns" value=".*"/>-->
        <property name="patterns" value="com.xxxx.spring.dao.impl.NewsDAOImpl.insert.*"/>
        <property name="advice" ref="newsDAOAdvice"/>
    </bean>
    <!--生成代理对象-->
    <bean id="newsDAOProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!--设置代理目标-->
        <property name="target" ref="newsDAO"/>
        <!--false JDK  true CGLIB-->
        <property name="proxyTargetClass" value="true"/>
        <!--增强bean名称-->
        <property name="interceptorNames" value="pointCutAdvisor"/>
    </bean>
</beans>


目录
相关文章
|
5月前
|
XML 安全 Java
使用 Spring 的 @Aspect 和 @Pointcut 注解简化面向方面的编程 (AOP)
面向方面编程(AOP)通过分离横切关注点,如日志、安全和事务,提升代码模块化与可维护性。Spring 提供了对 AOP 的强大支持,核心注解 `@Aspect` 和 `@Pointcut` 使得定义切面与切入点变得简洁直观。`@Aspect` 标记切面类,集中处理通用逻辑;`@Pointcut` 则通过表达式定义通知的应用位置,提高代码可读性与复用性。二者结合,使开发者能清晰划分业务逻辑与辅助功能,简化维护并提升系统灵活性。Spring AOP 借助代理机制实现运行时织入,与 Spring 容器无缝集成,支持依赖注入与声明式配置,是构建清晰、高内聚应用的理想选择。
642 0
|
9月前
|
监控 安全 Java
Spring AOP实现原理
本内容主要介绍了Spring AOP的核心概念、实现机制及代理生成流程。涵盖切面(Aspect)、连接点(Join Point)、通知(Advice)、切点(Pointcut)等关键概念,解析了JDK动态代理与CGLIB代理的原理及对比,并深入探讨了通知执行链路和责任链模式的应用。同时,详细分析了AspectJ注解驱动的AOP解析过程,包括切面识别、切点表达式匹配及通知适配为Advice的机制,帮助理解Spring AOP的工作原理与实现细节。
1417 13
|
4月前
|
XML Java 数据格式
《深入理解Spring》:AOP面向切面编程深度解析
Spring AOP通过代理模式实现面向切面编程,将日志、事务等横切关注点与业务逻辑分离。支持注解、XML和编程式配置,提供五种通知类型及丰富切点表达式,助力构建高内聚、低耦合的可维护系统。
|
6月前
|
人工智能 监控 安全
如何快速上手【Spring AOP】?核心应用实战(上篇)
哈喽大家好吖~欢迎来到Spring AOP系列教程的上篇 - 应用篇。在本篇,我们将专注于Spring AOP的实际应用,通过具体的代码示例和场景分析,帮助大家掌握AOP的使用方法和技巧。而在后续的下篇中,我们将深入探讨Spring AOP的实现原理和底层机制。 AOP(Aspect-Oriented Programming,面向切面编程)是Spring框架中的核心特性之一,它能够帮助我们解决横切关注点(如日志记录、性能统计、安全控制、事务管理等)的问题,提高代码的模块化程度和复用性。
|
XML Java 开发者
Spring Boot中的AOP实现
Spring AOP(面向切面编程)允许开发者在不修改原有业务逻辑的情况下增强功能,基于代理模式拦截和增强方法调用。Spring Boot通过集成Spring AOP和AspectJ简化了AOP的使用,只需添加依赖并定义切面类。关键概念包括切面、通知和切点。切面类使用`@Aspect`和`@Component`注解标注,通知定义切面行为,切点定义应用位置。Spring Boot自动检测并创建代理对象,支持JDK动态代理和CGLIB代理。通过源码分析可深入了解其实现细节,优化应用功能。
625 6
|
6月前
|
设计模式 Java 开发者
如何快速上手【Spring AOP】?从动态代理到源码剖析(下篇)
Spring AOP的实现本质上依赖于代理模式这一经典设计模式。代理模式通过引入代理对象作为目标对象的中间层,实现了对目标对象访问的控制与增强,其核心价值在于解耦核心业务逻辑与横切关注点。在框架设计中,这种模式广泛用于实现功能扩展(如远程调用、延迟加载)、行为拦截(如权限校验、异常处理)等场景,为系统提供了更高的灵活性和可维护性。
|
XML Java 测试技术
Spring AOP—通知类型 和 切入点表达式 万字详解(通俗易懂)
Spring 第五节 AOP——切入点表达式 万字详解!
932 25
|
XML 安全 Java
Spring AOP—深入动态代理 万字详解(通俗易懂)
Spring 第四节 AOP——动态代理 万字详解!
523 24
|
11月前
|
Java API 微服务
微服务——SpringBoot使用归纳——Spring Boot中的切面AOP处理——Spring Boot 中的 AOP 处理
本文详细讲解了Spring Boot中的AOP(面向切面编程)处理方法。首先介绍如何引入AOP依赖,通过添加`spring-boot-starter-aop`实现。接着阐述了如何定义和实现AOP切面,包括常用注解如`@Aspect`、`@Pointcut`、`@Before`、`@After`、`@AfterReturning`和`@AfterThrowing`的使用场景与示例代码。通过这些注解,可以分别在方法执行前、后、返回时或抛出异常时插入自定义逻辑,从而实现功能增强或日志记录等操作。最后总结了AOP在实际项目中的重要作用,并提供了课程源码下载链接供进一步学习。
1528 0