zoukankan      html  css  js  c++  java
  • Spring_9_AspectJ-Advice定义及实例

    =Advice定义及实例===================================================
    Before advice


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

    @Component
    @Aspect
    public class MoocAspect {
     
     @Before("execution(* com.imooc.aop.aspectj.biz.*Biz.*(..))")//在执行com.imooc.aop.aspectj包下以Biz结尾的类所有方法时匹配Advice
     public void before() {
      System.out.println("Before.");
     } 
    }

    =============================================
    After Returning advice

    @Aspect
    public class AfterReturningExample {
     @AfterReturning("com.xyz.myapp.SystemArchitecture.dateAccessOperation()")
     public void doAccessCheck() {
     //...
     }
    }
    ·有时又需要在通知体内得到返回的实际值,可以使用@AfterReturning绑定返回值的形式
    @Aspect
    public class AfterReturningExample {
     @AfterReturning(
         pointcut="com.xyz.myapp.SystemArchitecture.dateAccessOperation()",
         returning="retVal")
     public void doAccessCheck(Object retVal) //不确定返回值类型,使用Object,确定时可使用相应类型
     {
     //...
     }
    }
    ====================================================
    After Throwing advice

    @Aspect
    public class AfterThrowingExample {
     @AfterThrowing("com.xyz.myapp.SystemArchitecture.dateAccessOperation()")
     public void doAccessCheck() {
     //...
     }
    }
    ·有时又需要在通知体内得到返回的实际值,可以使用@AfterThrowing绑定返回值的形式
    @Aspect
    public class AfterThrowingExample {
     @AfterThrowing(
         pointcut="com.xyz.myapp.SystemArchitecture.dateAccessOperation()",
         throwing="ex")
     public void doAccessCheck(DateAccessException ex) //不确定返回值类型,使用Object,确定时可使用相应类型
     {
     //...
     }
    }
    ====================================================
    After (finally) advice
    最终通知必须准备处理正常和异常两种返回情况,它通常用于释放资源
    像是java的try catch finally代码块的finally 通常用于释放资源
    @Aspect
    public class AfterFinallyExample {
     @After("com.xyz.myapp.SystemArchitecture.dateAccessOperation()")
     public void doReleaseLock() {
     //...
     }
    }
    ====================================================
    Around advice
    ·环绕通知使用@Around注解来生命,通知方法的第一个参数必ProceedingJoinPoint类型
    ·在通知内部调用ProceedingJoinPoint的proceed()方法导致执行真正的方法,传到一个Object[]对象,
    数组中的值将作为参数传递给方法 proceed[proʊˈsi:d]vi.进行;前进;尤指打断后)继续说 n收入获利
    @Aspect
    public class AroundExample {
     @Around("com.xyz.myapp.SystemArchitecture.dateAccessOperation()")
     public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Trowable {//pjp.proceed()可能会抛出异常处理方式1.throws 该exception2.catch该异常
     //start stopwatch
     Object retVal = pjp.proceed();//真正执行方法的步骤,不知道真正的方法是否有返回值,
     //所以用通用类型Object接收(void也是特殊类型的返回值)
     //stop  stopwatch
     }
    }
    ==Advicer扩展==================================================
    给advice传递参数
    方式1 用来获取相应的参数进行判断或记录
    @Before("com.xyz.myapp.SystemArchitecture.dateAccessOperation() && args(account,..)")//account与方法参数的名称一致
    public void validateAccount(Account account) {
     System.out.println("Before.");
    }
    方式2(与方式1等效)
    @Pointcut("com.xyz.myapp.SystemArchitecture.dateAccessOperation() && args(account,..)")//account与方法参数的名称一致
    public void accountDataAccessPoeration(Account account) {}

    @Before("accountDataAccessPoeration(account)")
    public void validateAccount(Account account) {
     System.out.println("Before.");
    }

    方式3:作用1 记录 2 判断方法用了哪些注解或者注解的值,根据注解的不同或注解value的不同,可以做一些前置的操作
    1)定义一个注解
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface Auditable { 
     AuditCode value();
    }
    2)使用该注解
    @Before("com.xyz.lib.Pointcuts.anyPublicMethod() && @annotation(auditable)")
    public void auditAuditable auditable){
     AuditCode code = auditable.value();
     //System.out.println("Before.");
    }

    ===Advice的参数及泛型=================================================
    ·Spring AOP可以处理泛型类的声明和使用方法的参数
    public interface Sample<T> {
     void sampleGenericMethod(T param);
     void sampleGenericCollectionMethod(Collection<T> param);
    }

    @Before("execution(* ..Sample+.sampleGenericMethod(*)) && args(param)")
    public void beforeSampleMethod(MyType param) {
     //advice implementation
    }
    @Before("execution(* ..Sample+.sampleGenericCollectionMethod(*)) && args(param)")
    public void beforeSampleGenericCollectionMethod(Collection<MyType> param) {
     //advice implementation
    }
    ===Advice参数名称=================================================
    通知和切入点注解有一个额外的"argNames"属性,它可以用来指定所注解的方法的参数名

    @Before(value = "com.xyz.lib.Pointcuts.anyPublicMethod() && target(bean) && @annotation(auditble)",
     argNames="bean,auditable")
    public void audit(Object bean,Auditable auditable){
     AuditCode code = auditable.value();
     //...use code and bean
    }
    如果第一个参数是JoinPoint,ProceedingJoinPoint,JoinPoint.StaticPart,那么可以忽略它
    @Before(value = "com.xyz.lib.Pointcuts.anyPublicMethod() && target(bean) && @annotation(auditble)",
     argNames="bean,auditable")
    public void audit(JoinPoint jp,Object bean,Auditable auditable){
     AuditCode code = auditable.value();
     //...use code and bean
    }
    ===Introductions=======================================================
    ·允许一个切面声明一个通知对象实现指定接口,并且提供了一个接口实现类来代表这些对象
    ·introduction使用@DeclareParents进行注解,这个注解用来定义匹配的类型拥有ige新的parent
    例如:给定一个接口UsageTracked,并且该接口拥有DefaultUsageTracked的实现,
    接下来的切面声明了所有service皆苦的实现都实现了UsageTracked接口

    @Aspect
    public class UsageTracking {
     @DeclareParents(value="com.xzy.myapp.service.*+",defaultImpl="DefaultUsageTracked.class")
     public static UsageTracked mixin;
     @Before("com.xyz.myapp.SystemArchitecture.bussinessService() && this(usageTracked)")
     public void recordUsage(UsageTracked usageTracked) {
      usageTracked.incrementUseCount();
     }
    }
    ====切面实例化模型===================================
    ·这是一个高级主题
    ·"perthis"切面通过指定@Aspect注解perthis子句实现
    ·每个独立的service对象执行时都会创建一个切面实例
    ·service对象的每个方法在第一次执行的时候创捷切面实例,切面在service对象失效的同事失效

    @Aspect("perthis(com.xyz.myapp.SystemArchitecture.businessService())")
    public class MyAspect {

     private int someState;

     @Before("com.xyz.myapp.SystemArchitecture.bussinessService()")
     public void recordServiceUsage () {
      //...
     }
    }


    ====================================================
    ====================================================

    定义注解

     1 package com.imooc.aop.aspectj;
     2 import java.lang.annotation.ElementType;
     3 import java.lang.annotation.Retention;
     4 import java.lang.annotation.RetentionPolicy;
     5 import java.lang.annotation.Target;
     6 @Retention(RetentionPolicy.RUNTIME)
     7 @Target(ElementType.METHOD)
     8 public @interface MoocMethod {
     9  
    10  String value();
    11 }


    ====================================================
    例子

     1 package com.imooc.aop.aspectj;
     2 
     3 import org.aspectj.lang.ProceedingJoinPoint;
     4 import org.aspectj.lang.annotation.After;
     5 import org.aspectj.lang.annotation.AfterReturning;
     6 import org.aspectj.lang.annotation.AfterThrowing;
     7 import org.aspectj.lang.annotation.Around;
     8 import org.aspectj.lang.annotation.Aspect;
     9 import org.aspectj.lang.annotation.Before;
    10 import org.aspectj.lang.annotation.Pointcut;
    11 import org.springframework.stereotype.Component;
    12 
    13 @Component
    14 @Aspect
    15 public class MoocAspect {
    16     
    17     //a    @Pointcut("execution(* com.imooc.aop.aspectj.biz.*Biz.*(..)) && @annotation(moocMethod)")
    18     //a    public void pointcut(MoocMethod moocMethod) {}
    19     @Pointcut("execution(* com.imooc.aop.aspectj.biz.*Biz.*(..))")
    20     public void pointcut() {}
    21     
    22     @Pointcut("within(com.imooc.aop.aspectj.biz.*)")
    23     public void bizPointcut() {}
    24     
    25     @Before("pointcut()")// pointcut()方法上面声明了一种类型的pointcut,此处可以使用代替@Before("execution(* com.imooc.aop.aspectj.biz.*Biz.*(..))")表达式
    26     public void before() {
    27         System.out.println("Before.");
    28     }
    29     
    30     @Before("pointcut() && args(arg)")
    31     public void beforeWithParam(String arg) {
    32         System.out.println("BeforeWithParam." + arg);
    33     }
    34     
    35     @Before("pointcut() && @annotation(moocMethod)")
    36     //a    @Before("pointcut(moocMethod)")
    37     public void beforeWithAnnotaion(MoocMethod moocMethod) {
    38         System.out.println("BeforeWithAnnotation." + moocMethod.value());
    39     }
    40     
    41     @AfterReturning(pointcut="bizPointcut()", returning="returnValue")
    42     public void afterReturning(Object returnValue) {
    43         System.out.println("AfterReturning : " + returnValue);
    44     }
    45     
    46     @AfterThrowing(pointcut="pointcut()", throwing="e")
    47     public void afterThrowing(RuntimeException e) {
    48         //e.printStackTrace();//调试时,可以打印出堆栈信息
    49         System.out.println("AfterThrowing : " + e.getMessage());
    50     }
    51     
    52     @After("pointcut()")
    53     public void after() {
    54         System.out.println("After.");
    55     }
    56 
    57     @Around("pointcut()")
    58     public Object around(ProceedingJoinPoint pjp) throws Throwable {
    59         System.out.println("Around 1.");
    60         Object obj = pjp.proceed();
    61         System.out.println("Around 2.");
    62         System.out.println("Around : " + obj);
    63         return obj;
    64     }
    65     
    66 }
     


    ==xml

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <beans xmlns="http://www.springframework.org/schema/beans"
     3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4     xmlns:context="http://www.springframework.org/schema/context"
     5     xmlns:aop="http://www.springframework.org/schema/aop"
     6     xsi:schemaLocation="http://www.springframework.org/schema/beans 
     7         http://www.springframework.org/schema/beans/spring-beans.xsd  
     8         http://www.springframework.org/schema/context
     9         http://www.springframework.org/schema/context/spring-context.xsd
    10         http://www.springframework.org/schema/aop 
    11         http://www.springframework.org/schema/aop/spring-aop.xsd">
    12         
    13         <context:component-scan base-package="com.imooc.aop.aspectj"/>
    14       <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    15  </beans>

    ==biz

     1 package com.imooc.aop.aspectj.biz;
     2 import org.springframework.stereotype.Service;
     3 import com.imooc.aop.aspectj.MoocMethod;
     4 @Service
     5 public class MoocBiz {
     6  
     7  @MoocMethod("MoocBiz save with MoocMethod.")//给注解赋值
     8  public String save(String arg) {
     9   System.out.println("MoocBiz save : " + arg);
    10 //  throw new RuntimeException(" Save failed!");
    11   return " Save success!";
    12  }
    13 }


    ==Test

     1 package com.imooc.test.aop.aspectj;
     2 import org.junit.Test;
     3 import org.junit.runner.RunWith;
     4 import org.junit.runners.BlockJUnit4ClassRunner;
     5 import com.imooc.aop.aspectj.biz.MoocBiz;
     6 import com.imooc.test.base.UnitTestBase;
     7 @RunWith(BlockJUnit4ClassRunner.class)
     8 public class TestAspectJ extends UnitTestBase {
     9  
    10  public TestAspectJ() {
    11   super("classpath:spring-aop-aspectj.xml");
    12  }
    13  
    14  @Test
    15  public void test() {
    16   MoocBiz biz = getBean("moocBiz");
    17   biz.save("This is test.");
    18  }
    19  
    20 }

  • 相关阅读:
    springboot整合邮件发送(163邮箱发送为例)
    MySQL 容器修改配置文件后无法启动问题(终极解决办法)
    SQLyog无操作一段时间后重新操作会卡死问题(解决办法)
    Linux中配置端口转发(反向代理)
    SpringBoot之整合Quartz调度框架-基于Spring Boot2.0.2版本
    shell脚本报错:-bash: xxx: /bin/sh^M: bad interpreter: No such file or directory
    用xshell连接linux服务器失败 Could not connect to '112.74.73.194' (port 22): Connection failed.
    GooglePlay的多apk命令行安装
    trojan阉割备份
    网易云音乐本地数据库的歌单列表导出,一个不丢,支持1000首以上
  • 原文地址:https://www.cnblogs.com/charles999/p/6672443.html
Copyright © 2011-2022 走看看