Spring系列之:AOP

一,相关名词

切面(Aspect):一个横切功能的模块化,这个功能可能会横切多个对象(业务),比如:aMethod()方法就是一个"切面",它横切到多个业务中

切入点(Pointcut):可以插入 "横切逻辑(如aMethod())"的方法。比如:"调用add()"就是一个切点。

通知:

前置通知(Before Advice):在切入点add()方法执行之前,插入的通知。

后置通知(After Returning Advice):在切入点add()方法执行完毕之后,插入的通知

异常通知(After Throwing Advice):在切入点add()方法抛出异常时,插入的通知

最终通知(After FinallyAdvice):当切入点add()方法执行完毕时,插入的通知(不论是正常返回还是异常退出)

环绕通知(Around Advice):可以贯穿切入点add()方法执行的整个过程。

二,通知

1,我们想把一个普通的类变成一个特定功能的类。有三种方法:

继承类

实现接口

加注解

配置

2,把一个普通的类 变成 "通知",

2.1,通过让类实现接口来实现

通知类型          需要实现的接口         接口中的方法       执行时机

前置通知  org.springframework.aop.MethodBeforeAdvice    before()       目标方法执行前      

后置通知  org.springframework.aop.AfterReturningAdvice   afterReturning()    目标方法执行后

异常通知  org.springframework.aop.ThrowsAdvice        无          目标方法发生异常时

环绕通知  org.aopalliance.intercept.MethodInterceptor     invoke()    拦截对目标方法调用,即调用目标方法的整个过程

2.2, 以后置通知为例:

实现逻辑(三步):

  A,需要通知类  ---->  普通类实现接口

  B,业务类,业务方法  ------>  StudentServiceImpl中的addStudent();

  C,配置:

    将业务类,通知 纳入springIOC容器

    定义切入点(一端),定义通知类(另一类),通过pointcut-ref将两端连接起来

代码实现:

业务类:

public class StudentServiceImpl implements StudentService{

  @Autowried

  private StudentDao studentDao;

  public int addStudent(Student student){

    int result = studentDao.insert(student);

    System.out.println("添加学生");

    return result;

  }

}

通知类:

public class LogAfter implements AfterReturningAdvice{

   @Override

   public void afterReturning(Object returnValue,Method mehtod,Object[] args,Object target)throws Throwable{

      Sysout.out.println(" 前置通知 ");

      //我们还可以拿到目标对象的一些属性。对于studentService.addStudent(); 来说,studentService就是目标对象

      Sysout.println("目标对象:" + target + "调用的方法名:"+method.getName()+"方法参数的个数:"+args.length+",方法的返回值:"+ returnValue);

   }

}

配置:application.xml

//将业务类纳入springIOC容器

<bean id = "studentService" class = "org.yaming.service.StudentService">

  <property name = "stuentDao" ref = "studentDao"></property>

</bean>

//将通知纳入springIOC容器

<bean id = "LogAfter" class = "org.yaming.aop.LogAfter"></bean>

<aop:config>

  //切入点(连接线的一端:业务类的具体方法)

  <aop:pointcut expression = "execution(public * org.yaming.service.StudentServiceImpl.addStudent(..))"  id = "pointcut"/>

  //连接线的另一端:通知类

  <aop:advisor advice-ref = "LogAfter" pointcut-ref = "pointcut"/>

</aop:config>

 

3,通过注解来实现

3.1,代码示例:

@Aspect //声明该类是一个通知

public class LogBeforeAnnotation(){

  @Before("execution(public * addStudent(..))")

  public void myBefore(){

    System.out.println("注解形式---前置通知")

  }

  @AfterReturning("execution(public * addStudent(..))")

  public void myAfter(){

    System.out.println("注解形式---后置通知")

  }

}

开启注解对AOP的支持: <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

3.2,通过注解形式实现的aop,如果想获取目标对象的一些参数,需要使用一个对象:JoinPoint

public class LogBeforeAnnotation(){

  @Before("execution(public * addStudent(..))")

  public void myBefore(JointPoint jp){

    System.out.println("注解形式---前置通知");

    System.out.println("目标对象:" + jp.getTarget()+",方法名:"+jp.getSignature().getName()+",参数列表:"+Arrays.toString(jp.getArgs()));

  }

 

  @AfterReturning("execution(public * addStudent(..))" , returning = "returningValue")

  public void myAfter(JoinPoint jp,Object returningValue){

    System.out.println("注解形式---后置通知");

    System.out.println("目标对象:" + jp.getTarget()+",方法名:"+jp.getSignature().getName()+",参数列表:"+Arrays.toString(jp.getArgs()) + ",返回值:"+returningValue);

  }

}

 

posted @ 2019-05-07 20:46  inspire0x001  阅读(187)  评论(0编辑  收藏  举报