切面的魔力:解密Spring AOP 面向切面编程

这篇具有很好参考价值的文章主要介绍了切面的魔力:解密Spring AOP 面向切面编程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、AOP简介

1.1 什么是AOP ?

1.2 什么是面向切面编程 ?

1.3 AOP 的特点

二、 AOP的基本概念解读

2.1 AOP的基本概念

2.2 AOP 概念趣事解读

三、代码情景演示

3.1 编写目标对象(超级英雄们正常的行动)

3.2 编写通知类

3.2.1 前置通知

3.2.2 后置通知

3.2.3 异常通知

3.2.4 环绕通知

3.3 spring核心xml文件配置

3.4 测试运行

3.5 配置过滤通知后测试

总结


一、AOP简介

1.1 什么是AOP ?

        AOP(Aspect-Oriented Programming)是一种软件开发技术,旨在通过将横切关注(cross-cutting concerns)从主要业务逻辑中分离出来,提供更好的模块化和可维护性。AOP通过在程序执行过程中动态地将这些关注点织入到代码中,从而实现了代码的解耦和重用。

1.2 什么是面向切面编程 ?

        面向切面编程(Aspect-Oriented Programming)是AOP的一种具体实现方式。它通过将横切关注点(cross-cutting concerns)从主要业务逻辑中分离出来,以切面(Aspect)的形式进行模块化。切面定义了在何处和何时应该应用横切关注点。切面通常由切点(Pointcut)和通(Advice)组成。

1.3 AOP 的特点

  1. 横切关注点的模块化:AOP允许将与业务逻辑无关的横切关注点(如日志记录、事务管理、安全性等)从主要业务逻辑中分离出来,以切面的形式进行统一管理。这样可以提高代码的可维护性,使开发人员能够更好地关注核心业务逻辑。

  2. 解耦和重用:通过将横切关注点从主要业务逻辑中分离出来,AOP实现了代码的解耦。这意味着可以更容易地修改、扩展和重用横切关注点,而无需修改主要业务逻辑。这提高了代码的可重用性和可维护性。

  3. 声明式编程:AOP允许开发人员通过声明式的方式将切面应用到目标对象中,而无需在目标对象的代码中显式地编写切面逻辑。这使得代码更加清晰、简洁,并且易于理解和维护。

  4. 动态织入:AOP允许在程序运行时动态地将切面织入到目标对象中。这意味着可以根据需要选择性地应用切面,而无需在编译时或加载时进行硬编码。这提供了更大的灵活性和可配置性。

  5. 提高系统性能:AOP可以将一些通用的横切关注点(如性能监控、缓存管理等)应用到多个目标对象中,从而提高系统的性能和效率。这避免了在每个目标对象中重复编写相同的代码。

        总的来说,AOP的特点包括横切关注点的模块化、解耦和重用、声明式编程、动态织入以及提高系统性能。这些特点使得AOP成为一种强大的技术,可以提高代码的可维护性、可重用性和可测试性,同时降低代码的复杂性和重复性。

二、 AOP的基本概念解读

2.1 AOP的基本概念

  1. 切面(Aspect):切面是一个模块化的单元,它封装了与横切关注点相关的行为。切面可以包含通知和切点。

  2. 连接点(Join Point):连接点是在应用程序执行过程中可以插入切面的点。它可以是方法调用、方法执行、异常抛出等。(也将Pointcut理解成一个条件 ,此条件决定了容器在什么情况下将通知和目标组合成代理返回给外部程序)

  3. 切点(Pointcut):切点定义了在哪些连接点上应用切面。它使用表达式来匹配连接点,例如指定特定的类、方法、注解等。

  4. 通知(Advice):通知是切面在特定连接点上执行的动作。常见的通知类型包括前置通知(Before)、后置通知(After)、返回通知(After Returning)和异常通知(After Throwing)。

  5. 引入(Introduction):引入允许在现有类中添加新的方法和属性。它允许将新功能引入到现有的类中,而无需修改类的源代码。

  6. 织入(Weaving):织入是将切面应用到目标对象中并创建新的代理对象的过程。织入可以在编译时、类加载时或运行时进行。

  7. AOP代理(Proxy):AOP框架创建的对象,代理就是对目标对象的加强。Spring中的AOP代理可以是JDK动态代理,也可以是CGLIB代理,前者基于接口,后者基于子类。(代理=目标+通知)    注:只有代理对象才有AOP功能,而AOP的代码是写在通知的方法里面的

  8. 目标对象(Target): 包含连接点的对象,被通知(被代理)的对象,完成具体的业务逻辑 。

