SPRING学习(十九)--基于注解的AOP切面编程

Posted GLLegolas

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SPRING学习(十九)--基于注解的AOP切面编程相关的知识,希望对你有一定的参考价值。

上篇中介绍了基于XML配置的AOP切面编程,除了XML配置AOP切面编程外,还可以通过注解方式实现AOP切面编程,本篇通过一个小例子来介绍基于注解的AOP编程。

 

 

1、在spring中使用AOP变成,不止要导入spring-aop.jar,还需要导入spring-aspects.jar、aspectjweaver.jar和aopalliance.jar,但是aspectjweaver.jar被spring-aspects.jar依赖,aopalliance.jar被spring-aop.jar依赖,spring-aop.jar又被spring-mvc.jar依赖,所以只要导入spring-mvc.jar和spring-aspects.jar就行了。

 

2、spring-aop-annotion.xml

<?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:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <!-- 配置自动扫描的包 -->
    <context:component-scan base-package="springAopAnnotion"></context:component-scan>
    <!-- 自动为切面方法中匹配的方法所在的类生成代理对象。 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

 

3、被增强的类Sleep.java

package springAopAnnotion;

import org.springframework.stereotype.Component;

//将实现类加入Spring的IOC容器进行管理
@Component("sleeping")
public class Sleep {

    public void sleep(String who){
        System.out.println(who + " want to sleep!");
    }
}

4、增强类SleepAspect.java

package springAopAnnotion;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
 * * 有两种声明切入点方法
 * 1、提前声明切入点@PointCut,后续在切入方法中引用切入点
 * 2、直接在切入方法中声明切入点
 *     
 * 切入方式一共有五种
 * 1、方法执行前 @before
 * 2、方法执行后,返回前 @after
 * 3、方法返回后 @afterReturning
 * 4、方法执行前后 @around
 * 5、抛异常时候 @AfterThrowing
 * @author qiaozhong
 */
@Component
@Aspect
public class SleepAspect {
    
    /**
     * 提前声明切入点@PointCut,后续在切入方法中引用切入点
     * 声明方法执行前的切点
     */
    @Pointcut("execution(* springAopAnnotion.Sleep.*(..))")
    public void beforeMethod(){}
    
    /**
     * 提前声明切入点@PointCut,后续在切入方法中引用切入点
     * 声明方法执行后的切点
     */
    @Pointcut("execution(* springAopAnnotion.Sleep.*(..))")
    public void afterMethod(){}
    
    /**
     * 方法执行前,要织入的切面方法,切入点为之前声明的beforeMethod()
     * @param joinPoint
     */
    @Before("beforeMethod()")
    public void beforeAspect(JoinPoint joinPoint){
        System.out.println("方法执行前,入参="+joinPoint.getArgs()[0]);
    }
    
    /**
     * 方法执行后,返回前,要织入的切面方法,切入点为之前声明的afterMethod()
     * @param joinPoint
     */
    @After("afterMethod()")
    public void afterAspect(){
        System.out.println("方法执行后");
    }
    
    /**
     * 方法返回后,要织入的切面方法,切入点在本方法中直接配置
     * @param joinPoint
     */
    @AfterReturning(value="execution(* springAopAnnotion.Sleep.*(..))")
    public void afterReturnAspect(){
        System.out.println("方法返回后");
    }
    
     /**
     * 异常通知:目标方法发生异常的时候执行以下代码,切入点在本方法中直接配置
     */
    @AfterThrowing(value="execution(* springAopAnnotion.Sleep.*(..))",throwing="e")
    public void afterThorwingMethod(JoinPoint jp, NullPointerException e){
        String methodName = jp.getSignature().getName();
        System.out.println("【异常通知】the method 【" + methodName + "】 occurs exception: " + e);
    }
    
      /**
      * 环绕通知:目标方法执行前后分别执行一些代码,发生异常的时候执行另外一些代码,切入点在本方法中直接配置
      * @return 
      */
     @Around(value="execution(* springAopAnnotion.Sleep.*(..))")
     public void aroundMethod(ProceedingJoinPoint jp) {
         try {
             System.out.println("aroundMethod前置切面");
             jp.proceed();
             System.out.println("aroundMethod后置切面");
         } catch (Throwable e) {
             e.printStackTrace();
         }
     }
}

 

5、测试类

package springAopAnnotion;

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

public class TestSleep {
    public static void main(String[] args) {
        ApplicationContext ac = new ClassPathXmlApplicationContext("springConfig/spring-aop-annotion.xml");
        Sleep sleep = (Sleep)ac.getBean("sleeping");
        sleep.sleep("Little ball");
    }
}

 

结果:

aroundMethod前置切面
方法执行前,入参=Little ball
Little ball want to sleep!
aroundMethod后置切面
方法执行后
方法返回后

 

以上是关于SPRING学习(十九)--基于注解的AOP切面编程的主要内容,如果未能解决你的问题,请参考以下文章

spring学习5:基于注解实现spring的aop

Spring AOP基于@AspectJ注解的切面

阶段3 2.Spring_08.面向切面编程 AOP_9 spring基于注解的AOP配置

spring学习基于xml文件配置AOP

Spring AOP 切面编程的方法

Springday03 AOPSpring声明式事务Spring编程式事务