首页 > 代码库 > Spring AOP (下)

Spring AOP (下)

 昨天记录了Spring AOP学习的一部分(http://www.cnblogs.com/yanbincn/archive/2012/08/13/2635413.html),本来是想一口气梳理完的。但是大晚上时间不够(无奈一场奥运篮球总决赛耗费掉了2小时,不过的确相当精彩),又考虑到篇幅太长,阅读性比较差,所以将后半部分更偏于应用的重起一篇随笔。

  利用方式一的配置起来,可见代码还是非常的厚重的,定义一个切面就要定义一个切面类,然而切面类中,就一个通知方法,着实没有必要。所以Spring提供了,依赖aspectj的schema配置和基于aspectj 注解方式。这两种方式非常简介方便使用,也是项目中普遍的使用方式。梳理之:

4、方式二:schema配置

a、业务类:

技术分享
/** * 业务类 *  * @author yanbin *  */public class AspectBusiness {    /**     * 切入点     */    public String delete(String obj) {        System.out.println("==========调用切入点:" + obj + "说:你敢删除我!===========\n");        return obj + ":瞄~";    }    public String add(String obj) {        System.out.println("================这个方法不能被切。。。============== \n");        return obj + ":瞄~ 嘿嘿!";    }    public String modify(String obj) {        System.out.println("=================这个也设置加入切吧====================\n");        return obj + ":瞄改瞄啊!";    }}

b、切面类:切面类中,包含了所有的通知

技术分享
/** * 定义一个切面 *  * @author yanbin *  */public class AspectAdvice {    /**     * 前置通知     *      * @param jp     */    public void doBefore(JoinPoint jp) {        System.out.println("===========进入before advice============ \n");        System.out.print("准备在" + jp.getTarget().getClass() + "对象上用");        System.out.print(jp.getSignature().getName() + "方法进行对 ‘");        System.out.print(jp.getArgs()[0] + "‘进行删除!\n\n");        System.out.println("要进入切入点方法了 \n");    }    /**     * 后置通知     *      * @param jp     *            连接点     * @param result     *            返回值     */    public void doAfter(JoinPoint jp, String result) {        System.out.println("==========进入after advice=========== \n");        System.out.println("切入点方法执行完了 \n");        System.out.print(jp.getArgs()[0] + "在");        System.out.print(jp.getTarget().getClass() + "对象上被");        System.out.print(jp.getSignature().getName() + "方法删除了");        System.out.print("只留下:" + result + "\n\n");    }    /**     * 环绕通知     *      * @param pjp     *            连接点     */    public void doAround(ProceedingJoinPoint pjp) throws Throwable {        System.out.println("===========进入around环绕方法!=========== \n");        // 调用目标方法之前执行的动作        System.out.println("调用方法之前: 执行!\n");        // 调用方法的参数        Object[] args = pjp.getArgs();        // 调用的方法名        String method = pjp.getSignature().getName();        // 获取目标对象        Object target = pjp.getTarget();        // 执行完方法的返回值:调用proceed()方法,就会触发切入点方法执行        Object result = pjp.proceed();        System.out.println("输出:" + args[0] + ";" + method + ";" + target + ";" + result + "\n");        System.out.println("调用方法结束:之后执行!\n");    }    /**     * 异常通知     *      * @param jp     * @param e     */    public void doThrow(JoinPoint jp, Throwable e) {        System.out.println("删除出错啦");    }}

c、配置文件:

技术分享
<?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:p="http://www.springframework.org/schema/p"    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-3.0.xsd               http://www.springframework.org/schema/context               http://www.springframework.org/schema/context/spring-context-3.0.xsd           http://www.springframework.org/schema/aop               http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"    default-autowire="byName">    <!-- ==============================利用spring 利用aspectj来配置AOP================================ -->    <!-- 声明一个业务类 -->    <bean id="aspectBusiness" class="aop.schema.AspectBusiness" />    <!-- 声明通知类 -->    <bean id="aspectAdvice" class="aop.schema.advice.AspectAdvice" />    <aop:config>        <aop:aspect id="businessAspect" ref="aspectAdvice">            <!-- 配置指定切入的对象 -->            <aop:pointcut id="point_cut" expression="execution(* aop.schema.*.*(..))" />            <!-- 只匹配add方法作为切入点            <aop:pointcut id="except_add" expression="execution(* aop.schema.*.add(..))" />             -->            <!-- 前置通知 -->            <aop:before method="doBefore" pointcut-ref="point_cut" />            <!-- 后置通知 returning指定返回参数 -->            <aop:after-returning method="doAfter"                pointcut-ref="point_cut" returning="result" />            <aop:around method="doAround" pointcut-ref="point_cut"/>            <aop:after-throwing method="doThrow" pointcut-ref="point_cut" throwing="e"/>        </aop:aspect>    </aop:config></beans>

d、测试类:

技术分享
public class Debug {    public static void main(String[] args) {        ApplicationContext context = new ClassPathXmlApplicationContext("aop/schema_aop.xml");        AspectBusiness business = (AspectBusiness) context.getBean("aspectBusiness");        business.delete("猫");    }}

5、方式三:aspectj注解

注解在项目中已经到处都是了,撇开一些优劣不提,开发的便利性和可读性是非常的方便的。用来配置Spring AOP也非常简单便利

a、业务类:

技术分享
/** * 业务类 *  * @author yanbin *  */@Componentpublic class Business {    /**     * 切入点     */    public String delete(String obj) {        System.out.println("==========调用切入点:" + obj + "说:你敢删除我!===========\n");        return obj + ":瞄~";    }    public String add(String obj) {        System.out.println("================这个方法不能被切。。。============== \n");        return obj + ":瞄~ 嘿嘿!";    }    public String modify(String obj) {        System.out.println("=================这个也设置加入切吧====================\n");        return obj + ":瞄改瞄啊!";    }}

b、切面类:

技术分享
/** * 定义切面 *  * @Aspect : 标记为切面类 * @Pointcut : 指定匹配切点 * @Before : 指定前置通知,value中指定切入点匹配 * @AfterReturning :后置通知,具有可以指定返回值 * @AfterThrowing :异常通知 *  * @author yanbin *  */@Component@Aspectpublic class AspectAdvice {    /**     * 指定切入点匹配表达式,注意它是以方法的形式进行声明的。     */    @Pointcut("execution(* aop.annotation.*.*(..))")    public void anyMethod() {    }    /**     * 前置通知     *      * @param jp     */    @Before(value = "http://www.mamicode.com/execution(* aop.annotation.*.*(..))")    public void doBefore(JoinPoint jp) {        System.out.println("===========进入before advice============ \n");        System.out.print("准备在" + jp.getTarget().getClass() + "对象上用");        System.out.print(jp.getSignature().getName() + "方法进行对 ‘");        System.out.print(jp.getArgs()[0] + "‘进行删除!\n\n");        System.out.println("要进入切入点方法了 \n");    }    /**     * 后置通知     *      * @param jp     *            连接点     * @param result     *            返回值     */    @AfterReturning(value = "http://www.mamicode.com/anyMethod()", returning = "result")    public void doAfter(JoinPoint jp, String result) {        System.out.println("==========进入after advice=========== \n");        System.out.println("切入点方法执行完了 \n");        System.out.print(jp.getArgs()[0] + "在");        System.out.print(jp.getTarget().getClass() + "对象上被");        System.out.print(jp.getSignature().getName() + "方法删除了");        System.out.print("只留下:" + result + "\n\n");    }    /**     * 环绕通知     *      * @param pjp     *            连接点     */    @Around(value = "http://www.mamicode.com/execution(* aop.annotation.*.*(..))")    public void doAround(ProceedingJoinPoint pjp) throws Throwable {        System.out.println("===========进入around环绕方法!=========== \n");        // 调用目标方法之前执行的动作        System.out.println("调用方法之前: 执行!\n");        // 调用方法的参数        Object[] args = pjp.getArgs();        // 调用的方法名        String method = pjp.getSignature().getName();        // 获取目标对象        Object target = pjp.getTarget();        // 执行完方法的返回值:调用proceed()方法,就会触发切入点方法执行        Object result = pjp.proceed();        System.out.println("输出:" + args[0] + ";" + method + ";" + target + ";" + result + "\n");        System.out.println("调用方法结束:之后执行!\n");    }    /**     * 异常通知     *      * @param jp     * @param e     */    @AfterThrowing(value = "http://www.mamicode.com/execution(* aop.annotation.*.*(..))", throwing = "e")    public void doThrow(JoinPoint jp, Throwable e) {        System.out.println("删除出错啦");    }}

c、配置:

技术分享
<?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:p="http://www.springframework.org/schema/p"    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-3.0.xsd               http://www.springframework.org/schema/context               http://www.springframework.org/schema/context/spring-context-3.0.xsd           http://www.springframework.org/schema/aop               http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"    default-autowire="byName">    <context:component-scan base-package="aop.annotation" />    <!-- 打开aop 注解 -->    <aop:aspectj-autoproxy /></beans>

d、测试类:

技术分享
/** * 测试类 *  * @author yanbin *  */public class Debug {    public static void main(String[] args) {        ApplicationContext context = new ClassPathXmlApplicationContext("aop/annotation_aop.xml");        Business business = (Business) context.getBean("business");        business.delete("猫");    }}
 
转自:http://www.cnblogs.com/yanbincn/archive/2012/08/13/2636961.html

Spring AOP (下)