AOP面向切面编程),可以说是OOP面向对象编程)的补充和完善。OOP引入封装、继承多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。

当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。

例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。

这种散布在各处的无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。

AOP技术则恰恰相反,它利用一种称为横切技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为Aspect,即切面

所谓切面,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码降低模块间的耦合度,并有利于未来的可操作性可维护性

AOP代表的是一个横向的关系,如果说“对象”是一个空心的圆柱体,其中封装的是对象的属性和行为;那么面向方面编程的方法,就仿佛一把利刃,将这些空心圆柱体剖开,以获得其内部的消息,然后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹。

AOP的基本概念

  1. Aspect(切面):Aspect 声明类似于 Java 中的类声明,在 Aspect 中会包含着一些 Pointcut 以及相应的
    Advice。

  2. Joint point(连接点):表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等,它自身还可以嵌套其它joint point。

  3. Pointcut(切点):表示一组 joint point,这些 joint point
    或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了相应的 Advice 将要发生的地方。

  4. Advice(增强):Advice 定义了在 Pointcut 里面定义的程序点具体要做的操作,它通过 before、after 和 around 来区别是在每个 joint point 之前、之后还是代替执行的代码。

  5. Target(目标对象):织入 Advice 的目标对象.。

  6. Weaving(织入):将 Aspect 和其他对象连接起来, 并创建
    Adviced object 的过程

