当前位置: 首页 > wzjs >正文

衡水做网站网上购物系统

衡水做网站,网上购物系统,连云港市赣榆区建设局网站,WordPress显示不出广告1. AOP AOP(Aspect-Oriented Programming), 是一种思想, 面向切面编程。 在前文统一异常处理,统一结果返回就是使用了这一思想(都是在集中处理某一类事情, 但又不影响原有代码的正常运行),但他们不是AOP,只是应用了这…

1. AOP

AOP(Aspect-Oriented Programming), 是一种思想, 面向切面编程。

在前文统一异常处理,统一结果返回就是使用了这一思想(都是在集中处理某一类事情, 但又不影响原有代码的正常运行),但他们不是AOP,只是应用了这一思想。

共同点就是:不修改目标方法,而达到了对目标方法功能的增强(就像MybatisPlus对Mybatis) 

AOP是一种思想, 实现它的方式有很多: SpringAOP, AspectJ, CGLIB, ....等

Spring 共有两大核心机制, 一个是 Spring IoC, 一个就是 Spring AOP.

在这句话中,第一个 "Spring" 指的是 Spring Framework,而不是 Spring Boot。

原因是,Spring IoC(控制反转)和 Spring AOP(面向切面编程)是 Spring Framework 的两大核心特性。这些特性是 Spring Framework 的基础,Spring Boot 则是在 Spring Framework 的基础上进行封装和简化配置,使得开发者能更快速地构建应用。

Spring IoC 主要负责对象的管理和依赖注入。

Spring AOP 用于面向切面编程,通过代理机制提供横切关注点(如日志、事务管理等)。

Spring Boot 作为 Spring Framework 的扩展,简化了配置和开发流程,但核心机制(如 IoC 和 AOP)依然是基于 Spring Framework 的。所以当提到 "Spring 的核心机制" 时,通常是指 Spring Framework 中的 IoC 和 AOP。 

关于面向切面编程的讲解会在应用中体现 

2. Spring AOP 入门

2.1 引入 Spring AOP 依赖

Spring AOP 依赖不能在创建项目时引入, 必须手动引入

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>

2.2 Spring AOP 简单使用

我们使用 Spring AOP 编写一个程序, 记录接口的执行时长.

@Slf4j
@Aspect
@Component
public class TimeAspect {//公共切点表达式@Pointcut("@annotation(com.cym.spring_aop.aspect.MyAspect)")private void pt(){}@Around("pt()")public Object recordTime(ProceedingJoinPoint pjp) throws Throwable {//记录方法执行前的时间long begin = System.currentTimeMillis();//方法执行Object result = pjp.proceed();//记录方法执行后的时间long end = System.currentTimeMillis();log.info(pjp.getSignature() + ",耗费时间:{}" , end - begin);return result;}
}

如上图所示, 通过 Spring AOP, 我们只需在外部通过 Spring AOP 就可以获取到接口的执行时长. 达到了 "获取执行时长" 这一功能和业务代码的解耦

如果不使用 Spring AOP, 我们就需要在每个接口的起始位置和结束位置获取时间戳, 再计算执行时长, 这样不仅入侵了业务代码, 还需要手动对每个要实现这个功能的接口都编写这些代码(对于懒人是一定不能接受的吧)

3.Spring AOP 详解

3.1 核心概念

Spring AOP 有以下 4 个核心概念:

  1. 切点
  2. 连接点
  3. 通知
  4. 切面

举个例子:
假如你要在所有 Controller 方法执行前打印日志,那么:

