Spring AOP学习笔记(一)-AOP相关概念和基于注解方式实现AOP的规则

一、 Spring AOP 概念

其实AOP就是要将我们Aspect中的Pointcut和Target Object中的JointPoint动态的连接起来,同时我们通过Advice指明Pointcut执行的一个时机。这是个人理解
AOP相关名词解释

名词 解释
Ascpect 横跨多个类的模块化关注点
Pointcut 切面中的方法指明在需要执行的方法
Advice 执行Pointcut的时机,也就是Pointcut什么时候执行
Target Object Aspect关注的对象
Joint Point 表示目标对象执行的方法

Advice 的分类

Adice种类 解释
Before Advice 在Joint Point(执行方法)之前执行Pointcut方法)
After return Advice 在 Joint Point(执行方法)正常退出时执行Pointcut
After throwing Advice 在Joint Point(执行方法)抛出异常退出时执行Pointcut
After Advice 在Joint Point(执行方法)退出(不管是正常退出还是抛异常退出)时执行Pointcut
Around Advice 在Joint Point(执行方法)被调用之前和之后都会执行Pointcut

二、注解的方式声明一个切面

2.1、切面中涉及的注解
注解 声明地点 使用方式
@Aspect 声明在类上 表明这时一个Aspect
@Pointcut 声明在Pointcut(Aspect的方法)上 指明和哪个Target Object 的Joint Point进行连接
@Before 声明注解在Aspect的方法上 表明在Joint Point(执行方法)之前执行Aspect的方法
@AfterReturning 声明注解在Aspect的方法上 表明在 Joint Point(执行方法)正常退出时执行Aspect的方法
@AfterThrowing 声明注解在Aspect的方法上 表明在Joint Point(执行方法)抛出异常退出时执行执行Aspect的方法
@After 声明注解在Aspect的方法上 表明在Joint Point(执行方法)被调用之前和之后都会执行执行Aspect的方法
2.2、声明一个Aspect
package com.zbt.day03;

import org.aspectj.lang.annotation.*;

@Aspect
public class AfterThrowingAspect {
}

在Spring上下文中配置Bean注入,因为Aspect也是一个类,需要使用注入的方式让Spring管理一个Bean

<aop:aspectj-autoproxy/>//开启Spring AOP自动代理功能
<bean id="audience" class="com.zbt.day01.Audience"></bean>

因为使用@AspectJ表示我们已经放弃了自动代理(auto-proxy)的方式,因此我们需要使用注解的方式@Component或者在Spring上下文中配置自动代理。

2.3、切点表达式
方法 描述
execution(public * *(..)) 执行那些方法为public的Joint Point
execution(* set*(..)) 执行那些方法名为set的Joint Point
execution(* com.xyz.service.AccountService.*(..)) 执行com.xyz.service.AccountService中所有的JointPoint(方法)
execution(* com.xyz.service.* . *(..) 执行com.xyz.service包中任何的JointPoint(方法)
execution(* com.xyz.service..* . *(..)) 执行com.xyz.service..* . *(..))包和其子包下面所有的JointPoint(方法)
within(com.xyz.service.*) 执行所有在com.xyz.service包中所有的JointPoint(方法)
this(com.xyz.service.AccountService)
target(com.xyz.service.AccoutnService) 执行实现了com.xyz.service.AccoutnService接口的所有的类的JointPoint(方法)
args(java.io.Serializable) 执行任何链接点参数只有一个,且指定参数类型为运行时Serializable(我们可以指定任意参数类型,只要是我们需要的)
@target(org.springframework.transaction.annotation.Transactional) 执行目标对象注解了@Transaction注解的方法
bean(tradeService)
bean(*Service)
2.4、声明一个Advice

@Before

    @Before("execution(* com.zbt.day03.ThrowExceptionApp.division(..))")
    public void beforeJointPoint(){
        System.out.println("在Joint Point执行前执行此方法");
    }

@AfterThrowing

    @AfterThrowing("execution(* com.zbt.day03.ThrowExceptionApp.division(..))")
    public void printAbonormal(){
        System.out.println("在Joint Point抛出异常后执行此方法");
    }

@AfterReturning

    @AfterReturning("execution(* com.zbt.day03.ThrowExceptionApp.division(..))")
    public void printNormal(){
        System.out.println("在Joint Point正常退出执行此方法");
    }

@After

    @After("execution(* com.zbt.day03.ThrowExceptionApp.division(..))")
    public void print(){
        System.out.println("不管Joint Point是正常退出还是异常退出都执行此方法");
    }

@Round

示例
编写Aspect和Advice

package com.zbt.day03;

import org.aspectj.lang.annotation.*;

@Aspect
public class AfterThrowingAspect {
    @Before("execution(* com.zbt.day03.ThrowExceptionApp.division(..))")
    public void beforeJointPoint(){
        System.out.println("在Joint Point执行前执行此方法");
    }
    @AfterThrowing("execution(* com.zbt.day03.ThrowExceptionApp.division(..))")
    public void printAbonormal(){
        System.out.println("在Joint Point抛出异常后执行此方法");
    }
    @AfterReturning("execution(* com.zbt.day03.ThrowExceptionApp.division(..))")
    public void printNormal(){
        System.out.println("在Joint Point正常退出执行此方法");
    }
    @After("execution(* com.zbt.day03.ThrowExceptionApp.division(..))")
    public void print(){
        System.out.println("不管Joint Point是正常退出还是异常退出都执行此方法");
    }
}

编写Target Object和Joint Point(Target 中的方法)

package com.zbt.day03;

/**
 * Created by luckyboy on 2018/8/15.
 */
public class ThrowExceptionApp {
    public int division(int a,int b){
        int i = 0;
        try{
           i =  a/b;
        }catch (Exception e){
            throw e;
        }
        return i;
    }
}

代码测试

package com.zbt.day03;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestAdvice {
    @Test
    public void testPerformance(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationConfig.xml");
        ThrowExceptionApp throwExceptionApp = context.getBean("throwExceptionApp",ThrowExceptionApp.class);
        throwExceptionApp.division(1,1);
    }
}

猜你喜欢

转载自blog.csdn.net/makeliwei1/article/details/81711182