zoukankan      html  css  js  c++  java
  • Spring AOP AspectJ

    Spring框架建议您AOP实现上使用Spring AspectJ AOP实现,因为它为您提供了更多的控制并且易于使用。

    有两种方式可以实现Spring AOP AspectJ:

    • 基于注解(下面我们将讨论)
    • 基于xml配置

    Spring AspectJ AOP 实现提供了很多注解:

    • @Aspect 声明一个切面类
    • @Pointcut 声明一个切点表达式

    用于创建advices的注解如下:

    • @Before 声明一个before advice,它应用在实际方法调用之前
    • @After 声明一个after advice,它应用在实际方法调用之后
    • @AfterReturning 声明一个after returning advice,它应用在实际方法返回之后
    • @Around 声明一个around advice,它应用在实际方法调用前后
    • @AfterThrowing 声明一个 after throwing advice,它应用在实际方法抛出异常后

    理解Pointcut(切入点)

    切入点是Spring AOP的一种表达语言。

    @Pointcut批注用于定义切入点。我们也可以通过名称引用切入点表达式。让我们看一下切入点表达式的简单示例。

    @Pointcut("execution(* Operation.*(..))")  
    private void doSomething() {}  

    切入点表达式的名称为doSomething()。无论返回类型如何,它将应用于Operation类的所有方法。

    了解切入点表达式

    让我们尝试通过以下示例了解切入点表达式:

     @Pointcut("execution(public * *(..))")  

    它将应用于所有公共方法。

    @Pointcut("execution(public Operation.*(..))")  

    它将应用于Operation类的所有公共方法。

    @Pointcut("execution(public Employee.set*(..))")  

    它将应用于Employee类的所有公共setter方法。

    @Pointcut("execution(int Operation.*(..))")  

    它将应用于返回int值的Operation类的所有方法。

    1、@Before 例子

    目录结构如下:

    在实际业务逻辑方法之前应用AspectJ Before Advice。您可以在此处执行任何操作,例如conversion,authentication 等。创建一个包含实际业务逻辑的类。


    import org.springframework.stereotype.Component;

    /**
    * @author:crelle
    * @className:Operation
    * @version:1.0.0
    * @date:2020/9/21
    * @description:XX
    **/

    @Component(value = "beforeOperation")
    public class Operation {

    public void msg(){
    System.out.println("msg method invoked");
    }

    public int m(){
    System.out.println("m method invoked");return 2;
    }

    public int k(){
    System.out.println("k method invoked");return 3;
    }
    }

    现在,创建aspect类并且包含before advice。

    
    
    package crelle.test.aspectj.before;

    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Component;

    /**
    * @author:crelle
    * @className:TrackOperation
    * @version:1.0.0
    * @date:2020/9/21
    * @description:XX
    **/
    @Aspect
    @Component(value = "beforeTrackOperation")
    public class TrackOperation {

    /**
    *@author:crelle
    *@date:2020/9/21
    *@title:k
    *@description:pointcut name
    *@params:[]
    *@return:void
    *@throw:
    */
    @Pointcut("execution(* crelle.test.aspectj.before.Operation.*(..))")
    public void k(){};

    /**
    *@author:crelle
    *@date:2020/9/21
    *@title:myadvice
    *@description: applying pointcut on before advice
    *@params:[jp]
    *@return:void
    *@throw:
    */
    @Before("k()")
    public void myadvice(JoinPoint jp){
    System.out.println("additional concern");
    System.out.println("Method Signature:"+jp.getSignature());
    }
    }
     
    import crelle.test.aspectj.before.Operation;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.EnableAspectJAutoProxy;
    
    @SpringBootApplication
    @EnableAspectJAutoProxy
    public class SpringAopAspectjAnnotationExampleApplication implements CommandLineRunner {
    
        @Autowired
        private Operation operation;
    
        public static void main(String[] args) {
            SpringApplication.run(SpringAopAspectjAnnotationExampleApplication.class, args);
        }
    
        @Override
        public void run(String... args) throws Exception {
    
         System.out.println("calling msg...");
           operation.msg();
           System.out.println("calling m...");
           operation.m();
           System.out.println("calling k...");
           operation.k();
    
    
        }
    }

    结果:

    calling msg...
    additional concern
    Method Signature:void crelle.test.aspectj.before.Operation.msg()
    msg method invoked
    calling m...
    additional concern
    Method Signature:int crelle.test.aspectj.before.Operation.m()
    m method invoked
    calling k...
    additional concern
    Method Signature:int crelle.test.aspectj.before.Operation.k()
    k method invoked

    2、@After 例子

    它可以用来维护log,security,notification 等。

    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.Primary;
    import org.springframework.context.annotation.Scope;
    import org.springframework.core.annotation.AliasFor;
    import org.springframework.stereotype.Component;
    
    /**
     * @author:crelle
     * @className:Operation
     * @version:1.0.0
     * @date:2020/9/21
     * @description:XX
     **/
    @Component(value = "afterOperation")
    public class Operation {
    
        public void msg(){
            System.out.println("msg method invoked");
        }
    
        public int m(){
            System.out.println("m method invoked");return 2;
        }
    
        public int k(){
            System.out.println("k method invoked");return 3;
        }
    }

    现在,创建aspect类并且包含after advice。

    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Component;
    
    /**
     * @author:crelle
     * @className:TrackOperation
     * @version:1.0.0
     * @date:2020/9/21
     * @description:XX
     **/
    @Aspect
    @Component(value = "afterTrackOperation")
    public class TrackOperation {
    
        @Pointcut("execution(* Operation.*(..))")
        public void k() {
        }
    
        @After("k()")//applying pointcut on after advice
        public void myadvice(JoinPoint jp)//it is advice (after advice)
        {
            System.out.println("additional concern");
            //System.out.println("Method Signature: "  + jp.getSignature());
        }
    }
    package crelle.test.aspectj;
    
    import crelle.test.aspectj.after.Operation;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.EnableAspectJAutoProxy;
    
    @SpringBootApplication
    @EnableAspectJAutoProxy
    public class SpringAopAspectjAnnotationExampleApplication implements CommandLineRunner {
    
        @Autowired
        private Operation operation;
    
        public static void main(String[] args) {
            SpringApplication.run(SpringAopAspectjAnnotationExampleApplication.class, args);
        }
    
        @Override
        public void run(String... args) throws Exception {
            System.out.println("calling msg...");
            operation.msg();
            System.out.println("calling m...");
            operation.m();
            System.out.println("calling k...");
            operation.k();
    
        }
    }

    结果:

    calling msg...
    msg method invoked
    additional concern
    calling m...
    m method invoked
    additional concern
    calling k...
    k method invoked
    additional concern

    3、@AfterReturning 例子

    通过@AfterReturning,我们可以在advice中获得结果。

    import org.springframework.context.annotation.Configuration;
    import org.springframework.stereotype.Component;
    
    /**
     * @author:crelle
     * @className:Operation
     * @version:1.0.0
     * @date:2020/9/21
     * @description:XX
     **/
    @Component(value = "afterreturningOperation")
    public class Operation {
    
        public int m(){
            System.out.println("m() method invoked");
            return 2;
        }
        public int k(){
            System.out.println("k() method invoked");
            return 3;
        }
    }

    现在,创建aspect类并且包含afterreturning advice。

    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.AfterReturning;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Component;
    
    /**
     * @author:crelle
     * @className:TrackOperation
     * @version:1.0.0
     * @date:2020/9/21
     * @description:XX
     **/
    @Aspect
    @Component(value = "afterreturningTrackOperation")
    public class TrackOperation{
    
        @AfterReturning(pointcut = "execution(* Operation.*(..))",returning= "result")
        public void myadvice(JoinPoint jp, Object result)//it is advice (after returning advice)
            {
                System.out.println("additional concern");
                System.out.println("Method Signature: " + jp.getSignature());
                System.out.println("Result in advice: "+result);
                System.out.println("end of after returning advice...");
            }
    }
    package crelle.test.aspectj;
    
    import crelle.test.aspectj.afterreturning.Operation;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.EnableAspectJAutoProxy;
    
    @SpringBootApplication
    @EnableAspectJAutoProxy
    public class SpringAopAspectjAnnotationExampleApplication implements CommandLineRunner {
    
        @Autowired
        private Operation operation;
    
        public static void main(String[] args) {
            SpringApplication.run(SpringAopAspectjAnnotationExampleApplication.class, args);
        }
    
        @Override
        public void run(String... args) throws Exception {
    
            System.out.println("calling m...");
            System.out.println(operation.m());
            System.out.println("calling k...");
            System.out.println(operation.k());
    
    
        }
    }

    结果:

    calling m...
    m() method invoked
    additional concern
    Method Signature: int crelle.test.aspectj.afterreturning.Operation.m()
    Result in advice: 2
    end of after returning advice...
    2
    calling k...
    k() method invoked
    additional concern
    Method Signature: int crelle.test.aspectj.afterreturning.Operation.k()
    Result in advice: 3
    end of after returning advice...
    3

    4、@Around 例子

    around advice的AspectJ在调用实际的业务逻辑方法之前和之后都会应用。

    import org.springframework.stereotype.Component;
    
    /**
     * @author:crelle
     * @className:Operation
     * @version:1.0.0
     * @date:2020/9/21
     * @description:XX
     **/
    @Component(value = "aroundOperation")
    public class Operation {
    
        public void msg(){
            System.out.println("msg() is invoked");
        }
        public void display(){
            System.out.println("display() is invoked");
        }
    }

    现在,创建aspect类并且包含around advice。

    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Pointcut;
    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Component;
    
    /**
     * @author:crelle
     * @className:TrackOperation
     * @version:1.0.0
     * @date:2020/9/21
     * @description:XX
     **/
    @Aspect
    @Component(value = "aroundTrackOperation")
    public class TrackOperation {
        @Pointcut("execution(* Operation.*(..))")
        public void abcPointcut() {
        }
    
        @Around("abcPointcut()")
        public Object myadvice(ProceedingJoinPoint pjp) throws Throwable {
            System.out.println("Additional Concern Before calling actual method");
            Object obj = pjp.proceed();
            System.out.println("Additional Concern After calling actual method");
            return obj;
        }
    }
    package crelle.test.aspectj;
    
    import crelle.test.aspectj.around.Operation;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.EnableAspectJAutoProxy;
    
    @SpringBootApplication
    @EnableAspectJAutoProxy
    public class SpringAopAspectjAnnotationExampleApplication implements CommandLineRunner {
    
        @Autowired
        private Operation operation;
    
        public static void main(String[] args) {
            SpringApplication.run(SpringAopAspectjAnnotationExampleApplication.class, args);
        }
    
        @Override
        public void run(String... args) throws Exception {
            operation.msg();
            operation.display();
    
        }
    }

    结果:

    Additional Concern Before calling actual method
    msg() is invoked
    Additional Concern After calling actual method
    Additional Concern Before calling actual method
    display() is invoked
    Additional Concern After calling actual method

    5、@AfterThrowing 例子

    通过使用@AfterThrowing,我们可以在TrackOperation类中打印异常。让我们看一下AspectJ AfterThrowing advice的示例。

    import org.springframework.stereotype.Component;
    
    /**
     * @author:crelle
     * @className:Operation
     * @version:1.0.0
     * @date:2020/9/21
     * @description:XX
     **/
    @Component(value = "afterthrowingOperation")
    public class Operation {
    
        public void validate(int age)throws Exception{
            if(age<18){
                throw new ArithmeticException("Not valid age");
            }else{
                System.out.println("Thanks for vote");
            }
        }
    }

    现在,创建aspect类并且包含after throwing advice。

    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.AfterThrowing;
    import org.aspectj.lang.annotation.Aspect;
    import org.springframework.stereotype.Component;
    
    /**
     * @author:crelle
     * @className:TrackOperation
     * @version:1.0.0
     * @date:2020/9/21
     * @description:XX
     **/
    @Aspect
    @Component(value = "afterthrowingTrackOperation")
    public class TrackOperation {
    
        @AfterThrowing(
                pointcut = "execution(* Operation.*(..))",
                throwing= "error")
        public void myadvice(JoinPoint jp, Throwable error)//it is advice
        {
            System.out.println("additional concern");
            System.out.println("Method Signature: "  + jp.getSignature());
            System.out.println("Method params:" + jp.getArgs().toString());
            System.out.println("Exception is: "+error);
            System.out.println("end of after throwing advice...");
        }
    }
    package crelle.test.aspectj;
    
    import crelle.test.aspectj.afterthrowing.Operation;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.context.annotation.EnableAspectJAutoProxy;
    
    @SpringBootApplication
    @EnableAspectJAutoProxy
    public class SpringAopAspectjAnnotationExampleApplication implements CommandLineRunner {
    
        @Autowired
        private Operation operation;
    
        public static void main(String[] args) {
            SpringApplication.run(SpringAopAspectjAnnotationExampleApplication.class, args);
        }
    
        @Override
        public void run(String... args) throws Exception {
            try{
                operation.validate(19);
            }catch(Exception e){
                System.out.println(e);
            }
    
             System.out.println("calling validate again...");
    
            try{
                operation.validate(11);
            }catch(Exception e){
                System.out.println(e);
            }
    
        }
    }

    结果:

    Thanks for vote
    calling validate again...
    additional concern
    Method Signature: void crelle.test.aspectj.afterthrowing.Operation.validate(int)
    Method params:[Ljava.lang.Object;@6bb2d00b
    Exception is: java.lang.ArithmeticException: Not valid age
    end of after throwing advice...
    java.lang.ArithmeticException: Not valid age

    完毕!

  • 相关阅读:
    nginx 过滤了自定义的请求头参数
    Mysql5.7查看已经执行的sql语句
    Reids5 持久化
    JS 格式化时间,转成 几天前,几个月前
    个人小镜像站点
    记录一次清理Redis 病毒程序 kdevtmpfsi
    laravels 热重启
    Redis 布隆器安装和简单实现
    Redis Zset类型跳跃表算法实现(JAVA)
    Redis5 基于Lua实现分布式排它锁
  • 原文地址:https://www.cnblogs.com/crelle/p/13709149.html
Copyright © 2011-2022 走看看