zoukankan      html  css  js  c++  java
  • Spring AOP With AspectJ

    一.AOP和拦截器

       某些情况下,AOP和拦截器包括Filter能够实现同样的功能,一般都是请求即controller层的操作,这三个执行顺序为Filter>Interceptor>AOP,当然这里面的区别我会重新写一篇文章讲解,这里面提一下就是想告诉大家,不一定要使用AOP,个人感觉用Filter和Interceptor实现的更方便简单一点。

    二.AOP 准备

        在spring框架下,你还需要添加aspectjrt,aspectjweaver和cglib 的相关jar包,maven项目的pom.xml中可直接在maven公服获取配置。

        在spring-mvc.xml中配置aop,并添加<aop:aspectj-autoproxy /> 。

        对于aspect类,对类添加@Aspect和@Component即可。

    三.Spring AOP简

        AOP这个概念看文档比较抽象,网上的举例子也基本上是操作日志这些,不过日志记录的确是一个非常形象的例子。说白了,当我们想对一些批量的方法进行一些补充操作,在service层和dao层,我们一般选择AOP。

        日志的例子,当我们dao层我们执行crud的时候同时想在数据库中生成一条日志记录,这时候日志的处理代码其实是一样的,我们可以提取出来。

        再比如,某些操作需要发短息通知用户(更改密码,账单到期等等),发短信的代码其实是一样的,就是一个手机号和短信内容。这时候我们用AOP就能解决,所有需要发短信的方法都可以用AOP来解决。好处是:只需要 一个地方维护代码,动态的决定哪些地方给用户发短信。

        一般用AOP的时候我们都是配合一些注解来完成的,注解的主要作用有两个方面:1.可以用来判断是否拦截该方法,2.传递一些aop方法中需要的参数或者变量值。

    Glossory  of AOP:

        1.Pointcut: aop拦截的是哪些方法,必须要告诉aop方法,一般我们都是通过类似正则的表示,pointcut有不同的几种类型,通常我们见到的应该就是execution,其实目前我用的也就是execution,其他类型比如:within,this,args,target,@args,@target,@annotation...

          下面是pointcut的几个例子: pointcut的表达式可以通过'||','&&'和'!'连接

          @Pointcut("execution(pubic * *(..))")

          private void allOperation() {}

          @Pointcut("within(com.cnblog.service.User..") =>@Pointcut("execution(* com.cnblog.service.User.*(..))")

          private void userOperation() {}

          @Pointcut("allOperation() && userOperation() ")

          private void unionOperation() {}

    2.Advice: Advice is associated with a pointcut expression, and runs before, after, or around method executions matched by the pointcut. The pointcut expression may be either a simple reference to a named pointcut, or a pointcut expression declared in place.

    我们通常最简洁的用法就是@Around("execution(public *.update*(..))"),其实它等同于@Around(pointcut="execution(public *.update*(..))"),pointcut的值可以为上面我们定义的pointcut表达式的函数。下面主要介绍四种advice:

        Before:在拦截函数执行之前执行,一般数据权限或者用户验证的信息都是这样,类似Interceptor的prehandle。

         @Before("execution(public * * (..))")

          public void doCheck() {...}

        Around:around 是最通常用的,,因为可以before和after都融合,而且可以决定被拦截的方法什么时候执行,advice method的第一个参数必须是ProceedingJoinPoint.通过调用ProceedingJoinPoint的proceed方法就可以执行被拦截的函数。

          @Around("execution(public * * (..))")

          public Object doAround(ProceedingJoinPoint pjp ,..) {

              Object[] args = pjp.getArgs();

              ...

              return pjp.proceed(args);

          }

        After:在函数执行完之后执行,执行完包含被拦截函数返回值或者出现异常,一般情况我们是针对出现异常做一个记录等。

          @After("execution(public * * (..))")

          public void doFinal() {...}

       注:advice ordering:如果多个advices在同一个连接点执行,这时候就有一个执行顺序,一般情况下我们可以尽量避免,如果无法避免可以通过@Order(org.springframework.core.annotation.Order)来表示先后顺序。优先级越高,在"on  the way in"先执行,"on the way out"后执行.

    4.Other keys: Introductions,perthis,PessimisticLockingFailureException(详情参照spring官方文档)

    四.AOP的选择

        Spring AOP or AspectJ      ,Aspect language style ,@AspectJ or Spring xml style(aspect schema_based 这里面就不讲了,就是aop的xml配置)。

        1.Spring AOP  or full AspectJ

           spring aop 更简单,因为aspectj还需要引入compiler/weaver相关的jar 包。

           如果你的aop切入的是spring beans,可以直接使用spring  aop就可以了,如果你想拦截的对象不是spring容器管理的只能使用AspectJ,个人一直使用Aspectj,因                   为比较方便,如果用maven的话 就更简单了。

       2.个人建议直接使用@Aspect语法风格,使用spring xml配置很繁琐,而且容易遗漏。

    五.AOP代理

      spring AOP使用JDK动态代理或者cglib来创建目标对象的代理,JDK动态代理会优先选择。

      默认情况下:如果被代理的目标对象至少实现了一个接口,那么这时候默认使用JDK动态代理,反之,则使用cglib。

      当然,你也可以强制使用cglib,如果你很偏爱它,不过在spring3.x你首先得提供cglib的相关jar包。然后需要在spring 中配置<aop:config proxy-target-class="true" />,to force CGLIB proxying when using @AspectJ autoproxy support ==> <aop:aspectj-autoproxy proxy-target-class="true" />

      理解AOP代理:

        一般object 调用:interface pojo  ,class SimplePojo implements pojo

    public classMain {
        public  static voidmain(String[] args) {
          Pojo pojo = new SimplePojo();
        // this is a direct method call on the 'pojo' reference
        pojo.foo();
      }
    }    
    

       我们稍微改变一下,当客户端只有一个代理的时候 ,如图: 

     

    public classMain {
        public static voidmain(String[] args) {
            ProxyFactory factory = newProxyFactory(newSimplePojo());
            factory.addInterface(Pojo.class);
            factory.addAdvice(newRetryAdvice());
            Pojo pojo = (Pojo) factory.getProxy();
            // this is a method call on the proxy!
            pojo.foo();
        }
    }            
    

      

  • 相关阅读:
    Restful levels &HATEOAS基本介绍~
    跨源资源共享(CORS)概念、实现(用Spring)、起源介绍
    Ubuntu下math库函数编译时未定义问题的解决
    常用软件清单~
    JetBrains PyCharm 专业版激活
    hello1.java内容简单介绍
    hello1 web项目中web.xml作用分析
    hello2 source analisis(notes)
    Servlet filter
    分析helo1项目中的 Web.xml
  • 原文地址:https://www.cnblogs.com/wangkeustc/p/4718154.html
Copyright © 2011-2022 走看看