@AspectJ(一)

慕课网学习总结

配置@AspectJ

需要aspectjweaver.jar包

XML配置

@Component//这个类可以被spring的bean容器识别
@Aspect//声明这是一个切面类
public class MoocAspect {

}
xml配置文件:
//自动扫描

Java风格(注解)配置

aspect

  • @AspectJ切面使用@Aspect注解配置,拥有@Aspect的任何bean将被Spring自动识别并应用。
  • 用@Aspect注解的类可以有方法和字段,他们也可能包括切入点(pointcut),通知(Advice)和引入(introduction)声明。
  • @Aspect注解是不能够通过类路径自动检测发现的,所以需要配合使用@Component注释或者在xml配置bean。
@Component//这个类可以被spring的bean容器识别
@Aspect//声明这是一个切面类
@Configuration
@EnableAspectJAutoProxy//自动使用AspectJ代理
public class MoocAspect {
    //以biz结尾的任何类型方法都会匹配这个切入点
    @Pointcut("execution(* com.zzspring.dao.*Biz.*(..))")
    public void pointcut() {}
    
    //当前包下的任何类都会匹配到这个切入点
    @Pointcut("within(com.zzspring.dao.*)")
    public void bizPointcut() {}
    
//  @Pointcut("pointcut() && bizPointcut()")
//  private void trad() {}
    @Before("execution(* com.zzspring.dao.*Biz.*(..))")
    public void before() {
        System.out.println("Before");
        
    }
}
  • 一个类中的@Aspect注解标识它为一个切面,并且将自己从自动代理中排除。

pointcut

  • 一个切入点通过一个普通的方法定义来提供,并且切入点表达式使用@Pointcut注解,方法返回类型必须未void。
  • 定义一个名为' anyOldTransfer ',这个切入点将匹配任何名为" transfer "的方法的执行。
@Pointcut("execution(* transfer(..))")
    private void anyOldTransfer() {}
execution 匹配方法执行的连接点
within 限定匹配特定类型的连接点
this 匹配特定连接点的bean引用是指定类型的实例的限制
target 限定匹配特定连接点的目标对象是指定类型的实例
args 限定匹配特定连接点的参数是给定类型的实例
@target 限定匹配特定连接点的类执行对象的具有给定类型的注解
@args 限定匹配特定连接点的实际传入参数的类型具有给定类型的注解
@within 限定匹配到内具有给定的注释类型的连接点
@annotation 限定匹配特定连接点的的主体具有给定的注解

组合pointcut

  • 切入点表达式可以通过&&、|| 和!进行组合,也可以通过名字引用切入点表达式。
  • 通过组合,可以建立更加复杂的切入点表达式。
@Component
@Aspect
public class MoocAspect {
    //以Biz结尾的任何类的类型方法都会匹配这个切入点
    @Pointcut("execution(* com.zzspring.dao.*Biz.*(..)")
    private void pointcut() {}
    
    //当前包下的任何类型方法都会匹配到这个切入点
    @Pointcut("within(* com.zzspring.dao.*)")
    private void bizPointcut() {}
    
    //取pointcut()和bizPointcut()的交集
    @Pointcut("pointcut() && bizPointcut()")
    private void trad() {}
}
  • 定义良好的pointcuts
  • AspectJ是编译期的AOP。
  • 检查代码并匹配连接点与切入点的代价是昂贵的。
  • 一个好的切入点应该包括一下几点
    1.选择特定类型的连接点,入:execution,get,set,call,handler
    2.确定连接点范围 ,如:within,withincode
    3.匹配上下文信息,如:this,target,@annotation

Advice

@Before

@Component
@Aspect
@Configuration
@EnableAspectJAutoProxy
public class MoocAspect {
    //以biz结尾的任何类型方法都会匹配这个切入点
    @Pointcut("execution(* com.zzspring.dao.*Biz.*(..))")
    public void pointcut() {}
    
    //当前包下的任何类都会匹配到这个切入点
    @Pointcut("within(com.zzspring.dao.*)")
    public void bizPointcut() {}
    
    //以下2种方式都可以
    //@Before("pointcut()")
    @Before("execution(* com.zzspring.dao.*Biz.*(..))")
    public void before() {
        System.out.println("Before");
        
    }
}

@AfterReturning

@Component
@Aspect
@Configuration
@EnableAspectJAutoProxy
public class MoocAspect {
    //以biz结尾的任何类型方法都会匹配这个切入点
    @Pointcut("execution(* com.zzspring.dao.*Biz.*(..))")
    public void pointcut() {}
    
    //当前包下的任何类都会匹配到这个切入点
    @Pointcut("within(com.zzspring.dao.*)")
    public void bizPointcut() {}
    
    //returning="returnValue" 执行方法的返回值
    @AfterReturning(pointcut="pointcut()",returning="returnValue")
    public void afterReturning(Object returnValue) {
        System.out.println("AfterReturning : " + returnValue);
    }
}

@AfterThrowing

@Component
@Aspect
@Configuration
@EnableAspectJAutoProxy
public class MoocAspect {
    //以biz结尾的任何类型方法都会匹配这个切入点
    @Pointcut("execution(* com.zzspring.dao.*Biz.*(..))")
    public void pointcut() {}
    
    //当前包下的任何类都会匹配到这个切入点
    @Pointcut("within(com.zzspring.dao.*)")
    public void bizPointcut() {}
    
    //throwing="e"获取异常;打印异常信息
    @AfterThrowing(pointcut="pointcut()",throwing="e")
    public void afterThrowing(RuntimeException e) {
        //e.printStackTrace();
        System.out.println("afterThrowing : " +e.getMessage());
        
    }
    
}

@After(finally)advice

  • 最终通知必须准备处理正常和异常两种返回情况,它通常用于释放资源。
@Component
@Aspect
@Configuration
@EnableAspectJAutoProxy
public class MoocAspect {
    //以biz结尾的任何类型方法都会匹配这个切入点
    @Pointcut("execution(* com.zzspring.dao.*Biz.*(..))")
    public void pointcut() {}
    
    //当前包下的任何类都会匹配到这个切入点
    @Pointcut("within(com.zzspring.dao.*)")
    public void bizPointcut() {}
    
    @After("pointcut()")
    public void after() {
    System.out.println("after!!!!!");
    }   
}

Around advice

  • 环绕通知使用@Around注释来声明,通知方法的第一个参数必须是ProceedingJoinPoint类型。
  • 在通知内部调用ProceedingJoinPoint的proceed()方法会导致执行真正的方法,传入一个Object[]对象,数组中的值将被作为参数传递给方法。
@Component
@Aspect
@Configuration
@EnableAspectJAutoProxy
public class MoocAspect {
    //以biz结尾的任何类型方法都会匹配这个切入点
    @Pointcut("execution(* com.zzspring.dao.*Biz.*(..))")
    public void pointcut() {}
    
    //当前包下的任何类都会匹配到这个切入点
    @Pointcut("within(com.zzspring.dao.*)")
    public void bizPointcut() {}

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint pjb) throws Throwable {
        System.err.println("Around 1 ");
        Object obj = pjb.proceed();//proceed()方法会执行真正的方法
        System.err.println("Around 2 ");
        System.err.println("Around : " + obj);
        return obj;
    }
}

你可能感兴趣的:(@AspectJ(一))