2.2 AOP 概念趣事解读

        AOP最多的就是概念,面对这么概念我们大多数人是记不住的。特别是像博主这样的越看感觉都要长脑子了,所以我准备一个小故事来解读AOP各功能(术语)的解读。

《 这是一个好故事 》

        小猪侠是一个勇敢而机智的超级英雄,他的使命是保护城市的和平与安全。他有一个特殊的能力,可以通过棒棒糖来赋予他人额外的力量和技能。这个棒棒糖就是它的 " 切面(Aspect)"。

        小猪侠的切面是一个模块化的单元,它封装了与超级英雄相关的行为。他的切面包含了一些 通知(Advice),这些通知定义了在特定的情境(连接点)下给其他超级英雄赋予的额外力量和技能。连接点(Join Point)可以是超级英雄的战斗、救援行动、危机处理等。

        为了将它的切面应用到超级英雄身上,小猪侠需要创建一个 代理(Proxy)。代理是一个中间人,它将超级英雄包装起来,并在必要时调用切面中定义的通知。代理使得超级英雄在执行任务时能够自动获得额外的力量和技能。

        超级英雄们在执行任务时,并不知道小猪侠的切面和代理的存在。他们只需要按照正常的方式进行战斗和救援,而不需要关注切面的实现细节。这就是 目标对象(Target)的作用。目标对象是超级英雄们正常的行动,而切面和代理则为他们提供了额外的力量和技能。

        一天,小猪侠遇到了一个危机,城市中的一座大桥即将坍塌。他需要帮助其他超级英雄一起救援。小猪侠使用他的切面技能,创建了一个前置通知,它会在超级英雄们展开救援行动之前被触发。

        小猪侠将他的切面应用到超级英雄们身上,通过代理来调用他们的救援行动。当超级英雄们准备展开救援行动时,切面中的前置通知被触发,小猪侠使用棒棒糖赋予他们额外的力量和技能,使得他们能够成功救援并修复大桥。

        在这个故事中,小猪侠的切面代表了它的棒棒糖,连接点是超级英雄们展开救援行动的位置,代理是将切面应用到超级英雄们身上的中间人,通知是切面中定义的赋予额外力量和技能的动作,目标对象是超级英雄们正常的行动,织入是将切面应用到目标对象中的过程。

三、代码情景演示

3.1 编写目标对象(超级英雄们正常的行动)

1. 为了降低代码耦合性,首先编写一个动作行为的接口定义发动技能和飞行的方法。

package com.ycxw.aop.biz;

/**
 * @author 云村小威
 * @site blog.csdn.net/Justw320
 * @create 2023-08-17 16:08
 */
public interface Behavior {
	// 飞行
	public boolean fly(String name);

	// 发动技能
	public void skill(String name, String skills);
}

2. 编写实现接口的类

package com.ycxw.aop.biz.impl;

import com.ycxw.aop.biz.Behavior;
/**
 * @author 云村小威
 * @site blog.csdn.net/Justw320
 * @create 2023-08-17 16:15
 */
public class BehaviorImpl implements Behavior {

	public BehaviorImpl() {
		super();
	}


	@Override
	public boolean fly(String name) {
		System.out.println("超级英雄:"+name);
		return true;
	}

	@Override
	public void skill(String name, String skills) {
		System.out.println("超级英雄:"+name+" 发动了"+skills);
	}
}

3.2 编写通知类

通知:是切面中定义的赋予额外力量和技能的动作

3.2.1 前置通知

在目标对象使用前执行:

package com.ycxw.aop.advice;

import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * 前置通知
 * @author 云村小威
 * @site blog.csdn.net/Justw320
 * @create 2023-08-17 16:20
 */
public class MyMethodBeforeAdvice implements MethodBeforeAdvice {