通知方法:

      1. 前置通知:在我们执行目标方法之前运行(@Before)

      2. 后置通知:在我们目标方法运行结束之后 ,不管有没有异常(@After)

      3. 返回通知:在我们的目标方法正常返回值后运行(@AfterReturning)

      4. 异常通知:在我们的目标方法出现异常后运行(@AfterThrowing)

      5. 环绕通知:动态代理, 需要手动执行joinPoint.procced()(其实就是执行我们的目标方法执行之前相当于前置通知,执行之后就相当于我们后置通知(@Around)

AOP代码示范

下面以一个AOP日志功能的例子进行代码的演示,具体的代码如下所示:

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*; /**
* @Description:切面日志类
* @author: 张重虎
* @Date: 2022/2/8 14:58
* @Copyright: Xi'an Dian Tong Software Co., Ltd. All Rights Reserved.
* @Version 1.0
*/
@Aspect
public class LogAspect {
@Pointcut("execution(* com.example.zhangchonghu.demo.controller.aop.Calculator .*(..))")
public void pointCut(){}; /**
* 前置通知:在我们执行目标方法之前运行(@Before)
*/
@Before("pointCut()")
public void logStart(){
System.out.println("除法运行....参数列表是:{}");
} /**
* 后置通知:在我们目标方法运行结束之后 ,不管有没有异常(@After)
*/
@After("pointCut()")
public void logEnd(){
System.out.println("除法结束......");
} /**
* 返回通知:在我们的目标方法正常返回值后运行(@AfterReturning)
*/
@AfterReturning("pointCut()")
public void logReturn(){
System.out.println("除法正常返回......运行结果是:{}");
} /**
* 异常通知:在我们的目标方法出现异常后运行(@AfterThrowing)
*/
@AfterThrowing("pointCut()")
public void logException(){
System.out.println("异常通知");
} /**
* 环绕通知:动态代理, 需要手动执行joinPoint.procced()(其实就是执行我们的目标方法执行之前相当于前置通知,执行之后就相当于我们后置通知(@Around)
* @param proceedingJoinPoint 切点
* @return
* @throws Throwable
*/
@Around("pointCut()")
public Object logAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{
System.out.println("执行目标方法之前");
//调用方法
Object obj = proceedingJoinPoint.proceed();
System.out.println("@Arount:执行目标方法之后...");
return obj;
}
}

@Pointcut("execution(* com.savage.aop.Calculator .*(..))"),括号中各个pattern分别表示:

  • 第一个*表示返回值匹配,可以为*表示任何返回值, 全路径的类名等

  • com.savage.aop表示类路径匹配

  • 第二个*表示方法名匹配,可以指定方法名 或者*代表所有, set* 代表以set开头的所有方法

  • (..)表示参数匹配:可以指定具体的参数类型,多个参数间用“,”隔开,各个参数也可以用""来表示匹配任意类型的参数,".."表示零个多个任意参数。如(String)表示匹配一个String参数的方法;(,String)表示匹配有两个参数的方法,第一个参数可以是任意类型,而第二个参数String类型。异常类型匹配(throws-pattern?)

目标方法:

/**
* @Description: 切面目标
* @author: 张重虎
* @Date: 2022/2/8 15:04
* @Copyright: Xi'an Dian Tong Software Co., Ltd. All Rights Reserved.
* @Version 1.0
*/
public class Calculator {
public int div(int i, int j){
System.out.println("--------");
return i/j;
}
}

配置类:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy; /**
* @Description: 切面配置类
* @author: 张重虎
* @Date: 2022/2/8 15:05
* @Copyright: Xi'an Dian Tong Software Co., Ltd. All Rights Reserved.
* @Version 1.0
*/
@Configuration
@EnableAspectJAutoProxy
public class MyAspectConfig {
@Bean
public Calculator calculator(){
return new Calculator();
} @Bean
public LogAspect logAspects(){
return new LogAspect ();
}
}

测试类:

import com.example.zhangchonghu.demo.controller.aop.Calculator;
import com.example.zhangchonghu.demo.controller.aop.MyAspectConfig;
import org.junit.jupiter.api.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; /**
* @Description:
* @author: 张重虎
* @Date: 2022/2/8 15:05
* @Copyright: Xi'an Dian Tong Software Co., Ltd. All Rights Reserved.
* @Version 1.0
*/
public class TestLogAop {
@Test
public void test(){
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(MyAspectConfig.class);
Calculator c = app.getBean(Calculator.class);
int result = c.div(4, 3);
System.out.println(result);
app.close();
}
}

运行结果:

spring---面向切面(AOP @Pointcut 表达式篇)的更多相关文章

  1. Spring框架使用(控制反转,依赖注入,面向切面AOP)

    参见:http://blog.csdn.net/fei641327936/article/details/52015121 Mybatis: 实现IOC的轻量级的一个Bean的容器 Inversion ...

  2. Spring 面向切面编程(AOP)

    Spring 系列教程 Spring 框架介绍 Spring 框架模块 Spring开发环境搭建(Eclipse) 创建一个简单的Spring应用 Spring 控制反转容器(Inversion of ...

  3. Spring事务管理—aop:pointcut expression 常见切入点表达式及事务说明

    Spring事务管理—aop:pointcut expression 常见切入点表达式及事物说明 例: <aop:config>  <aop:pointcut expression= ...

  4. 快速高效掌握企业级项目中的Spring面向切面编程应用,外带讲面试技巧

    Spring面向切面编程(AOP)是企业级应用的基石,可以这样说,如果大家要升级到高级程序员,这部分的知识必不可少. 这里我们将结合一些具体的案例来讲述这部分的知识,并且还将给出AOP部分的一些常见面 ...

  5. Spring框架系列(五)--面向切面AOP

    背景: 当需要为多个不具有继承关系的对象引入一个公共行为,例如日志.权限验证.事务等功能时,如果使用OOP,需要为每个对象引入这些公共 行为.会产生大量重复代码,并且不利用维护.AOP就是为了解决这个 ...

  6. Spring——面向切面编程(AOP)详解

    声明:本博客仅仅是一个初学者的学习记录.心得总结,其中肯定有许多错误,不具有参考价值,欢迎大佬指正,谢谢!想和我交流.一起学习.一起进步的朋友可以加我微信Liu__66666666 这是简单学习一遍之 ...

  7. 解析Spring第三天(面向切面AOP)

    面向切面:AOP 在不修改源代码的基础上,对方法进行增强.AOP的底层原理就是代理技术(第一种:jdk的动态代理(编写程序必须要有接口).第二种:cglib代理技术(生成类的子类).如果编写的程序有借 ...

  8. Spring基础(二)_面向切面(AOP)

    面向切面编程 面向切面编程[AOP,Aspect Oriented Programming]:通过预编译方式和运行期间动态代理实现程序功能的统一维护的技术.AOP 是 Spring 框架中的一个重要内 ...

  9. Spring面向切面编程(AOP)

    1 spring容器中bean特性 Spring容器的javabean对象默认是单例的. 通过在xml文件中,配置可以使用某些对象为多列. Spring容器中的javabean对象默认是立即加载(立即 ...

  10. 详解Spring面向切面编程(AOP)三种实现

    一.什么是AOP AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善. ...

随机推荐

  1. you-get的使用

    转载自: 利用Python下载:You-Get的安装及使用方法 - 宁佳兵 - 博客园   宁佳兵 所谓的光辉岁月,并不是后来闪耀的日子,而是无人问津时,对梦想的偏执. 博客园 首页 标签 GitHu ...

  2. redis 中的 list

    lpush K1 V1 V2 V3   左边加入list rpush k1 v1 v2 v3 右边加入list lpop k1 左边吐出一个值 rpop k1 右边吐出一个值 lrange k1 0 ...

  3. Cilium 系列-7-Cilium 的 NodePort 实现从 SNAT 改为 DSR

    系列文章 Cilium 系列文章 前言 将 Kubernetes 的 CNI 从其他组件切换为 Cilium, 已经可以有效地提升网络的性能.但是通过对 Cilium 不同模式的切换/功能的启用,可以 ...

  4. 园子的商业化努力-阿里云开发者社区合作:RDS MySQL Serverless 免费试用活动

    阿里云开发者社区这个月组织了一个针对"云数据库 RDS MySQL Serverless 版"免费试用用户的做任务活动,上周找园子合作,希望能在园子里推广一下这个活动. 由于时间太 ...

  5. 【技术积累】Linux中的命令行【理论篇】【二】

    ag命令 命令介绍 ag命令是一个用于在Linux系统中进行文本搜索的工具.它是基于Silver Searcher的改进版本,具有更快的搜索速度和更强大的功能. ag命令的基本用法是在指定的目录中搜索 ...

  6. 发布关于PostGIS对于USD格式的拓展

    我们非常高兴的发布为了一年一度的SIGGRAPH 2023发布关于为PostGIS支持USD格式的新拓展. 新添加了3个函数 ST_AsUSDA(geom geometry, usd_root_nam ...

  7. [docker]封装python的docker镜像

    前言 基于alpine的python镜像封装. docker pull python:3.10-alpine 准备 requirements.txt内容: fastapi uvicorn server ...

  8. Programming abstractions in C阅读笔记:p107-p110

    <Programming Abstractions In C>学习第46天,p107-p110,3.1小节--"The concept of interface",总结 ...

  9. 领域驱动设计(DDD):从基础代码探讨高内聚低耦合的演进

    大家好,我是付威,一名已在编码第一线奋斗了十余年的程序员.在2019年我初次接触到领域驱动设计(Domain-Driven Design,简称DDD)的概念.在我的探索中,我发现许多有关DDD的教程过 ...

  10. 史上最强.NET数据分页方法

    [前言] 本文讲述的.NET数据分页方法为[史上最强],已被多家大型科技公司实战采用 & 也被圈内多家知名IT培训机构转载收藏. [正文] 支持.Net Core(2.0及以上)与.Net F ...