zoukankan      html  css  js  c++  java
  • [转载]Spring学习4-面向切面(AOP)之aspectj注解方式

    一、简介
      
    1、AOP用在哪些方面:AOP能够将那些与业务无关,却为业务模块所共同调用的逻辑或责任,例如事务处理、日志管理、权限控制,异常处理等,封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。
       2、AOP中的概念:
        Aspect(切面):指横切性关注点的抽象即为切面,它与类相似,只是两者的关注点不一样,类是对物体特征的抽象,而切面是横切性关注点的抽象.

      joinpoint(连接点):所谓连接点是指那些被拦截到的点(可以是方法、属性、或者类的初始化时机(可以是Action层、Service层、dao层))。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点,实际上joinpoint还可以是field或类构造器)

    Pointcut(切入点):所谓切入点是指我们要对那些joinpoint进行拦截的定义,也即
    joinpoint的集合.

    Advice(通知):
    所谓通知是指拦截到joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知

    Target(目标对象):代理的目标对象

    Weave(织入)
    :指将aspects应用到target对象并导致proxy对象创建的过程称为织入.

    Introduction(引入):
    在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field.

       3、AOP带来的好处::降低模块的耦合度;使系统容易扩展;更好的代码复用性


    二、通过注解方式实现Spring的AOP
    Spring AOP环境的环境与上篇博文

    Spring接口方式相同

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

    @Component    //使用自动注解的方式实例化并初始化该类
    public 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 + ":瞄改瞄啊!";
        }

    }

    步骤二、切面类:

     // @Aspect : 标记为切面类
     // @Pointcut : 指定匹配切点集合
     // @Before : 指定前置通知,value中指定切入点匹配
     // @AfterReturning :后置通知,具有可以指定返回值
    // @AfterThrowing :异常通知
     //注意:前置/后置/异常通知的函数都没有返回值,只有环绕通知有返回值
    @Component    //首先初始化切面类
    @Aspect      //声明为切面类,底层使用动态代理实现AOP
    public class AspectAdvice {

        // 指定切入点匹配表达式,注意它是以方法的形式进行声明的。
        //即切点集合是:
    aop.annotation包下所有类所有方法
       //第一个* 代表返回值类型

    //如果要设置多个切点可以使用 || 拼接
      @Pointcut("execution(* aop.annotation.*.*(..))|| execution(* com.action.admin.*.*update*(..))")
        public void anyMethod() {
        }

        //前置通知
       //在切点方法集合执行前,执行前置通知
       @Before("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] + "'进行删除!nn");

            System.out.println("要进入切入点方法了 n");
        }

       // 后置通知
      
     @AfterReturning(value = "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 + "nn");
        }

        // 环绕通知
    (##环绕通知的方法中一定要有ProceedingJoinPoint 参数,
        //
    Filter中的  doFilter方法类似
       
       @Around("execution(* aop.annotation.*.*(..))")
        public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
            System.out.println("===========进入around环绕方法!=========== n");
     HttpSession session = ServletActionContext.getRequest().getSession();
         Emp login =(Emp) session.getAttribute("login")
    ;//ssh2整合后AOP也可以得到request、response、session等
            // 调用目标方法之前执行的动作
            System.out.println("调用方法之前: 执行!n");

            // 调用方法的参数
            Object[] args = pjp.getArgs();
            // 调用的方法名
            String method = pjp.getSignature().getName();
            // 获取目标对象(形如:com.action.admin.LoginAction@1a2467a)
            Object target = pjp.getTarget();
           //获取目标对象的类名(形如:com.action.admin.LoginAction)
          String targetName = pjp.getTarget().getClass().getName();
            // 执行完方法的返回值:调用proceed()方法,就会触发切入点方法执行
            Object result = pjp.proceed();//result的值就是被拦截方法的返回值

            System.out.println("输出:" + args[0] + ";" + method + ";" + target + ";" + result + "n");
            System.out.println("调用方法结束:之后执行!n");
          return result;
        }

        // 异常通知
       
       @AfterThrowing(value = "execution(* aop.annotation.*.*(..))", throwing = "e")
        public void doThrow(JoinPoint jp, Throwable e) {
            System.out.println("删除出错啦");
        }

    }

     步骤三、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: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->

        <context:component-scan base-package="aop.annotation" />
        <!-- 打开aop 注解 -->
        <aop:aspectj-autoproxy proxy-target-class="true"/>


    </beans>

    步骤四、测试类:

    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.2cto.com/kf/201208/149757.html
  • 相关阅读:
    Codeforces 1045C Hyperspace Highways (看题解) 圆方树
    Codeforces 316E3 线段树 + 斐波那切数列 (看题解)
    Codeforces 803G Periodic RMQ Problem 线段树
    Codeforces 420D Cup Trick 平衡树
    Codeforces 295E Yaroslav and Points 线段树
    Codeforces 196E Opening Portals MST (看题解)
    Codeforces 653F Paper task SA
    Codeforces 542A Place Your Ad Here
    python基础 异常与返回
    mongodb 删除
  • 原文地址:https://www.cnblogs.com/liuzhuqing/p/7480404.html
Copyright © 2011-2022 走看看