    @Override
    public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
        //在这里,可以获取到目标类的全路径及方法及方法参数,然后就可以将他们写到日志表里去
        String target = arg2.getClass().getName();
        String methodName = arg0.getName();
        String args = Arrays.toString(arg1);
        System.out.println("【前置通知:系统日志】:"+target+"."+methodName+"("+args+") 被调用了");

    }
}

3.2.2 后置通知

在目标对象使用完后执行:

package com.ycxw.aop.advice;

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * 后置通知
 * @author 云村小威
 * @site blog.csdn.net/Justw320
 * @create 2023-08-17 16:48
 */
public class MyAfterReturningAdvice implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
        String target = arg3.getClass().getName();
        String methodName = arg1.getName();
        String args = Arrays.toString(arg2);
        System.out.println("【后置通知:】:"+target+"."+methodName+"("+args+") 被调用了,"+"该方法被调用后的返回值为:"+arg0);

    }
}

3.2.3 异常通知

当运行发生异常执行该通知:

package com.ycxw.aop.advice;

import com.ycxw.aop.exception.PriceException;
import org.springframework.aop.ThrowsAdvice;

/**
 * 异常通知
 * @author 云村小威
 * @site blog.csdn.net/Justw320
 * @create 2023-08-17 17:00
 */
public class MyThrowsAdvice implements ThrowsAdvice {
    public void afterThrowing(PriceException ex) {
        System.out.println("【异常通知】:当技能施展发生异常,那么执行此处代码块!!!");
    }

}

3.2.4 环绕通知

这个在平常是用的最多的,比较便捷,相当于结合前置和后置的通知功能。

package com.ycxw.aop.advice;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import java.util.Arrays;

/**
 * @author 云村小威
 * @site blog.csdn.net/Justw320
 * @create 2023-08-17 16:54
 */
public class MyMethodInterceptor implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation arg0) throws Throwable {
        String target = arg0.getThis().getClass().getName();
        String methodName = arg0.getMethod().getName();
        String args = Arrays.toString(arg0.getArguments());
        System.out.println("【环绕通知调用前:】:"+target+"."+methodName+"("+args+")被调用了");
//		arg0.proceed()就是目标对象的方法
        Object proceed = arg0.proceed();
        System.out.println("【环绕通知调用后:】:该方法被调用后的返回值为:"+proceed);
        return proceed;

    }
}

3.3 spring核心xml文件配置

<?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.xsd">

    <!--  目标对象  -->
    <bean class="com.ycxw.aop.biz.impl.BehaviorImpl" id="behavior"></bean>
<!-- 通知  -->
    <bean class="com.ycxw.aop.advice.MyMethodBeforeAdvice" id="beforeAdvice"></bean>
    <bean class="com.ycxw.aop.advice.MyAfterReturningAdvice" id="afterAdvice"></bean>
    <bean class="com.ycxw.aop.advice.MyMethodInterceptor" id="interceptor"></bean>
    <bean class="com.ycxw.aop.advice.MyThrowsAdvice" id="throwsAdvice"></bean>
   
<!--  代理  ProxyFactoryBean类似于工厂模式(直接配置)-->
    <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="behaviorProxy">
    <!--   配置目标对象   -->
        <property name="target" ref="behavior"></property>
        <!--配置代理目标对象的接口 cglid动态代理-->
        <property name="proxyInterfaces">
            <list>
                <value>com.ycxw.aop.biz.Behavior</value>
            </list>
        </property>
        <!--配置通知-->
        <property name="interceptorNames">
            <list>
                <value>beforeAdvice</value>
                <value>afterAdvice</value>
                <value>interceptor</value>
                <value>throwsAdvice</value>
            </list>
        </property>
    </bean>
</beans>

3.4 测试运行

1. 编写测试类

package com.ycxw.aop.demo;

import com.ycxw.aop.biz.Behavior;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author 云村小威
 * @site blog.csdn.net/Justw320
 * @create 2023-08-17 16:08
 */
public class demo1 {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");
        Behavior bean = (Behavior) context.getBean("behaviorProxy");
        bean.fly("小威");
        bean.skill("小威","变大技能");
    }
}

