面向切面编程AOP:基于注解的配置

Aop编程就是面向编程的羝是切面,而切面是模块化横切关注点。

     -切面:横切关注点,被模块化的特殊对象。

     -通知:切面必须要完成的工作

     -目标:被通知的对象

     -代理:向目标对象应用通知之后创建的对象。

     -连接点:程序执行的某个特定的位置。

    -切点:相当于查询条件

其配置文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">
       <!--加入自动扫描的包-->
       <context:component-scan base-package="com.sevenhu.AOPTests"></context:component-scan>
       <!--使AspesctJ的注解起作用-->
       <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

 声明切面的两种方式:

       1.基于XML配置文件的方式:只需要在IOC容器中将切面声明为bean实例,当在Spring IOC容器中初始化AspectJ切面之后,Spring IOC容器会为那些与AspectJ切面相匹配的bean创建代理。

       2.基于注解的方式:在AspectJ注解中,切面只是一个带有@Aspect注解的java类。

AspectJ支持5中类型的通知注解:

1.@Before:前置通知,在方法执行前执行

2.@After:后置通知,在方法执行后执行

3.@AfterReturning:返回通知,在方法返回结果之后执行

4.@AfterThrowing:异常通知,在方法抛出异常之后执行

5.@Around:环绕通知,围绕着方法执行。

上代码,首先建立一个bean实例:

package com.sevenhu.AOPTests;

import org.springframework.stereotype.Component;

/**
 * Created by hu on 2016/4/1.
 */
@Component
public class Calculator {
    //加
    public int add(int a,int b){
        return a+b;
    }
    //减
    public int sub(int a,int b){
        return a-b;
    }
    //乘
    public int multiply(int a,int b){
        return a*b;
    }
    //除
    public double divide(int a,int b) throws Exception {
        if(b==0){
            throw new Exception();
        }else{
            return a/b;
        }
    }
}

  切面代码如下:

package com.sevenhu.AOPTests;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;

/**
 * Created by hu on 2016/4/1.
 */
@Aspect
@Component
public class AspectDemo {
    //可以在通知方法中声明一个类型为JoinPoint的参数,然后就可以访问链接的细节,如方法名和参数值

    //前置通知
    @Before("execution(public int com.sevenhu.AOPTests.Calculator.*(int ,int ))")
    public void beforeMethod(JoinPoint joinPoint){
        String methodName=joinPoint.getSignature().getName();
        Object[] args=joinPoint.getArgs();
        System.out.println("The method "+methodName+" begins with "+ Arrays.asList(args));
    }
    //后置通知:在连接点完成之后执行,即连接点返回结果或抛出异常的时候。
    @After("execution(public int com.sevenhu.AOPTests.Calculator.*(int ,int ))")
    public void afterMethod(JoinPoint joinPoint){
        String methodName=joinPoint.getSignature().getName();
        System.out.println("The method "+methodName+" ends");
    }
    //返回通知:只在连接点返回结果的时候执行(即不抛出异常),并且还可以访问返回结果
    @AfterReturning(pointcut = "execution(public int com.sevenhu.AOPTests.Calculator.*(int ,int ))",returning = "result")
    public void afterMethodReturning(JoinPoint joinPoint,Object result){//必须在方法签名中添加一个同名的参数“result”,Spring会通过这个参数传递返回值
        String methodName=joinPoint.getSignature().getName();
        System.out.println("The method "+methodName+" ends with a returning value "+result);
    }
    //异常通知:只有在连接点抛出异常的时候才会执行异常通知
    @AfterThrowing(pointcut = "execution(public int com.sevenhu.AOPTests.Calculator.*(int ,int ))",throwing = "e")
    public void afterMethodThrowing(JoinPoint joinPoint,Exception e){//必须在方法签名中添加一个同名的参数“e”,Spring会通过这个参数传递异常对象
        String methodName=joinPoint.getSignature().getName();
        System.out.println("The method "+methodName+" has thrown a exception: "+e.getMessage());
    }
    //环绕通知:环绕通知是所有通知中功能最为强大的,能够全面控制连接点,甚至可以控制是否执行连接点,对于环绕通知,连接点参数是必须的
    /*
    * ProceedingJoinPoint是JoinPoint的子接口,允许控制何时执行,是否执行连接点
    * 在环绕通知中需要明确调用ProceedingJoinPoint的proceed()方法来执行被代理的方法,如果忘记这样做就会导致通知被执行了,但是目标方法没有被执行。
    * 注:环绕通知的方法需要返回目标方法执行之后的结果,即joinPoint.proceed();的返回值,否则 会出现空指针异常
    * */
    @Around("execution(public int com.sevenhu.AOPTests.Calculator.*(int ,int ))")
    public void aroundMethod(ProceedingJoinPoint joinPoint)  {
        String methodName=joinPoint.getSignature().getName();
        System.out.println("The method "+methodName+" begins");//相当于前置通知
        try{
            joinPoint.proceed();//执行连接点方法
        }catch (Throwable e){
            System.out.println("An Exception happened");//相当于异常通知
        }
        System.out.println("The method "+methodName+" ends");//相当于后置通知
    }
}

  指定切面的优先级

    在同一个连接点上可能不止一个切面,除非明确指定,否则它们的优先级是不确定的,切面的优先级可以通过实现Ordered接口 或@Order注解指定。

    实现Order接口,getOrder()方法的返回值越小,优先级越高,常用的也就是使用注解的方式,所以具体方法如下:

@Aspect
@Order(0)
 class Order1{
     ...
 }
@Aspect
@Order(1)
class Order2{
    ...
}

重用切入点定义

     在编写AspectJ切面时,可以直接在通知注解中书写切入点表达式,但是一个切入点表达式可能会在通知中重复出现。在AspectJ切面中,可以通过@PointCut注解将一个切入点声明成简单的方法,切入点的方法体通常是空的。其具体用法如下:

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

    @Before("pointCut()")
    public void beforeMethod(){
        System.out.println("doning sth...");
    }

  

    

转载于:https://www.cnblogs.com/hujingwei/p/5344227.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值