zoukankan      html  css  js  c++  java
  • 手把手教你学会用Spring AOP

            用了Spring很长时间了,一直想写些AOP的东西,但一直没有空闲,直到现在项目稍微进入正轨了,才赶紧写写。废话不多说,先从AOP入门开始,后面再介绍AOP的原理(JDK动态代码和CGLIB动态代码的知识)。注:该部分适合于未接触过Spring AOP的童鞋,如果是AOP老手,请直接绕过,不用打招呼^^

           请尊重作者劳动成果,转载请标明原文链接:

           https://www.cnblogs.com/jpcflyer/p/9339104.html

    一、环境准备

           1.在Spring官网(地址见本文最后)下载springframework相关jar包,下载完后的jar包里面会包含aop/aspects/context/beans/core等相关的jar。

           2.在AspectJ官网(AOP依赖包,地址见本文最后)下载AspectJ.jar,目前最新稳定版是1.9.1。

           3.在Eclipse中,新建java project,然后在根目录下新建lib目录,并将第1步中下载的jar包全部copy到lib目录下。

           4.将第2步下载的AspectJ.jar解压,并将解压后的aspectjrt.jar、aspectjweaver.jar两个jar包copy到lib目录下。

           5.项目右键-build path-libraries-add jars,然后选择lib中的全部jar包,点击确定。

           6.在项目根目录下新建配置文件applicationContext.xml,文件内容暂时为空,到此环境准备完毕。

    二、代码示例

           了解AOP的童鞋都知道,使用AOP的方式有多少,这里建议使用配置文件的方式,能够减少对代码的注入,比较简洁。

           1.新建切面类

    package test;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    
    public class AspectAdvice {
    
         /**
         * 前置通知
         * 
         * @param jp
         */
        public void doBefore(JoinPoint jp) {
            System.out.println("===========进入before advice============ 
    ");
    
            System.out.print("准备在" + jp.getTarget().getClass() + "对象上用");
            System.out.print(jp.getSignature().getName() + "方法进行对 '");
            System.out.print(jp.getArgs()[0] + "'进行删除!
    
    ");
    
            System.out.println("要进入切入点方法了 
    ");
        }
    
        /**
         * 后置通知
         * 
         * @param jp
         *            连接点
         * @param result
         *            返回值
         */
        public void doAfter(JoinPoint jp, String result) {
            System.out.println("==========进入after advice=========== 
    ");
            System.out.println("切入点方法执行完了 
    ");
    
            System.out.print(jp.getArgs()[0] + "在");
            System.out.print(jp.getTarget().getClass() + "对象上被");
            System.out.print(jp.getSignature().getName() + "方法删除了");
            System.out.print("只留下:" + result + "
    
    ");
        }
    
        /**
         * 环绕通知
         * 
         * @param pjp
         *            连接点
         */
        public void doAround(ProceedingJoinPoint pjp) throws Throwable {
            System.out.println("===========进入around环绕方法!=========== 
    ");
    
            // 调用目标方法之前执行的动作
            System.out.println("调用方法之前: 执行!
    ");
    
            // 调用方法的参数
            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 + "
    ");
            System.out.println("调用方法结束:之后执行!
    ");
        }
    
        /**
         * 异常通知
         * 
         * @param jp
         * @param e
         */
        public void doThrow(JoinPoint jp, Throwable e) {
            System.out.println("删除出错啦");
        }
    
    
    }
    View Code

           2.新建业务类

    package test;
    
    public class AspectBusiness {
    
        public String delete(String obj) {
            System.out.println("==========调用切入点:" + obj + "说:你敢删除我!===========
    ");
            return obj + ":瞄~";
        }
    
        public String add(String obj) {
            System.out.println("================这个方法不能被切。。。============== 
    ");
            return obj + ":瞄~ 嘿嘿!";
        }
    
        public String modify(String obj) {
            System.out.println("=================这个也设置加入切吧====================
    ");
            return obj + ":瞄改瞄啊!";
        }
    
    
    }
    View Code

           3.在applicationContext.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"
           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.xsd"
          >
    
    <!-- bean definitions here -->
    
    
    
        <!-- 声明一个业务类 -->
        <bean id="aspectBusiness" class="test.AspectBusiness" />
    
        <!-- 声明通知类 -->
        <bean id="aspectAdvice" class="test.AspectAdvice" />
    
        <aop:config>
            <aop:aspect id="businessAspect" ref="aspectAdvice">
                <!-- 配置指定切入的对象 -->
                <aop:pointcut id="point_cut" expression="execution(* test.*.*(..))" />
                <!-- 只匹配add方法作为切入点
                <aop:pointcut id="except_add" expression="execution(* test.*.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>
    View Code

           4.新建测试类

    package test;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.LinkedList;
    import java.util.List;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class StringTest {
    
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            AspectBusiness business = (AspectBusiness) context.getBean("aspectBusiness");
            business.delete("猫");
        }
    }
    View Code

    三、运行结果

           运行结果如下所示:

    ===========进入before advice============ 
    
    准备在class test.AspectBusiness对象上用delete方法进行对 '猫'进行删除!
    
    要进入切入点方法了 
    
    ===========进入around环绕方法!=========== 
    
    调用方法之前: 执行!
    
    ==========调用切入点:猫说:你敢删除我!===========
    
    输出:猫;delete;test.AspectBusiness@3b69e7d1;猫:瞄~
    
    调用方法结束:之后执行!
    
    ==========进入after advice=========== 
    
    切入点方法执行完了 
    
    猫在class test.AspectBusiness对象上被delete方法删除了只留下:null

           这样AOP的示例就算完成了,本篇先不介绍切面、通知、切入点等的相关概念了,这些概念在百度上可谓信手拈来,如果有不了解,可以自行百度。本篇先写到这里,后续再介绍AOP的相关原理。

           参考资料:

           1. Spring官网:https://spring.io/

           2. Spring5.0官网下载地址:https://repo.spring.io/webapp/#/artifacts/browse/tree/General/libs-release-local/org/springframework/spring/5.0.0.RELEASE

           3. AspectJ最新稳定版官网下载地址:http://www.eclipse.org/aspectj/downloads.php#stable_release

     

  • 相关阅读:
    Android应用之个人应用软件开发(2)【签到功能和记账】
    抽象类判断日期能否被2整除
    Android应用之个人应用软件开发(3)【SQLite数据库及理财功能实现】
    移动终端网页游戏移植研发框架【服务器及客户端交互处理】
    DirectX学习资料
    列宁的故事
    Managed DirectX +C# 开发(入门篇)(七)
    Managed DirectX +C# 开发(入门篇)(六)
    Managed DirectX +C# 开发(入门篇)(三)
    C#不同窗口类中的变量相互调用
  • 原文地址:https://www.cnblogs.com/jpcflyer/p/9339104.html
Copyright © 2011-2022 走看看