2. 运行结果

切面的魔力:解密Spring AOP 面向切面编程,Spring,spring,java,后端,intellij-idea

 由此可见,应证了前面的通知。可看到环绕通知跟前置和、后置通知处于等效功能,而环绕通知更为简便。

3.5 配置过滤通知后测试

这里过滤了后置通知:

<?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.xsd">

<!--AOP-->
    <!--  目标对象  -->
    <bean class="com.ycxw.aop.biz.impl.BehaviorImpl" id="behavior"></bean>
<!-- 通知  -->
    <bean class="com.ycxw.aop.advice.MyMethodBeforeAdvice" id="beforeAdvice"></bean>
    <bean class="com.ycxw.aop.advice.MyAfterReturningAdvice" id="afterAdvice"></bean>
    <bean class="com.ycxw.aop.advice.MyMethodInterceptor" id="interceptor"></bean>
    <bean class="com.ycxw.aop.advice.MyThrowsAdvice" id="throwsAdvice"></bean>
    <!--过滤-->
    <bean class="org.springframework.aop.support.RegexpMethodPointcutAdvisor" id="regexpAdvisor">
        <!--配置需要过滤的通知-->
        <property name="advice" ref="afterAdvice"></property>
        <!--通过正则过滤指定方法-->
        <property name="pattern" value=".*skill"></property>
    </bean>

<!--  代理  ProxyFactoryBean类似于工厂模式(直接配置)-->
    <bean class="org.springframework.aop.framework.ProxyFactoryBean" id="behaviorProxy">
    <!--   配置目标对象   -->
        <property name="target" ref="behavior"></property>
        <!--配置代理目标对象的接口 cglid动态代理-->
        <property name="proxyInterfaces">
            <list>
                <value>com.ycxw.aop.biz.Behavior</value>
            </list>
        </property>
        <!--配置通知-->
        <property name="interceptorNames">
            <list>
                <value>beforeAdvice</value>
                <value>regexpAdvisor</value>
                <value>throwsAdvice</value>
            </list>
        </property>
    </bean>
</beans>

切面的魔力:解密Spring AOP 面向切面编程,Spring,spring,java,后端,intellij-idea

由运行结果可见,等代码执行完后才执行后置通知,在前面的fly方法后才过滤的后置通知。

总结

        AOP是面向切面编程,它通过在程序执行过程中动态地将横切关注点织入到代码中来实现。当程序执行到目标对象的目标方法时,AOP可以在方法调用前、后或异常抛出时执行相应的通知。

        具体来说,如果连接点上有前置通知,AOP会先执行前置通知,然后再执行目标方法。前置通知可以在目标方法执行之前执行一些预处理操作,如日志记录、参数验证等。

        如果没有前置通知,AOP会直接执行目标方法。然后,AOP会检查目标方法上是否有后置通知。如果有后置通知,AOP会在目标方法执行后执行后置通知。后置通知可以在目标方法执行之后执行一些后处理操作,如结果处理、资源释放等。

        除了前置和后置通知,AOP还支持异常通知和环绕通知。异常通知可以在目标方法抛出异常时执行一些处理逻辑。环绕通知是最强大的通知类型,它可以完全控制目标方法的执行过程,包括在方法调用前后执行自定义的逻辑。

        需要注意的是,虽然通知代码通常是非业务核心代码,如日志记录和事务管理,但并不是所有的通知都是非业务核心代码。有些通知可能涉及到业务逻辑,例如在目标方法执行前进行权限检查。AOP的灵活性和可配置性使得开发人员可以根据具体需求来定义和应用切面,以实现代码的解耦和重用,提高代码的可维护性和可测试性。文章来源地址https://www.toymoban.com/news/detail-665469.html

