Spring aop的两种配置方式(XML配置AOP、注解配置AOP)

闲来无聊对项目中用到的AOP配置进行了一下归并。

AOP配置方式一(XML配置AOP):

   1. 编写通知类

 1 /**
 2  * 通过XML的方式配置AOP
 3  */
 4 public class AspectXmlCheck {
 5     Logger logger = LoggerFactory.getLogger(AspectXmlCheck.class);
 6 
 7     /**
 8      * 前通知方法
 9      * @param jp 连接点对象
10      */
11     public void beforeCheck(JoinPoint jp) {
12         Object[] args = jp.getArgs();
13         Stream.of(args).forEach(arg -> {
14             logger.info("before: " + (arg == null ? "null" : arg.toString()));
15         });
16     }
17 
18     /**
19      * 后通知方法
20      * @param jp 连接点对象
21      * @param retVal 连接点对象执行后返回的对象
22      */
23     public void afterCheck(JoinPoint jp, Object retVal) {
24         logger.info("after: " + (retVal == null ? "null" : retVal.toString()));
25     }
26 
27     /**
28      * 环绕通知方法
29      * @param pjp 连接点对象
30      */
31     public Object aroundCheck(ProceedingJoinPoint pjp) {
32         Object[] args = pjp.getArgs();
33         Stream.of(args).forEach(arg -> {
34             logger.info("around before: " + (arg == null ? "null" : arg.toString()));
35         });
36 
37         Object proceed = null;
38         try {
39             proceed = pjp.proceed();
40         } catch (Throwable throwable) {
41             logger.error("around execute error:", throwable);
42         }
43         logger.info("around after: " + (proceed == null ? "null" : proceed.toString()));
44 
45         return proceed;
46     }
47 }

  2. 在spring配置文件中引入aop标签的命名空间及地址(否则aop标签识不了)

   

  3. 在spring配置文件中定义切面(execution表达式请自行脑补)

  <bean id="aspectXmlCheck" class="com.cn.simple.aspect.AspectXmlCheck" />
    <aop:config>
        <aop:aspect id="myAspectCheck" ref="aspectXmlCheck">
            <aop:pointcut id="checkPointCut" expression="execution(* com.cn.simple.service.SimpleService.doSomething(..))"/>
            <aop:before method="beforeCheck" pointcut-ref="checkPointCut"/>
            <aop:after-returning method="afterCheck" pointcut-ref="checkPointCut" arg-names="jp,retVal" returning="retVal"/>
            <aop:around method="aroundCheck" pointcut-ref="checkPointCut"/>
        </aop:aspect>
    </aop:config>

 

AOP配置方式二(注解配置AOP):

  1. 在spring配置文件中引入aop标签的命名空间及地址(否则aop标签识不了)

  2. 在spring配置文件中打开动态代理 

   <!--使用注解配置AOP必须打开如下,否则无效,XML配置AOP则无需-->
    <!-- 通过aop命名空间的<aop:aspectj-autoproxy />声明自动为spring容器中那些配置@aspectJ切面的bean创建代理,织入切面。
    默认为false,表示使用jdk动态代理织入增强,当配为<aop:aspectj-autoproxy  poxy-target-class="true"/>时,表示使用CGLib动态代理技术织入增强-->
    <aop:aspectj-autoproxy />

  3. 编写切面类

/**
 * 通过注解的方式切入
 */
@Component
@Aspect
public class AspectAnnCheck {

    Logger logger = LoggerFactory.getLogger(AspectAnnCheck.class);

    /**
     * 方式一
     * 1. 先定义切入点(方法名随便定义,用于后续定义通知的时候引用)
     * 2. 定义通知(并引用切入点)  Before,After,AfterReturning,AfterThrowing,Around
     */
    /**
     *  先定义切入点(方法名随便定义,用于后续定义通知的时候引用)
     */
    @Pointcut(value = "execution(* com.cn.simple.service.SimpleService.*(..))")
    public void saySomething() {
    }

    /**
     * 前通知
     * 找到切入点,同时满足添加了AopCheckAnn注解的方法进行通知
     * @param jp 目标类连接点对象
     * @param aopCheckAnn 注解对象
     */
    @Before(value = "saySomething() && @annotation(aopCheckAnn)")
    public void saySomethingBefore(JoinPoint jp, AopCheckAnn aopCheckAnn) {
        Object[] args = jp.getArgs();
        String thing = Arrays.toString(args);
        logger.info("1.before say: " + thing + " to " + aopCheckAnn.toWho() + " for " + aopCheckAnn.forWhat());
    }

