首页 > 其他分享 >day125-aop

day125-aop

时间:2023-08-05 16:56:05浏览次数:35  
标签:连接点 int 通知 day125 joinPoint result aop 方法

aop

简介

AOP(Aspect Oriented Programming)是一种设计思想,是软件设计领域中的面向切面编程,它是面向对象编程的一种补充和完善,它以通过预编译方式和运行期动态代理方式实现在不修改源代码的情况下给程序动态统一添加额外功能的一种技术。

相关术语

  1. 横切关注点

从每个方法中抽取出来的同一类非核心业务。在同一个项目中,我们可以使用多个横切关注点对相关方法进行多个不同方面的增强。

这个概念不是语法层面天然存在的,而是根据附加功能的逻辑上的需要:有十个附加功能,就有十个横切关注点。

  1. 通知

每一个横切关注点上要做的事情都需要写一个方法来实现,这样的方法就叫通知方法。

前置通知:在被代理的目标方法执行

返回通知:在被代理的目标方法成功结束后执行(寿终正寝

异常通知:在被代理的目标方法异常结束后执行(死于非命

后置通知:在被代理的目标方法最终结束后执行(盖棺定论

环绕通知:使用try...catch...finally结构围绕整个被代理的目标方法,包括上面四种通知对应的所有位置

  1. 切面

封装通知方法的类。

  1. 目标

被代理的目标对象

  1. 代理

向目标对象应用通知之后创建的对象

  1. 连接点

这也是一个纯逻辑概念,不是语法定义的。

把方法排成一排,每一个横切位置看成x轴方向,把方法从上到下执行的顺序看成y轴,x轴和y轴的交叉点就是连接点。

  1. 切入点

定位连接点的方式。

每个类的方法中都包含多个连接点,所以连接点是类中客观存在的事物(从逻辑上来说)。

如果把连接点看作数据库中的记录,那么切入点就是查询记录的 SQL 语句。

Spring 的 AOP 技术可以通过切入点定位到特定的连接点。

切点通过 org.springframework.aop.Pointcut 接口进行描述,它使用类和方法作为连接点的查询条件。

aop作用

简化代码:把方法中固定位置的重复的代码抽取出来,让被抽取的方法更专注于自己的核心功能,提高内聚性。

代码增强:把特定的功能封装到切面类中,看哪里有需要,就往上套,被套用了切面逻辑的方法就被切面给增强了。

基于注解的AOP

技术说明

动态代理(InvocationHandler):JDK原生的实现方式,需要被代理的目标类必须实现接口。因为这个技术要求代理对象和目标对象实现同样的接口(兄弟两个拜把子模式)。

cglib:通过继承被代理的目标类(认干爹模式)实现代理,所以不需要目标类实现接口。

AspectJ:本质上是静态代理,将代理逻辑*“织入”被代理的目标类编译得到的字节码文件,所以最终效果是动态的。weaver就是织入器。Spring只是借用了AspectJ中的注解。

实现

public interface Calculator {
    int add(int i,int j);
​
    int sub(int i,int j);
​
    int mul(int i,int j);
​
    int div(int i,int j);
}
@Component
public class CalculatorImpl implements Calculator {
​
    @Override
    public int add(int i, int j){
        int result = i+j;
        System.out.println("inner" +result);
        return result;
    }
​
    @Override
    public int sub(int i, int j) {
        int result = i-j;
        System.out.println("inner" +result);
        return result;
    }
​
    @Override
    public int mul(int i, int j) {
        int result = i*j;
        System.out.println("inner" +result);
        return result;
    }
​
    @Override
    public int div(int i, int j) {
        int result = i/j;
        System.out.println("inner" +result);
        return result;
    }
}
​

 

创建切面类

@Component
@Aspect //通过@Aspect将此类标识为切面
public class LoggerAspect {
    //1. 在切面中,要通过指定的注解将方法标识为通知方法
    //@Before 前置通知,在目标对象方法执行前执行
    //@After 后置通知,在目标对象方法finally中执行
    //@AfterReturning 返回通知,在目标对象方法返回值之后执行,对应try中执行有错误不执行此方法
    //@AfterThrowing 异常通知,在目标对象方法catch中执行
​
    //2. 切入点表达式:设置在标识通知的注解value属性中
    //execution(public int com.gu.spring.annotation.CalculatorImpl.add(int ,int ))
    //execution(* com.gu.spring.annotation.CalculatorImpl.*(..))
    //第一个* 表示任意访问修饰符和返回值类型
    //第二个* 表示其中任意的方法
    // .. 表示任意的参数列表
    //类的地方也可以使用* ,表示包下所有的类
​
    //3. 获取连接点的信息
    // 在通知方法的参数位置,设置joinPoint的参数,就可以获取连接点所对应的方法的信息
    //    //获取连接点对应方法的签名信息
    //    Signature signature = joinPoint.getSignature();
    //    //获取连接点对应方法的参数
    //    Object[] args = joinPoint.getArgs();
​
​
    //4.重用切入点表达式
    //@Pointcut("execution(* com.gu.spring.annotation.CalculatorImpl.*(..))")声明一个公共的切入点表达式
    //使用方式:@Before("pointCut()")
​
​
    //5. 切面的优先级
    // 可以通过@Order注解的value属性设置优先级,默认值为integer的最大值
    //@Order的value属性值越小优先级越高
    @Pointcut("execution(* com.gu.spring.annotation.CalculatorImpl.*(..))")
    public void pointCut(){
​
    }
​
​
    //@Before("execution(public int com.gu.spring.annotation.CalculatorImpl.add(int ,int ))")
    //@Before("execution(* com.gu.spring.annotation.CalculatorImpl.*(..))")
    @Before("pointCut()")
    public void brforeAdviceMethod(JoinPoint joinPoint){
        //获取连接点对应方法的签名信息
        Signature signature = joinPoint.getSignature();
        //获取连接点对应方法的参数
        Object[] args = joinPoint.getArgs();
        System.out.println("LoggerAspect,方法: "+signature.getName()+"参数: "+ Arrays.toString(args));
        System.out.println(signature);
        System.out.println(Arrays.toString(args));
​
    }
​
    @After("pointCut()")
    public void afterAdviceMethod(JoinPoint joinPoint){
        //获取连接点对应方法的签名信息
        Signature signature = joinPoint.getSignature();
        //获取连接点对应方法的参数
        Object[] args = joinPoint.getArgs();
        System.out.println("LoggerAspect :"+signature.getName()+" okk");
    }
​
    //在返回通知中,若要获取目标对象方法的返回值,只需要通过@AfterReturning 注解的returning属性
    //就可以将通知方法的某个参数指定为接受目标方法的返回值的参数
    @AfterReturning(value = "pointCut()",returning = "result")
    public void afterReturningAdviceMethod(JoinPoint joinPoint, Object result){
        //获取连接点对应方法的签名信息
        Signature signature = joinPoint.getSignature();
        //获取连接点对应方法的参数
        Object[] args = joinPoint.getArgs();
        System.out.println("LoggerAspect :"+signature.getName()+" result: "+result);
    }
​
    //在异常通知中,若要获取目标对象方法的异常值,只需要通过@AfterThrowing 注解的throwing属性
    //就可以将通知方法的某个参数指定为接受目标方法的异常值的参数
    @AfterThrowing(value = "pointCut()",throwing = "ex")
    public void afterThrowAdviceMethod(JoinPoint joinPoint,Throwable ex){
        //获取连接点对应方法的签名信息
        Signature signature = joinPoint.getSignature();
        System.out.println("LoggerAspect : "+signature.getName()+" 异常: "+ex);
    }
​
​
    @Around("pointCut()")
    //环绕通知的方法的返回值一定要和目标对象的方法的返回值一致
    public Object aroundAdviceMethod(ProceedingJoinPoint joinPoint){
        Object result = null;
        //表示目标对象方法的执行
        try {
            System.out.println("环绕通知--前置通知");
            result = joinPoint.proceed();
            System.out.println("环绕通知--返回通知");
        } catch (Throwable e) {
            e.printStackTrace();
            System.out.println("环绕通知--异常通知");
        } finally {
            System.out.println("环绕通知--后置通知");
        }
        return result;
    }
}

 

配置文件

<!--    
    AOP的注意事项:
    切面类和目标类都需要交给IOC容器管理
    @Aspect:切面类必须通过@Aspect注解标识为一个切面
    在spring配置文件中设置aop:aspectj-autoproxy
-->
<context:component-scan base-package="com.gu.spring.annotation"></context:component-scan>
​
<!--  开启基于注解的AOP  -->
<aop:aspectj-autoproxy />

 

切面的优先级

相同目标方法上同时存在多个切面时,切面的优先级控制切面的内外嵌套顺序。

优先级高的切面:外面

优先级低的切面:里面

使用@Order注解可以控制切面的优先级:

@Order(较小的数):优先级高

@Order(较大的数):优先级低

基于xml的AOP

实现

<!--  扫描组件  -->
    <context:component-scan base-package="com.gu.spring.xml"></context:component-scan>
    
    <aop:config>
<!--    设置一个公共的切入点表达式    -->
        <aop:pointcut id="pointCut" expression="execution(* com.gu.spring.xml.CalculatorImpl.*(..))"/>
<!--    将ioc容器中某个bean设置为切面    -->
        <aop:aspect ref="loggerAspect">
            <aop:before method="brforeAdviceMethod" pointcut-ref="pointCut"></aop:before>
            <aop:after method="afterAdviceMethod" pointcut-ref="pointCut"></aop:after>
            <aop:after-returning method="afterReturningAdviceMethod" returning="result" pointcut-ref="pointCut"></aop:after-returning>
            <aop:after-throwing method="afterThrowAdviceMethod" throwing="ex" pointcut-ref="pointCut"></aop:after-throwing>
            <aop:around method="aroundAdviceMethod" pointcut-ref="pointCut"></aop:around>
        </aop:aspect>
    </aop:config>

 

over

标签:连接点,int,通知,day125,joinPoint,result,aop,方法
From: https://www.cnblogs.com/GUGUZIZI/p/17608191.html

相关文章

  • Spring Boot 中的 AOP 实践
    在SpringBoot中使用AOP(面向切面编程)可以帮助您在应用程序中更优雅地处理横切关注点,如日志、事务管理和安全性。本文将深入探讨如何在SpringBoot中使用AOP,以及如何创建自定义切面来实现特定功能。1.什么是AOP?AOP是一种编程范式,它允许您将横切关注点(如日志、安全性、事务......
  • AOP详解
    1:AOP:AOP为AspectOrientedProgramming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。它提倡的是针对同一类问题的统一处理,利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提......
  • 看一家头部实干派互娱公司如何玩转DataOps?
    DataOps的概念自首次被提出至今已有8年,并在2018年被Gartner纳入数据管理技术成熟度曲线。从实施上看,当下DataOps仍处在发展初期,鲜少企业或团队能据此真正沉淀一套方法论或技术产品的体系。不过,随着越来越多的企业开启DataOps实践,相信令人“雾里看花”的DataOps方法体系也会逐渐明朗......
  • 白鲸调度系统助力国内头部券商打造国产信创化 DataOps 平台
    导读国内某头部券商是国内排名前三的全国性大型综合证券公司。作为证券行业领头羊之一,该券商一直高度重视核心系统的自主可控以及网络信息安全。早些时候,其已经完成了信创化数据库改造和OA系统适配,接下来的当务之急是完成数据能力平台的信创化改造。随着该券商近年来数据中台的发......
  • 白鲸调度系统助力国内头部券商打造国产信创化 DataOps 平台
    导读国内某头部券商是国内排名前三的全国性大型综合证券公司。作为证券行业领头羊之一,该券商一直高度重视核心系统的自主可控以及网络信息安全。早些时候,其已经完成了信创化数据库改造和OA系统适配,接下来的当务之急是完成数据能力平台的信创化改造。随着该券商近年来数据中台的......
  • Spring AOP
    springAOP基础知识AOP是什么AOP是一种变成思想,AOP全名AspectOrientProgramming,直译过来就是面向切面编程。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。AOP简单的一点的理解就是,不改变源代码的......
  • 活动回顾|火山引擎 DataLeap 分享:DataOps、数据治理、指标体系最佳实践(文中领取 PPT)
    更多技术交流、求职机会,欢迎关注字节跳动数据平台微信公众号,回复【1】进入官方交流群 在7月21日至22日举行的 ArchSummit全球架构师峰会(深圳站)及 DataFunCon.数据智能创新与实践大会(北京站)上,来自火山引擎DataLeap的三位专家分别就 DataOps、数据治理和指标体系等......
  • 公共字段自动填充--AOP
    自定义AutoFill注解,用于标识需要进行公共字段自动填充的方法/*自定义注解,用于标识某个方法需要进行功能字段自动填充处理*/@Target(ElementType.METHOD)//证明这个注解只能加在方法上@Retention(RetentionPolicy.RUNTIME)//固定的写法public@interfaceAutoFill{//指......
  • 13_Spring_AOPXML方式实现_了解
    13_Spring_AOPXML方式实现_了解1、创建两个类,增强类和被增强类,创建方法见之前的代码2、在spring配置文件中创建两个类对象 3、在spring配置文件中配置切入点<aop:config><!--切入点--><aop:pointcutid="pointCutAdd"expression="execution......
  • 12_Spring_AOP注解方式实现_掌握
    12_Spring_AOP注解方式实现_掌握AspectJ本身并不是spring框架中的组成部分,是一个独立的AOP框架,一般把AspectJ和Spring框架的AOP依赖一起使用,所以要导入一个独立的依赖实现的两种方式1基于注解方式实现(熟练)2基于XML配置方式(了解)准备工作1导入依赖<!-......