到了这里,关于切面的魔力:解密Spring AOP 面向切面编程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring AOP(面向切面编程)和方法拦截

    Spring AOP(面向切面编程)和方法拦截 Spring是一款广泛使用的Java开发框架,提供了丰富的功能和工具,用于简化企业级应用程序的开发。其中一个重要的特性是面向切面编程(AOP)和方法拦截。本文将介绍Spring AOP和方法拦截的概念、工作原理以及在实际开发中的应用。 在软

    2024年02月05日
    浏览(45)
  • JAVA:使用 Spring AOP 实现面向切面编程

    1、简述 在现代的软件开发中,面向切面编程(AOP)是一种重要的编程范式,它允许我们将横切关注点(如日志记录、性能监控、事务管理等)从应用程序的核心业务逻辑中分离出来,以提高代码的模块化和可维护性。Spring 框架提供了强大的 AOP 支持,使得我们可以轻松地实

    2024年04月13日
    浏览(45)
  • 【Java 初级】Spring核心之面向切面编程(AOP)

    tip:作为程序员一定学习编程之道,一定要对代码的编写有追求,不能实现就完事了。我们应该让自己写的代码更加优雅,即使这会费时费力。 💕💕 推荐: 体系化学习Java(Java面试专题) AOP(面向切面编程)是一种编程范式,用于将横切关注点(如日志记录、性能统计等

    2024年02月04日
    浏览(51)
  • spring6-AOP面向切面编程

    1、场景模拟 搭建子模块:spring6-aop 1.1、声明接口 声明计算器接口Calculator,包含加减乘除的抽象方法 1.2、创建实现类 1.3、创建带日志功能的实现类 1.4、提出问题 ①现有代码缺陷 针对带日志功能的实现类,我们发现有如下缺陷: 对核心业务功能有干扰,导致程序员在开发核

    2024年02月08日
    浏览(54)
  • 【Spring AOP】结合日志面向切面编程 两种写法

            这里需要提前了解什么是Spring的AOP(Aspect Oriented Programming)。是在OOP(面向对象)思想的一种拓展思想。 简单来说就是将某个代码块嵌入到其它的代码块中 。笔者先前学Spring也有学什么IoC啊AOP啊,但实际上没有用过、就那听过学过没啥用的。。没会儿就忘记了。

    2024年02月13日
    浏览(44)
  • Spring AOP使用指南: 强大的面向切面编程技术

    🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页 ——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文并茂🦖生动形象🐅简单易学!欢迎大家来踩踩~🌺 🌊 《IDEA开发秘籍专栏》 🐾 学会IDEA常用操作,工作效率翻倍~💐 🌊 《100天精通Golang(基础

    2024年02月09日
    浏览(51)
  • Spring AOP (面向切面编程)原理与代理模式—实例演示

    Spring 中文文档 (springdoc.cn) Spring | Home 官网         Java是一个面向对象(OOP)的语言,但它有一些弊端。虽然使用OOP可以通过组合或继承的方式来实现代码的重用。但当我们需要为多个不具有继承关系的对象(一般指的是两个不同的类,它们之间没有继承自同一个父类或接

    2024年02月15日
    浏览(56)
  • 【JavaEE】面向切面编程AOP是什么-Spring AOP框架的基本使用

    【JavaEE】 AOP(1) 1.1 AOP 与 Spring AOP AOP ( A spect O riented P rogramming),是一种思想,即 面向切面编程 Spring AOP 则是一个框架,Spring项目中需要引入依赖而使用 AOP和Spring AOP的关系就相当于IoC和DI Spring AOP让开发者能够半自动的开发AOP思想下实现的功能 1.2 没有AOP的世界是怎样的

    2024年02月11日
    浏览(47)
  • Spring AOP:面向切面编程在实际项目中的应用

    🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页 ——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文并茂🦖生动形象🐅简单易学!欢迎大家来踩踩~🌺 🌊 《IDEA开发秘籍专栏》 🐾 学会IDEA常用操作,工作效率翻倍~💐 🌊 《100天精通Golang(基础

    2024年02月09日
    浏览(45)
  • 【Spring】一文带你吃透AOP面向切面编程技术(上篇)

    个人主页: 几分醉意的CSDN博客_传送门 什么是AOP? AOP(Aspect Orient Programming):面向切面编程 Aspect:表示切面,给业务方法增加的功能,叫做切面。切面一般都是非业务功能,而且切面功能一般都是可以复用的。例如日志功能,事务功能,权限检查,参数检查,统计信息等等

    2024年01月16日
    浏览(65)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包