列子、
public interface Calculator {
// 加
public int add(int i,int j);
// 减
public int sub(int i,int j);
// 乘
public int mul(int i,int j);
//除
public int div(int i,int j);
}
@Service
public class MyMathCalculator implements Calculator {
@Override
public int add(int i, int j) {
int result = i + j;
return result;
}
@Override
public int sub(int i, int j) {
int result = i - j;
return result;
}
@Override
public int mul(int i, int j) {
int result = i * j;
return result;
}
@Override
public int div(int i, int j) {
int result = i / j;
return result;
}
}
/**
* 如何将这个类(切面类)中的这些方法(通知方法)动态的在目标方法运行的各个位置切入
*
*
*/
@Aspect
@Component
public class LogUtils {
@Pointcut("execution(public int com.atguigu.impl.MyMathCalculator.*(..))")
public void MyPoint(){};
/**
*告诉spring每个方法都什么时候运行;
*
* try{
* @Before
* method.invoke(obj,args);
* @AfterReturning
* }catch(e){
* @AfterThrowing
* }finally{
* @After
* }
*
*
*
* 5个通知
* @Before:在目标方法之前运行
* @After:在目标方法结束之后
* @AfterReturning:在目标方法正常返回之后
* @AfterThrowing:在目标方法抛出异常之后运行
* @Around:环绕
*
* //execution(访问权限符 返回值类型 方法签名)
*
*/
// @Before("execution(public int com.apcstudy.aop.impl.MyMathCalculator.*(..))")
@Before(value = "MyPoint()")
public static void logStart(JoinPoint joinPoint){
//获取到目标方法运行是使用的参数
Object[] args = joinPoint.getArgs();
//获取到方法签名
Signature signature = joinPoint.getSignature();
String name = signature.getName();
System.out.println("【"+name+"】方法开始执行,用的参数列表【"+ Arrays.asList(args)+"】");
}
/**
* 告诉Spring这个result用来接收返回值:
* returning="result";
* @param joinPoint
* @param result
*/
@AfterReturning(value = "execution(public int com.apcstudy..impl.MyMathCalculator.*(..))",returning = "result")
public static void logReturn(JoinPoint joinPoint,Object result){
System.out.println("【"+joinPoint.getSignature().getName()+"】方法正常执行完成,计算结果是:"+result);
}
/**
* 细节四:我们可以在通知方法运行的时候,拿到目标方法的详细信息;
* 1)只需要为通知方法的参数列表上写一个参数:
* JoinPoint joinPoint:封装了当前目标方法的详细信息
* 2)、告诉Spring哪个参数是用来接收异常
* throwing="exception":告诉Spring哪个参数是用来接收异常
* 3)、Exception exception:指定通知方法可以接收哪些异常
*
* ajax接受服务器数据
* $.post(url,function(abc){
* alert(abc)
* })
*/
@AfterThrowing(value = "execution(public int com.apcstudy..MyMathCalculator.*(..))",throwing = "exception")
public static void logException(JoinPoint joinPoint,Exception exception){
System.out.println("【"+joinPoint.getSignature().getName()+"】方法执行出现异常了,异常信息是【"+exception+"】:;这个异常已经通知测试小组进行排查");
}
/**
* Spring对通知方法的要求不严格;
* 唯一要求的就是方法的参数列表一定不能乱写?
* 通知方法是Spring利用反射调用的,每次方法调用得确定这个方法的参数表的值;
* 参数表上的每一个参数,Spring都得知道是什么?
* JoinPoint:认识
* 不知道的参数一定告诉Spring这是什么?
* @param joinPoint
* @return
*/
@After("execution(public int com.apcstudy.aop.impl.MyMathCalculator.*(..))")
private int logEnd(JoinPoint joinPoint){
System.out.println("【"+joinPoint.getSignature().getName()+"】方法最终结束了");
return 0;
}
}
public class AOPTest {
ApplicationContext ioc = new ClassPathXmlApplicationContext("conf/applicationContext.xml");
/**
* 通知方法的执行顺序;
*
* try{
* @Before
* method.invoke(obj,args);
* @AfterReturning
* }catch(){
* @AfterThrowing
* }finally{
* @After
* }
*
* 正常执行: @Before(前置通知)=====@After(后置通知)====@AfterReturning(正常返回);
* 异常执行: @Before(前置通知)=====@After(后置通知)===@AfterThrowing(方法异常)
*
*/
@Ignore
public void test01(){
// 一定要从容器中拿到目标对象;注意:如果想要用类型,一定要用他的接口类型,不要用本类;
Calculator calculator = ioc.getBean(Calculator.class);
calculator.add(2, 12);
}
@Test
public void test02(){
// 一定要从容器中拿到目标对象;注意:如果想要用类型,一定要用他的接口类型,不要用本类;
Calculator calculator = ioc.getBean(Calculator.class);
calculator.add(2, 12);
System.out.println("=================");
calculator.div(1, 0);
}
}