精华内容
下载资源
问答
  • 切面编程

    2021-04-25 15:59:43
    切面编程 动态代理 导入jar包 <!--aop--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </...

    切面编程

    • 动态代理

    AOP术语
    1.target :目标类,既需要被代理的类。例如:UserService
    2.Joinpoint(连接点):所谓连接点是指那些可能被拦截到的方法 。例如:所有的方法
    3.PointCut切入点:已经被增强的连接点。例如:addUser()
    4.advice 通知/增强 ,增强代码.例如:after、 brfore
    5.Weaving(织入):驶入把增强advice应用到目标对象targer来创建新的代理对象proxy的过程。
    6.proxy代理类
    7.Aspect(切面):是切入点pointcut和通知advice的结合

    导入jar包

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

    建立切面

    package com.example.demo.anncoation;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD) //方法前切入
    public @interface adminFilter {
    
    }
    

    实现切入点逻辑

    package com.example.demo.aspoct;
    
    import com.example.demo.controller.TestOneContoller;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.stereotype.Component;
    
    import javax.annotation.Resource;
    
    
    @Aspect
    @Component
    public class CheckUser {
    
    
        @Resource
        private TestOneContoller testOneContoller;
       
        @Pointcut("@annotation(com.example.demo.anncoation.adminFilter)")
        public void  check(){
    
        }
        
        //前置通知
        @Before("check()")
        public void  beforeCheck(){
            testOneContoller.getUserName(1);
        }
        
    /*     //环绕通知
        @Around("check()")
        public void  beforeCheck(){
            testOneContoller.getUserName(1);
        }
    
        //后置通知
        @After("check()")
        public void  beforeCheck(){
            testOneContoller.getUserName(1);
        }*/
    
    
    }
    

    示例

     @GetMapping(value ="/test")
        @ApiOperation(value="测试切面")
        @adminFilter
        public void test(@RequestParam Integer userNumber){
            log.info("测试切面:{}",userNumber);
        }
    
    

    execution的使用和通知的介绍
    注解中的分为5个部分(自我理解)
    组成一:修饰符 例如:public(可以省略)
    组成二:方法放回值 (* 表示任意返回值都需要拦截 )
    组成三:切点路径 例如:com.example.demo.controller.*
    组成四:切点路径下的方法
    组成五:方法中的参数
    示例:

    package com.example.demo.aspoct;
    
    import com.example.demo.controller.TestOneContoller;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.springframework.stereotype.Component;
    
    import javax.annotation.Resource;
    
    
    /**
     * @author lilinchun
     * @date 2021/4/23 0023 17:43
     */
    @Aspect
    @Component
    public class CheckUser {
    
    
        @Resource
        private TestOneContoller testOneContoller;
    
    //    @Pointcut("@annotation(com.example.demo.anncoation.adminFilter)")
        @Pointcut("execution(* com.example.demo.controller.*.*(..))")
        public void  check(){
    
        }
    
    
        //前置通知
    //    @Before("check()")
    //    public void  beforeCheck(JoinPoint joinPoint){
    //        System.out.println("-------------------前置通知--------------------"+joinPoint);
               //方法执行
    //    }
    
    
        //环绕通知
    //    @Around("check()")
    //    public Object  arount(ProceedingJoinPoint p) throws Throwable {
    //          System.out.println("-------------------环绕通知前--------------------");
    //        Object proceed = p.proceed(); //执行目标方法
                   //方法执行
    //        System.out.println("-------------------环绕通知后--------------------");
    //        return proceed;
    //    }
    
        //后置通知 (方法执行完之后通知)
    //    @After("check()")
    //    public void  beforeCheck(){
    //       System.out.println("-------------------后置通知--------------------");
    //    }
    
     /*   //返回通知 (如果抛出异常则不执行)
        @AfterReturning("check()")
        public void  beforeCheck(JoinPoint joinPoint){
            System.out.println("-------------------返回通知--------------------"+joinPoint);
             //方法执行
        }*/
    
    
      /*  //异常通知(方法抛出异常时候执行) 可以获取错误的信息
        @AfterThrowing(value = "check()",throwing = "throwable")
        public void  beforeCheck(Throwable throwable){
         //方法执行
            System.out.println("-------------------异常通知--------------------"+throwable.getMessage());
        }*/
    
    
    
    
    }
    
    

    备注:持续更新

    展开全文
  • 1. pom 引入aop jarorg.springframework.bootspring-boot... 定义切面 Aspect@Aspect@Component // 这句不能少public class TestAspect {private Logger logger = Logger.getLogger(getClass());@Pointcut("executio...

    1. pom 引入aop jar

    org.springframework.boot

    spring-boot-starter-aop

    2. 定义切面 Aspect

    @Aspect

    @Component // 这句不能少

    public class TestAspect {

    private Logger logger = Logger.getLogger(getClass());

    @Pointcut("execution(* com.test.server1.controller.ComputerController.test(..))")

    public void testPoint() {}

    @Before(value="testPoint()")

    public void handleBeforeMethod()

    {

    logger.info("handleBeforeMethod before");

    }

    @Around(value = "testPoint()")

    public String handleAroundMethod(ProceedingJoinPoint joinPoint) throws Throwable

    {

    logger.info("handleAroundMethod Around");

    return (String) joinPoint.proceed();

    }

    @After(value = "testPoint()")

    public void handleAfterMethod()

    {

    logger.info("handleAfterMethod After");

    }

    }

    展开全文
  • 前言面向对象(OOP)作为经典的设计范式,对于我们来说可谓无人不知,还记得...既然OOP这么多优点,那么经常被大家提起的面向切面编程(AOP)是什么回事呢,下面我们就一起来看一下。AOP定义第一步还是要知道aop是什么,...

    前言

    面向对象(OOP)作为经典的设计范式,对于我们来说可谓无人不知,还记得我们入行起始时那句经典的总结吗-万事万物皆对象。

    是的,基于OOP思想封装、继承、多态的特点,我们会自然而然的遵循模块化、组件化的思维来设计开发应用,以到达易维护、可扩展、高复用的目的。

    既然OOP这么多优点,那么经常被大家提起的面向切面编程(AOP)是什么回事呢,下面我们就一起来看一下。

    AOP定义

    第一步还是要知道aop是什么,先个来自维基百科的解释:

    面向侧面的程序设计(aspect-oriented programming,AOP,又译作面向方面的程序设计、观点导向编程、剖面导向程序设计)是计算机科学中的一个术语,指一种程序设计范型。

    侧面的概念源于对面向对象的程序设计的改进,但并不只限于此,它还可以用来改进传统的函数。

    其从主关注点中分离出横切关注点是面向侧面的程序设计的核心概念。分离关注点使得解决特定领域问题的代码从业务逻辑中独立出来.

    业务逻辑的代码中不再含有针对特定领域问题代码的调用,业务逻辑同特定领域问题的关系通过侧面来封装、维护.

    这样原本分散在在整个应用程序中的变动就可以很好的管理起来。

    tip

    确实有点那么不太清晰,有点乱。不过在乱之前,我们可以选能理解的部分先看一下:

    侧面(也就是切面) 用来描述分散在对象、类或函数中的横切关注点。

    重点在这,分散在对象中的横切关注点,可以猜一下是什么,应该就是不同对象之间公用的部分

    侧面的概念源于对面向对象的程序设计的改进,它还可以用来改进传统的函数.

    AOP 显然不是OOP的替代品,是OOP的一种补充。

    从主关注点中分离出横切关注点是面向侧面的程序设计的核心概念。

    具体到业务项目中来说,主关注点就是业务逻辑了。针对特定领域问题代码的调用,就是AOP要关注的部分

    简而言之,AOP是针对业务处理过程中的切面(即非业务逻辑部分,例如错误处理,埋点,日志等)进行提取.

    它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果(目的是降低耦合)。

    具体到实现来说就是通过动态的方式将非主关注点部分插入到主关注点(一般是业务逻辑中)

    说了这么多,可能不太明白,还是一起看代码吧。

    埋点场景

    很普遍的这么个场景,需要点击按钮之后进行信息上报。

    假设我们有这么个logger的工具,可以进行上报:

    const logger = console.log

    //引入即可使用

    logger('按钮被点击了')

    那么,我们直接撸起来吧:

    const doSomething = ()=>{

    console.log('doSomething')

    }

    let clickHandler = ()=>{

    logger('doSomething之前')

    // n行代码

    doSomething()

    logger('doSomething之后')

    //n 行代码

    }

    看起来也没什么的,简单粗暴。

    如果有30个按钮,每个业务逻辑不同,都需要埋这个点(假设打点信息一致)。

    我们30个函数里面,都要手动写这个方法的话,这也太坑爹了吧。

    主要是与业务代码严重耦合,哪天不小心动了点其他内容,手抖误删了,就gg了。

    后续维护的时候,简直噩梦。

    仔细看一下,这不就是符合AOP的使用前提吗,那么试试AOP吧。

    关注点划分

    根据前面提的,可以划分下关注点。

    主关注点

    侧关注点

    业务逻辑(doSomething)

    埋点信息 logger

    前面提到AOP关注的是步骤具体到例子来说其实就是插入logger的步骤。

    插入时机无非时业务逻辑执行之前或者之后的阶段。

    具体实现起来也不那么困难

    实现思路

    具体到js来说,由于语言本身的特性,天生就具有运行时动态插入逻辑的能力。

    重点在于在原函数上增加其他功能并不改变函数本身。

    毕竟函数可以接受一切形式的参数,当然函数也不例外了。

    当传入一个函数的时候,我们要对其操作的余地就很大了,

    保存原函数,然后利用后续参数加上call或apply,就可以达到我们的目的。

    此外为了给函数都增加一个属性,我们在原型上操作就行了。

    经典before或者after的实现

    网上太多类似实现了,直接看代码好了:

    // action 即为我们的侧关注点,即logger

    Function.prototype.after = function (action) {

    //保留当前函数,这里this指向运行函数即clickHandler

    var func = this;

    // return 被包装过的函数,这里就可以执行其他功能了。

    // 并且该方法挂在Function.prototype上,

    // 被返回的函数依然具有after属性,可以链式调用

    return function () {

    // 原函数执行,这里不考虑异步

    var result = func.apply(this, arguments);

    // 执行之后的操作

    action.apply(this,arguments);

    // 将执行结果返回

    return result;

    };

    };

    // before 实现类似,只不过执行顺序差别而已

    Function.prototype.before = function (action) {

    var func = this;

    return function () {

    action.apply(this,arguments);

    return func.apply(this, arguments);

    };

    };

    那么我们使用AOP改造之后的代码就如下了:

    const doSomething = ()=>{

    console.log('doSomething')

    }

    let clickHandler = ()=>{

    // n行代码

    doSomething()

    //n 行代码

    }

    clickHandler = clickHandler.before(()=>{

    logger('doSomething之前')

    }).after(()=>{

    logger('doSomething之后')

    })

    clickHandler() // 执行结果和预期一致

    到这里就实现了面向切面编程,我们的业务逻辑里面只管业务本身,侧关注点通过这种方式来动态引入,与主逻辑解耦,更加纯净、易于维护。

    结束语

    到这里,简单的AOP就介绍完成了。利用这种模式结合我们js本身的特性,可以尝试更多的可能。

    例如我们react中常见的HOC、es7的装饰者模式、HOF等,很多时候不得不感叹大牛们思想的精髓,会让我们有种顿悟的感觉。本文抛砖引玉,共同学习啦,对自己是总结和提高,更希望能帮助到需要的小伙伴。更多文章请移步我的博客

    参考文章

    展开全文
  • AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的一种技术。 AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式...

    1. AOP

    AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的一种技术
    AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。

    面向切面的编程(AOP) 是一种编程范式,旨在通过允许横切关注点的分离,提高模块化。AOP提供切面来将跨越对象关注点模块化

    OOP中模块化的关键单元是类,而AOP中模块化的单元是切面。切面支持跨多个类型和对象的关注点(如事务管理)的模块化。(这种关注点在AOP文献中经常被称为“横切【crosscutting】”关注。)

    AOP框架是Spring的关键组件之一。虽然Spring IoC容器不依赖于AOP(这意味着如果您不想使用AOP就不需要),但AOP补充了Spring IoC以提供一个非常强大的中间件解决方案。

    1.1. 使用场景

    主要应用于处理一些具有横切性质的系统级服务,如日志收集、事务管理、安全检查、缓存、对象池管理等。

    1.2. AOP的关键技术

    AOP实现的关键就在于AOP框架自动创建的AOP代理,AOP代理则可分为静态代理和动态代理两大类

    • 静态代理是指使用AOP框架提供的命令进行编译,从而在编译阶段就可生成 AOP 代理类,因此也称为编译时增强;
    • 动态代理则在运行时借助于JDK动态代理、CGLIB等在内存中“临时”生成AOP动态代理类,因此也被称为运行时增强。

    2. AOP概念

    2.1. 核心概念

    • 切面(Aspect):跨越多个类的关注的模块化。事务管理是企业Java应用程序中横切关注点的一个很好的例子。在Spring AOP中,切面是通过使用常规类(基于模式的方法)或使用@Aspect注释(@AspectJ风格)注释的常规类来实现的
    • 连接点(Join point):程序执行过程中的一个点,如方法的执行或异常的处理。在Spring AOP中,连接点总是代表一个方法执行
    • 增强(Advice) : 切面在特定连接点上采取的动作。不同类型的Advice包括“around”、“before”和“after”建议。许多AOP框架,包括Spring,将Advice作为拦截器,并围绕连接点维护一个拦截器链
    • 切入点(Pointcut): 是一个(组)基于正则表达式的表达式。Advice与切入点表达式相关联,并在切入点匹配的任何连接点上运行(例如,具有特定名称的方法的执行)。连接点的概念与切入点表达式相匹配是AOP的核心,Spring默认使用AspectJ切入点表达式语言。
    • 引入(Introduction): 代表类型声明其他方法或字段,即为Advice对象增加新的属性和方法。Spring AOP允许您为任何需要增强的对象引入新接口(和相应的实现)。例如,可以使用引入来让bean实现IsModified接口,以简化缓存。
    • Target Object : 被一个或多个切面增强的对象。也称为“advised object”。由于Spring AOP是通过使用运行时代理实现的,因此该对象始终是一个代理对象
    • AOP代理(AOP Proxy) :由AOP框架创建的对象,用于实现切面契约(Advice方法执行等)。在Spring框架中,AOP代理是JDK动态代理或CGLIB代理
    • 编织(Weaving):将切面与其他应用程序类型或对象链接,以创建Advice的对象。这可以在编译时(例如,使用AspectJ编译器)、加载时或运行时完成。与其他纯Java AOP框架一样,Spring AOP在运行时执行编织。

    2.2. Joinpoint的类型

    AOP中的Joinpoint可以有多种类型:

    • 构造方法调用,
    • 字段的设置和获取,
    • 方法的调用,
    • 方法的执行,
    • 异常的处理执行,
    • 类的初始化等

    在AOP的概念中可以在上面的这些Joinpoint上织入自定义的Advice

    注意:在Spring中却没有实现上面所有的joinpoint,确切的说,Spring只支持方法执行类型的Joinpoint。

    2.3. Advice 的类型

    • before advice, 在 join point 前被执行的 advice. 虽然 before advice 是在 join point 前被执行, 但是它并不能够阻止 join point 的执行, 除非发生了异常(即在 before advice 代码中, 不能人为地决定是否继续执行 join point 中的代码)
    • after return advice, 在一个 join point 正常返回后执行的 advice
    • after throwing advice, 当一个 join point 抛出异常后执行的 advice
    • after(final) advice, 无论一个 join point 是正常退出还是发生了异常, 都会被执行的 advice.
    • around advice, 在 join point 前和 joint point 退出后都执行的 advice. 这个是最常用的 advice.

    3. 如何声明pointcut

    切入点【pointcut】确定感兴趣的连接点【Join point】,从而使我们能够控制通Advice何时运行。Spring AOP只支持Spring bean的方法执行连接点,因此您可以将切入点看作与Spring bean上方法的执行相匹配。
    一个切入点声明有两个部分:

    • 一个签名,包含一个名称和任何参数,
    • 一个切入点表达式,用来确定我们对哪个方法执行感兴趣

    在AOP的@AspectJ注释风格中,切入点签名由常规方法定义提供,切入点表达式通过使用**@Pointcut**注解表示(作为切入点签名的方法必须有一个空返回类型)。

    针对切入点表达式的详细使用指导,参见: The AspectJTM Programming Guide

    3.1. Spring支持的切入点标志符(Pointcut Designators)

    Spring AOP支持以下AspectJ切入点标志符(PCD),用于切入点表达式中:

    3.1.1. execution

    用于匹配方法执行的连接点。这是使用spring AOP时主要使用的PCD,
    格式如下:
    execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?)
    示例如下:

    execution(public * *(..))
    execution(* set*(..))
    //AccountService接口定义的任何方法的执行:
    execution(* com.xyz.service.AccountService.*(..))
    //service包中定义的任何方法的执行:
    execution(* com.xyz.service.*.*(..))
    //在service包或其子包中定义的任何方法的执行:
    execution(* com.xyz.service..*.*(..))
    

    3.1.2. within

    限制匹配某些类型内的连接点(使用Spring AOP时,在匹配类型中声明的方法的执行).
    示例如下:

    //service包中的任何连接点(仅在Spring AOP中执行方法):
     within(com.xyz.service.*)
     //service包或者子包中的任何连接点(仅在Spring AOP中执行方法):
     within(com.xyz.service..*)
    

    3.1.2. this

    限制匹配到连接点(使用Spring AOP时方法的执行),其中bean引用(Spring AOP代理)是给定类型的一个实例

    //代理实现AccountService接口的任何连接点(仅在Spring AOP中执行方法):
    this(com.xyz.service.AccountService)
    

    3.1.3. target

    限制匹配到连接点(使用Spring AOP时方法的执行),其中目标对象(被代理的应用程序对象)是给定类型的一个实例

    //目标对象实现AccountService接口的任何连接点(仅在Spring AOP中执行方法):
    target(com.xyz.service.AccountService)
    

    3.1.4. args

    限制匹配到连接点(使用Spring AOP时方法的执行),其中参数是给定类型的实例。

    //任何接受单个参数的连接点(仅在Spring AOP中执行方法),并且在运行时传递的参数是Serializable:
     args(java.io.Serializable)
    

    请注意,本例中给出的切入点不同于(execution* *(java.io.Serializable))。如果在运行时传递的参数是Serializable,则args版本匹配,如果方法签名声明了一个Serializable类型的参数,则execution版本匹配。

    3.1.5. @target

    限制匹配到连接点(使用Spring AOP时方法的执行),其中执行对象的类具有给定类型的注解。

    //目标对象具有@Transactional注解的任何连接点(仅在Spring AOP中执行方法):
     @target(org.springframework.transaction.annotation.Transactional)
    

    3.1.6. @args

    限制匹配到连接点(使用Spring AOP时方法的执行),其中传递的实际参数的运行时类型具有给定类型的注解。

    //任何接受单个参数的连接点(仅在Spring AOP中执行方法),其中传递的参数的运行时类型有@Classified注解:
    @args(com.xyz.security.Classified)
    

    3.1.7. @within

    限制匹配到具有给定注解的类型内的连接点(使用Spring AOP时使用给定注解类型中声明的方法的执行)。

    //任何连接点(仅在Spring AOP中执行方法),其中目标对象的声明类型具有@Transactional注解
     @within(org.springframework.transaction.annotation.Transactional)
    

    3.1.8. @annotation

    限制匹配到连接点,连接点的主题【Target Object】(在Spring AOP中运行的方法)具有给定的注解。

    //任何连接点(仅在Spring AOP中执行方法),其中执行方法具有@Transactional注解:
     @annotation(org.springframework.transaction.annotation.Transactional)
    

    3.1.9. bean

    //在名为tradeService的Spring bean上的任何连接点(仅在Spring AOP中执行方法):
     bean(tradeService)
    //Spring bean上的任何连接点(仅在Spring AOP中执行方法)的名称与通配符表达式*Service:
    bean(*Service)
    

    注意

    • 完整的AspectJ切入点语言支持但Spring中不支持的额外切入点标志符:call、get、set、preinitialization、staticinitialization、initialization、handler、adviceexecution、withcode、cflow、cflowbelow、if、@this和@withincode。在由Spring AOP解释的切入点表达式中使用这些切入点标签符会导致抛出一个IllegalArgumentException。
    • Spring AOP是一个基于代理的系统,它区分了代理对象本身(绑定到this)和代理背后的目标对象(绑定到target)
    • 由于Spring的AOP框架基于代理的特性,目标对象中的调用从定义上讲是不会被拦截的
    • 如果您的拦截需要在目标类中包括方法调用甚至构造函数,请考虑使用Spring驱动的本地AspectJ编织,而不是使用Spring基于代理的AOP框架

    3.2. 使用示例

    //匹配所有public的方法执行
    @Pointcut("execution(public * *(..))")
    private void anyPublicOperation() {} 
    
    //匹配所有位于com.xxx.xxxapp.trading package下的方法执行
    @Pointcut("within(com.xxx.xxxapp.trading..*)")
    private void inTrading() {} 
    
    //匹配所有位于com.xxx.xxxapp.trading package下所有public的方法执行
    @Pointcut("anyPublicOperation() && inTrading()")
    private void tradingOperation() {} 
    

    3.3. 共享公共的切入点定义

    在开发企业应用程序时,开发人员通常希望从几个方面引用应用程序的模块和特定的操作集,建议定义一个CommonPointcuts方面来捕获通用的切入点表达式。示例如下:

    package com.xxx.xxxapp;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    
    @Aspect
    public class CommonPointcuts {
        //在web layer的连接点
        @Pointcut("within(com.xxx.xxxapp.web..*)")
        public void inWebLayer() {}
    
        //在service layer的连接点
        @Pointcut("within(com.xxx.xxxapp.service..*)")
        public void inServiceLayer() {}
    
        //在daolayer的连接点
        @Pointcut("within(com.xxx.xxxapp.dao..*)")
        public void inDataAccessLayer() {}
    
        //假设业务服务是在服务接口上定义的任何方法的执行,
        //并且不同模块的接口和具体实现在不同的包下,如
       //com.xxx.xxxapp.login.service, com.xxx.xxxapp.order.service
        @Pointcut("execution(* com.xxx.xxxapp..service.*.*(..))")
        public void businessService() {}
    
        //数据访问操作是在dao接口上定义的任何方法的执行。这个定义假设接口放在dao包中,实现类型放在子包中。
        @Pointcut("execution(* com.xxx.xxxapp.dao.*.*(..))")
        public void dataAccessOperation() {}
    }
    

    AOP的配置如下:

    <aop:config>
        <aop:advisor
            pointcut="com.xxx.xxxapp.CommonPointcuts.businessService()"
            advice-ref="tx-advice"/>
    </aop:config>
    
    <tx:advice id="tx-advice">
        <tx:attributes>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
    

    4. 简单示例

    4.1. 在springboot中实现AOP

    在springboot maven项目中实现AOP功能,步骤如下:

    • 导入aop模块:Spring AOP:(spring-aspects)
    • 定义一个业务逻辑类(如MathCalculator);
    • 定义一个日志切面类(LOgAspects);切面类里面的方法需要动态感知MathCalculator的方法运行到哪里(通过不同类型的advice实现),然后执行对应的切面方法;
    • 给切面类的目标方法标注何时何地运行(不同Advice类型的注解)
    • 将切面类和业务逻辑类(目标方法所在类)都加入到容器中;
    • 必须告诉Spring哪个类是切面类(给切面类上加一个注解:@Aspect)
    • 给配置类中加@EnableAspectJAutoProxy 开启基于注解的AOP模式

    主要三步

    • 1、将业务逻辑组件和切面类都加入到容器中;告诉Spring哪个类是切面类(@Aspect)
    • 2、在切面类上的每一个Advice方法上标注不同类型的Advice注解,告诉Spring何时何地运行(切入点表达式)
    • 3、开启基于注解的AOP模式;@EnableAspectJAutoProxy
     <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-aop</artifactId>
                <version>2.1.8.RELEASE</version>
            </dependency>
    

    4.2. 示代代码

    4.2.1. 定义业务逻辑

    /**
     * 实现 加减乘除运算
     */
    public class MathCalculator {
        public int add(int a,int b){
            return a+b;
        }
    
        public int minus(int a,int b){
            return a - b;
        }
    
        public int multiply(int a,int b){
            return a * b;
        }
    
        public int div(int i, int j) {
            return i / j;
        }
    
    }
    

    4.2.2. 定义切面类

    @Aspect
    @Slf4j
    public class LogAspects {
    
        //抽取公共的切入点表达式
        @Pointcut(value = "execution(public int com.suntek.aop.MathCalculator.*(..))")
        private void pointCut() {
        }
    
        ;
    
        //@Before在目标方法之前切入;切入点表达式(指定在哪个方法切入)
        //JoinPoint一定要出现在参数列表的第一位
        @Before(value = "pointCut()")
        public void logStart(JoinPoint joinpoint) {
            log.info("logStart----{}----{}", joinpoint.getSignature().getName(), Arrays.toString(joinpoint.getArgs()));
        }
    
        @After(value = "com.suntek.aop.LogAspects.pointCut()")
        public void logEnd(JoinPoint joinpoint) {
            log.info("logEnd----{}----{}", joinpoint.getSignature().getName(), Arrays.toString(joinpoint.getArgs()));
        }
    
        @AfterReturning(value = "execution(public int com.suntek.aop.MathCalculator.*(..))", returning = "res")
        public void logReturn(Integer res) {
            log.info("logReturn----{}",res);
        }
    
        @AfterThrowing(value = "execution(public int com.suntek.aop.MathCalculator.*(..))", throwing = "e")
        public void logException(Exception e) {
            log.info("logException---{}", e);
        }
    }
    

    4.2.3. AOP配置

    @EnableAspectJAutoProxy
    @Configuration
    @Slf4j
    public class AOPConfig {
        //业务逻辑类加入到容器中
        @Bean
        public MathCalculator mathCalculator() {
            log.info("mathCalculator bean start init");
            return new MathCalculator();
        }
    
        //切面类加入到容器中
        @Bean
        public LogAspects logAspects() {
            log.info("logAspects bean start init");
            return new LogAspects();
        }
    }
    

    4.2.4. 测试类

    public class SpringAOPTest {
        @Test
        public void test01() {
            AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AOPConfig.class);
    
            MathCalculator mathCalculator = applicationContext.getBean(MathCalculator.class);
            mathCalculator.div(1, 1);
            mathCalculator.add(1, 88);
            applicationContext.close();
        }
    }
    

    4.2.5. 测试结果输出

    2021-07-07 11:04:21,915 INFO  com.xxx.aop.AOPConfig.mathCalculator(AOPConfig.java:15) - mathCalculator bean start init
    2021-07-07 11:04:21,965 INFO  com.xxx.aop.AOPConfig.logAspects(AOPConfig.java:22) - logAspects bean start init
    2021-07-07 11:04:21,978 INFO  com.xxx.aop.LogAspects.logStart(LogAspects.java:24) - logStart----add----[1, 88]
    2021-07-07 11:04:21,985 INFO  com.xxx.aop.LogAspects.logEnd(LogAspects.java:29) - logEnd----add----[1, 88]
    2021-07-07 11:04:21,985 INFO  com.xxx.aop.LogAspects.logReturn(LogAspects.java:34) - logReturn----89
    2021-07-07 11:04:21,986 INFO  com.xxx.aop.LogAspects.logStart(LogAspects.java:24) - logStart----div----[1, 1]
    2021-07-07 11:04:21,986 INFO  com.xxx.aop.LogAspects.logEnd(LogAspects.java:29) - logEnd----div----[1, 1]
    2021-07-07 11:04:21,986 INFO  com.xxx.aop.LogAspects.logReturn(LogAspects.java:34) - logReturn----1
    

    5. 参考

    Aspect Oriented Programming with Spring
    https://www.tutorialspoint.com/springaop/springaop_core_concepts.htm

    展开全文
  • 感受面向切面编程

    2020-12-20 14:34:36
    什么是面向切面初听面向切面编程时, 一头雾水, 什么是面向切面, 只听说过面向对象(OOP), 面向过程(PO), 函数式编程(FP), 面向切面 ? 面向的难道是某一个面?面向搜索引擎后才了解到, 面向切面是一种编程范式(Aspect ...
  • 结合 Redux应用实例与 applyMiddleware源码,对 Redux中间件的实现原理进行分析。在此基础上,对“面向切面”这一经典的编程思想建立初步的认识。
  • 之前在专栏《SSM编程日记》中和大家分享了很多关于SSM框架的相关知识和技术,其实创作该专栏的目的不仅仅是为了记录自己学习过的技术,更是希望更多的小伙伴们能够通过这个更进一步的进阶Java这条不归路!...
  • 什么是Spring AOP(面向切面编程) AOP(Aspect Orient Programming),也就是 面向切面编程,AOP 是一种编程思想,是OOP(面向对象编程)的一种补充,面向对象编程将程序抽象成各个层次的对象,而面向切面编程是将程序...
  • Aspectj表示切面执行时间,用的通知(Advice)。 这个通知可以使用注解表示。 5个注解表示切面的5个执行时间, 这些注解叫做通知注解。 @Before : 前置通知 @AfterRetunring: 后置通知 @Around: 环绕通知 @...
  • 学习目的:学会使用注解进行面向切面编程(AOP),实现在面向切面编程(AOP)中,使用XML配置完成的操作。Part 1修改cn.vaefun.dao.UserServiceImpl.java,在类上添加Component注解,告诉spring这是一个bean,并命名为...
  • AOP: 面向切面编程 在不影响核心代码的前提下,可以在任意位置添加非核心代码。 可以使用spring 的aop来完成代理日志 (1) 把相关spring的依赖加入 <dependencies> <dependency> <groupId>...
  • 1. 面向切面编程 以下内容来自百度百科: 定义:面向切面编程(AOP,Aspect Oriented Programming)是通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。 作用:利用AOP可以对业务逻辑的各个...
  • 最简洁、最少侵入实现接口入参校验目录实现入参校验Aop使用入参校验Aop演示附实现入参校验Aop1..../*** 基础请求基类** @author: zetting* @date: 2018/8/22 7:15*/public ...实现入参校验切面package com.param.valid...
  • AOP面向切面编程 @Aspect注解描述的类我们称为切面对象,此对象负责定义切入点和通知 切入点 那些方法执行时我们进行功能拓展 @Pointcut("@annotation(.....)")通过@pointcut注解定义切入点表达式 @annotation...
  • AOP (Aspect Orient Programming),直译过来就是 面向切面编程。AOP 是一种编程思想,是面向对象编程(OOP)的一种补充。面向对象编程将程序抽象成各个层次的对象,而面向切面编程是将程序抽象成各个切面。 从...
  • (1)本篇博客的代码,基于【Spring AOP面向切面编程2:初识AOP二:AOP初体验;(一个Spring AOP的案例,走了一遍流程)】中的代码; (2)如在【Spring AOP面向切面编程2:初识AOP二:AOP初体验;(一个Spring AOP...
  • 1.aop全称Aspect Oriented Programming 面向切面编程2.aop应用场景场景一: 记录日志场景二: 监控方法运行时间 (监控性能)场景三: 权限控制场景四: 缓存优化 (第一次调用查询数据库,将查询结果放入内存对象, 第...
  • 我们为什么要使用AOP(面向切面编程)?当我们在现实中完成实际的项目时,我们总是需要在一个“动作”进行前,进行中,或进行后进行一些操作,比如当我们在运行程序时,我们想要进行日志保存,或者在每一个方法调用...
  • AOP (Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现在不修改源代码的情况下,给程序动态统一添加功能的一种技术,可以理解成动态代理。是Spring框架中的一个重要内容。利用 ...
  • 1、相关依赖包org.springframework.bootspring-boot-starter-aoporg.aspectjaspectjrt1.8.62、定义切面类package com.bz.aspect;import com.bz.service.SysLogOperationService;import org.aspectj.lang....
  • //从切面织入点处通过反射机制获取织入点处的方法 MethodSignature signature = (MethodSignature) joinPoint.getSignature(); //获取切入点所在的方法 Method method = signature.getMethod(); //获取操作 MyLog ...
  • 在进入实例之前,可以先看我引用的另一篇文章:一.... 创建AOP切面类,直接上代码这里为了简单明了,我将切面类分为普通类方法切面和自定义注解方法切面1.普通类方法切面类package com.example.demo.aop;import l...
  • 切面编程落实到软件工程其实是为了更好地模块化,而不仅仅是为了减少重复代码。通过 AOP 等机制,我们可以把横跨多个不同模块的代码抽离出来,让模块本身变得更加内聚,进而业务开发者可以更加专注于业务逻辑本身。...
  • 一直心心念的想写一篇关于AOP切面实例的博文,拖更了许久之后,今天终于着手下笔将...面向切面编程则是指,对于一个我们已经封装好的类,我们可以在编译期间或在运行期间,对其进行切割,把立方体切开,在原有的方法里
  • 面向切面编程

    2021-04-02 09:17:21
    1. SpringAOP基本概念 1.AOP概念和使用原因 现实中有 些内容并不是面向对象 (OOP )可以解决的,比如数据库...从上图可知,交易和账户都是对象,两个对象需要在同一个事务中控制,因此需要面向切面的方法,切面就是
  • 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个...
  • 1.切面类的实现 切面类都是通过实现各种特定的接口来实现的,缺点是必须要实现特定的接口,且一个类基本上只有一个重写方法是有用的。 对于普通的类,若不实现特定的接口,可以通过可以通过注解转化为切面类(通知类...
  • 文章目录Spring中的AOP切面编程的三种实现方式1.最基本AOP的实现a.引入jar包b.编写通知类,这里以后置通知和环绕通知类为例子进行说明c.在SpringIOC容器中配置d.测试2.使用注解对AOP进行实现a.引入jar包b.编写基于...
  • } 切面类: import com.his.common.result.CommonResult; import com.his.system.shiro.form.SysLoginForm; import com.his.uc.facade.ISettingFacade; import org.apache.dubbo.config.annotation.Reference; ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 111,901
精华内容 44,760
关键字:

切面编程