• 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后置切面
    方法执行后
    方法返回后
    个人理解,如有错误,欢迎指正!
  • 相关阅读:
    @loj
    @codeforces
    @bzoj
    @hdu
    @poj
    @loj
    @bzoj
    @bzoj
    Python配合BeautifulSoup读取网络图片并保存在本地
    Java--多线程读取网络图片并保存在本地
  • 原文地址:https://www.cnblogs.com/gllegolas/p/11771627.html
Copyright © 2020-2023  润新知