切点(Pointcut) = "所有 Controller 里的方法"(切点可以看做是保存了众多连接点的⼀个集合

连接点(JoinPoint)= "Controller 中某个具体的方法"(满⾜切点表达式规则的⽅法

通知(Advice) = "方法执行前,打印日志"(对他说:开工吧)

切面(Aspect) = "拦截所有 Controller 方法,在执行前打印日志"

切⾯(Aspect) = 切点(Pointcut) + 通知(Advice)

 

3.1.1 切点


切点(Pointcut)本质上只是一个筛选规则, 它不会影响代码执行, 也不会真正“拦截”任何东西, 它只是告诉 Spring 要对哪些方法进行拦截, 对哪些方法生效.

3.1.1.1 @Pointcut 定义切点

切点 = @Pointcut 注解(声明切点) + 切点表达式(定义规则)


切点表达式是切点的一部分, 它决定了切点的“筛选规则”.

切点通过切点表达式定义一套规则, 这个规则表名了对哪些方法生效/拦截哪些方法(是一个集合), 描述哪些方法可能成为连接点

可以选择直接在@Around中写表达式:

@Around("execution(* com.cym.spring_aop.controller.*.*(..))")

也可以写在 pt()中:(可以复用,推荐)

    //公共切点表达式@Pointcut("execution(* com.cym.spring_aop.controller.*.*(..))")private void pt(){}@Around("pt()")

 还可以在其他切面中使用(使用时, 需要写出这个切点的全限定名):

com.cym.spring_aop.aspect.TimeAspect.pt()
3.1.1.2 切点表达式


常见的切点表达式有以下两种:

execution: 根据方法的签名来匹配 (如上图所示)
@annotation(......): 根据注解匹配


execution 表达式:

语法:

其中, 访问限定修饰符和异常可以省略.

以execution(* com.cym.spring_aop.controller.*.*(..))为例:

    /*** 1.TestController 下的 public修饰, 返回类型为String ⽅法名为t1, ⽆参⽅法* execution(public String com.example.demo.controller.TestController.t1())* 2.省略访问修饰符* execution(String com.example.demo.controller.TestController.t1())* 3.匹配所有返回类型* execution(* com.example.demo.controller.TestController.t1())* 4.匹配TestController 下的所有⽆参⽅法* execution(* com.example.demo.controller.TestController.*())* 5.匹配TestController 下的所有⽅法* execution(* com.example.demo.controller.TestController.*(..))* 6.匹配controller包下所有的类的所有⽅法* execution(* com.example.demo.controller.*.*(..))* 7.匹配所有包下⾯的TestController* execution(* com..TestController.*(..))* 8.匹配com.example.demo包下, ⼦孙包下的所有类的所有⽅法* execution(* com.example.demo..*(..))*/

@annotation 表达式:


通过 execution 定义切点表达式, Spring AOP 拦截的是符合方法签名规则的方法.

而通过 @annotation 定义切点表达式, Spring AOP 拦截的是标注了特定注解的方法(可以是自定义注解, 也可以是 Spring 提供的注解), 因此更加灵活.

@annotation 中, 需要写出该注解的完全限定名.

1.第一步定义自定义注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAspect {}

@Target(ElementType.METHOD):标识该注解只能作用于方法

@Retention(RetentionPolicy.RUNTIME):表示注解只存活在运行时,在编译好的文件中不存在

2.在需要拦截的方法前加上该注解

3.根据该注解定义切点表达式

    @Pointcut("@annotation(com.cym.spring_aop.aspect.MyAspect)")private void pt(){}@Around("pt()")

3.1.2 连接点

包含在切点表达式中的某个具体的方法, 在程序执行过程中实际被执行的那个方法, 就是一个连接点(即目标方法).

幸运儿,在增强中间执行的方法

  • 切点(Pointcut)是一个筛选规则,用来定义哪些方法(连接点)会被 AOP 代理。

  • 连接点(Join Point)是具体的方法,符合切点规则的方法就是连接点。

3.1.3 通知(Advice)


通知(Advice), 就是 AOP 拦截到目标方法(连接点)后, 具体要做的事/具体要执行的逻辑.

简单来说, 通知就是决定拦截后要做什么事情 .

切点(Pointcut) 只是一个“筛选规则”,它决定哪些方法(连接点)需要被拦截,但它本身不执行任何逻辑.

通知(Advice) 是真正 “干活的人”,它决定拦截后要做什么事情(比如打印日志、权限校验、事务管理等)

3.1.3.1 通知类型

Spring AOP 提供了 5 种常见的通知,不同的通知类型, 执行的时机不同:

• @Around: 环绕通知, 此注解标注的通知⽅法在⽬标⽅法前, 后都被执⾏

• @Before: 前置通知, 此注解标注的通知⽅法在⽬标⽅法前被执⾏

• @After: 后置通知, 此注解标注的通知⽅法在⽬标⽅法后被执⾏, ⽆论是否有异常都会执⾏

• @AfterReturning: 返回后通知, 此注解标注的通知⽅法在⽬标⽅法后被执⾏,

有异常不会执⾏

• @AfterThrowing: 异常后通知, 此注解标注的通知⽅法发⽣异常后执⾏

代码演示:

    /*** 前置通知*/@Before("execution(* com.cym.spring_aop.controller.*.*(..))")public void doBefore() {System.out.println("执行doBefore方法");}/*** 后置通知*/@After("execution(* com.cym.spring_aop.controller.*.*(..))")public void doAfter() {System.out.println("执行doAfter方法");}/***抛出异常后通知*/@AfterThrowing("execution(* com.cym.spring_aop.controller.*.*(..))")public void doAfterThrowing() {System.out.println("执行doAfterThrowing方法");}/*** 返回后通知*/@AfterReturning("execution(* com.cym.spring_aop.controller.*.*(..))")public void doAfterReturning() {System.out.println("执行doAfterReturning方法");}/*** 返回后通知*/@Around("execution(* com.cym.spring_aop.controller.*.*(..))")public Object Around(ProceedingJoinPoint pjp) throws Throwable {System.out.println("执行Around方法前..");Object result = pjp.proceed();System.out.println("执行Around方法后..");return result;}

 程序正常运行的情况下, @AfterThrowing 标识的通知方法不会执行, 只有抛出异常时, 该通知方法才会执行.

正常执行:

发现执行顺序:@Around   >  @doBefore  >  @doAferReturning  >  @doAfter  >  @Around

接下来我们添加一个异常 执行一下:

发现执行顺序:@Around   >  @doBefore  >  @doAferThrowing  >  @doAfter 

3.1.4 切面优先级

Spring AOP 允许多个切面作用于同一个目标方法.

当多个切面类, 作用于同一个目标方法(连接点)时, 切面之间是有优先级的:

  • 先执行优先级高的切面中的通知, 后执行优先级低的切面中的通知.

默认的切面优先级是按照名称来排序的:

不加优先级:

加了优先级 

@Order(1)
@Slf4j
@Aspect
@Component
public class Aspect2 {
...
}
@Order(2)
@Slf4j
@Aspect
@Component
public class Aspect3 {
...
}

注意: 

对于 JDK 代理. Spring AOP 只对 public 修饰的方法生效,即切点匹配的目标方法必须是 public, 切面的通知才会生效.
对于 CGLib 代理, Spring AOP 对非 private 非 final 修饰的方法生效,即切点匹配的目标方法不能是 private 或者 final 的.
SpringBoot 默认使用的是 CGLib 代理. 
综上, 如果要对我们项目中的某个方法进行 AOP 拦截通知, 那么这个方法不能是 private 或者 final 修饰的.

http://www.dtcms.com/wzjs/832276.html

相关文章:

  • 定制网站和模板网站的区别怎么制作网站域名
  • 网站建设培训哪家好自助建网站软件平台
  • 南昌高端网站开发费用表网站加速
  • 怎么查网站接入商企业电商网站优化
  • 响应试企业网站淘宝客网站怎么做的人少了
  • 郑州网站搜索排名专做排名的网站
  • 站长之家网址查询做国外进口衣服的网站好
  • 纯英文网站建设指数是指什么
  • 北京网站主题制作网站建设服务费属于什么科目
  • 工会门户网站建设需求ui培训设计哪里好
  • 学习做网站什么是广告艺术设计
  • 广州建设工程交易中心网站徐州网站设计制作建设
  • 南京市建设中心网站wordpress占用带宽
  • 免费网站开发模板网站提高内容的丰富度创意
  • 动漫设计与制作图建站到网站收录到优化
  • 企业网站的必要性哈尔滨网站开发渠道
  • 大学生创业服务网站建设方案项目书南通建设工程造价信息网站
  • 英语做美食网站如何查看一个网站是不是用h5做的
  • 网站正在建设中 文案网络规划设计师自学能通过么
  • 做PPT不错的网站有哪些做网站需要多少钱平邑
  • 怎么随便搞个网站电子商务可以从事的职业
  • 网站建设需要钱吗网站建设最重要的环节
  • 简单建设企业办公网站成都网站制作工具
  • 肇庆网站制作案例上海市网站建
  • 中国建设银行公积金网缴网站最打动人心的广告语
  • 哪家网站优化公司好个人网站源代码
  • 嘉兴地区有人做网站吗网络公司起名大全免费
  • 哪些网上可以赚钱的网站wordpress 目录别名
  • 网站首页快照做网站要多钱
  • 深圳建设培训中心网站人人开发网站