    /**
     * 后通知
     * 找到切入点,同时满足添加了AopCheckAnn注解的方法进行通知
     * @param jp 目标类连接点对象
     * @param aopCheckAnn 注解对象
     * @param retVal 连接点对象执行后返回的对象
     */
    @AfterReturning(value = "saySomething() && @annotation(aopCheckAnn)", argNames = "jp, aopCheckAnn, retVal", returning = "retVal")
    public void saySomethingAfterReturning(JoinPoint jp, AopCheckAnn aopCheckAnn, Object retVal) {
        logger.info("1.after say: " + (retVal == null ? "none" : retVal.toString()) + " to " + aopCheckAnn.toWho() + " for " + aopCheckAnn.forWhat());
    }

    /**
     * 环绕通知
     * 找到切入点,同时满足添加了AopCheckAnn注解的方法进行通知
     * @param pjp 连接点对象
     * @param aopCheckAnn 注解对象
     * @return 连接点对象执行后返回的对象
     */
    @Around(value = "saySomething() && @annotation(aopCheckAnn)")
    public Object saySomethingAround(ProceedingJoinPoint pjp, AopCheckAnn aopCheckAnn) {
        Object[] args = pjp.getArgs();
        Object proceed = null;
        try {
            proceed = pjp.proceed();
        } catch (Throwable throwable) {
            logger.error("around execute error:", throwable);
        }
        logger.info("1.around say: " + (proceed == null ? "none" : proceed.toString()) + " to " + aopCheckAnn.toWho() + " for " + aopCheckAnn.forWhat());
        return proceed;
    }

    /**
     * 方式二
     * 直接通知并定义切面
     */
    /**
     * 前通知
     * @param jp 目标类连接点对象
     * @param aopCheckAnn 注解对象
     */
    @Before(value = "execution(* com.cn.simple.service.SimpleService.saySomething(..)) && @annotation(aopCheckAnn)")
    public void sayBefore(JoinPoint jp, AopCheckAnn aopCheckAnn) {
        Object[] args = jp.getArgs();
        String thing = Arrays.toString(args);
        logger.info("2.before say: " + thing + " to " + aopCheckAnn.toWho() + " for " + aopCheckAnn.forWhat());
    }

    /**
     * 后通知
     * 找到切入点,同时满足添加了AopCheckAnn注解的方法进行通知
     * @param jp 目标类连接点对象
     * @param aopCheckAnn 注解对象
     * @param retVal 连接点对象执行后返回的对象
     */
    @AfterReturning(value = "execution(* com.cn.simple.service.SimpleService.saySomething(..)) && @annotation(aopCheckAnn)", argNames = "jp, aopCheckAnn, retVal", returning = "retVal")
    public void sayAfterReturning(JoinPoint jp, AopCheckAnn aopCheckAnn, Object retVal) {
        logger.info("2.after say: " + (retVal == null ? "none" : retVal.toString()) + " to " + aopCheckAnn.toWho() + " for " + aopCheckAnn.forWhat());
    }

    /**
     * 环绕通知
     * 找到切入点,同时满足添加了AopCheckAnn注解的方法进行通知
     * @param pjp 连接点对象
     * @param aopCheckAnn 注解对象
     * @return 连接点对象执行后返回的对象
     */
    @Around(value = "execution(* com.cn.simple.service.SimpleService.saySomething(..)) && @annotation(aopCheckAnn)")
    public Object sayAround(ProceedingJoinPoint pjp, AopCheckAnn aopCheckAnn) {
        Object[] args = pjp.getArgs();
        Object proceed = null;
        try {
            proceed = pjp.proceed();
        } catch (Throwable throwable) {
            logger.error("around execute error:", throwable);
        }
        logger.info("2.around say: " + (proceed == null ? "none" : proceed.toString()) + " to " + aopCheckAnn.toWho() + " for " + aopCheckAnn.forWhat());
        return proceed;
    }
}

 

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
public @interface AopCheckAnn {

    String toWho() default "none";

    String forWhat() default "nothing";
}

 

posted on 2017-09-13 15:52  小小'蜗牛  阅读(866)  评论(0编辑  收藏  举报