第七章节 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>


目录
相关文章
|
3月前
|
Java
Spring5入门到实战------9、AOP基本概念、底层原理、JDK动态代理实现
这篇文章是Spring5框架的实战教程,深入讲解了AOP的基本概念、如何利用动态代理实现AOP,特别是通过JDK动态代理机制在不修改源代码的情况下为业务逻辑添加新功能,降低代码耦合度,并通过具体代码示例演示了JDK动态代理的实现过程。
Spring5入门到实战------9、AOP基本概念、底层原理、JDK动态代理实现
|
10天前
|
XML Java 数据安全/隐私保护
Spring Aop该如何使用
本文介绍了AOP(面向切面编程)的基本概念和术语,并通过具体业务场景演示了如何在Spring框架中使用Spring AOP。文章详细解释了切面、连接点、通知、切点等关键术语,并提供了完整的示例代码,帮助读者轻松理解和应用Spring AOP。
Spring Aop该如何使用
|
1月前
|
存储 缓存 Java
Spring高手之路23——AOP触发机制与代理逻辑的执行
本篇文章深入解析了Spring AOP代理的触发机制和执行流程,从源码角度详细讲解了Bean如何被AOP代理,包括代理对象的创建、配置与执行逻辑,帮助读者全面掌握Spring AOP的核心技术。
37 3
Spring高手之路23——AOP触发机制与代理逻辑的执行
|
16天前
|
Java Spring
[Spring]aop的配置与使用
本文介绍了AOP(面向切面编程)的基本概念和核心思想。AOP是Spring框架的核心功能之一,通过动态代理在不修改原代码的情况下注入新功能。文章详细解释了连接点、切入点、通知、切面等关键概念,并列举了前置通知、后置通知、最终通知、异常通知和环绕通知五种通知类型。
27 1
|
12天前
|
安全 Java 测试技术
Java开发必读,谈谈对Spring IOC与AOP的理解
Spring的IOC和AOP机制通过依赖注入和横切关注点的分离,大大提高了代码的模块化和可维护性。IOC使得对象的创建和管理变得灵活可控,降低了对象之间的耦合度;AOP则通过动态代理机制实现了横切关注点的集中管理,减少了重复代码。理解和掌握这两个核心概念,是高效使用Spring框架的关键。希望本文对你深入理解Spring的IOC和AOP有所帮助。
25 0
|
2月前
|
设计模式 Java 测试技术
spring复习04,静态代理动态代理,AOP
这篇文章讲解了Java代理模式的相关知识,包括静态代理和动态代理(JDK动态代理和CGLIB),以及AOP(面向切面编程)的概念和在Spring框架中的应用。文章还提供了详细的示例代码,演示了如何使用Spring AOP进行方法增强和代理对象的创建。
spring复习04,静态代理动态代理,AOP
|
1月前
|
Java 编译器 Spring
Spring AOP 和 AspectJ 的区别
Spring AOP和AspectJ AOP都是面向切面编程(AOP)的实现,但它们在实现方式、灵活性、依赖性、性能和使用场景等方面存在显著区别。‌
69 2
|
1月前
|
Java Spring 容器
Spring IOC、AOP与事务管理底层原理及源码解析
【10月更文挑战第1天】Spring框架以其强大的控制反转(IOC)和面向切面编程(AOP)功能,成为Java企业级开发中的首选框架。本文将深入探讨Spring IOC和AOP的底层原理,并通过源码解析来揭示其实现机制。同时,我们还将探讨Spring事务管理的核心原理,并给出相应的源码示例。
127 9
|
1月前
|
XML Java 数据格式
Spring的IOC和AOP
Spring的IOC和AOP
45 0
|
2月前
|
Java 数据库连接 数据库
Spring基础3——AOP,事务管理
AOP简介、入门案例、工作流程、切入点表达式、环绕通知、通知获取参数或返回值或异常、事务管理
Spring基础3——AOP,事务管理