spring-aop学习

                             SpringAOP学习java

                                           author:luojie正则表达式

  1. 1.  AOP中的基本概念

AOP的通用术语,并不是spring java所特有。很遗憾AOP的术语不是特别的直观。但若是让Spring java来定义本身的专用名词,可能会更加教人糊涂。 

方面(Aspect):对横向分布在多个对象中的关注点所作的模块化。在企业应用中,事务管理就是一个典型的横切关注点。Spring java将方面实现为Advisor或拦截器(interceptor)。(按:Advisor是通知和切入点的组合,拦截器实际就是指通知,注意在本文档中,通常会把环绕通知称为拦截器,而将其它类型的通知称为通知,这是由于环绕通知实现的是AopAlliance.Intercept.IMethodInterceptor接口,而其它通知类型实现的都是Spring.Aop命名空间下的通知接口。) 

链接点(Joinpoint):程序执行过程当中的一个点,例如对某个方法的调用或者某个特定异常的抛出均可以称为链接点。 

通知(Advice):AOP框架在某个链接点所采起的行为。通知有多种类型,包括“环绕”通知,“前置”通知和“异常”通知等,后文将对通知类型进行讨论。包括Spring.NET在内的不少AOP框架都把通知建模为拦截器(interceptor),而且会维护一个"包围"在链接点周围的拦截器链。 

切入点(Pointcut):指通知的应用条件,用于肯定某个通知要被应用到哪些链接点上。AOP框架应容许让开发人员指定切入点,例如,可使用正则表达式来指定一个切入点。 

引入(Introduction):向目标对象添加方法或字段的行为。Spring.NET容许为任何目标对象引入新的接口。例如,能够利用引入让任何对象在运行期实现IAuditable接口,以简化对象状态变化的跟踪过程。(按:也称为mixin,混入) 

目标对象(Target object):指包含链接点的对象。也称为被通知或被代理对象。(按:“被通知对象”实际是“被应用了通知的对象”,在译文中,将advised object或proxied object统称为目标对象,这样更为统一) 

AOP代理(AOP proxy):由AOP框架在将通知应用于目标对象后建立的对象。在Spring.NET中,AOP代理是使用IL代码在运行时建立的动态代理。 

织入(Weaving):将方面进行组装,以建立一个目标对象。织入能够在编译期完成(例如使用Gripper_Loom.NET编译器),也能够在运行时完成。Spring.NET在运行时执行织入。 



各类通知类型包括: 

环绕通知(Around Advise):包围(按:即在链接点执行的前、后执行)某个链接点(如方法调用)的通知。这是功能最强大的一种通知。环绕通知容许在方法调用的先后执行自定义行为。它能够决定是让链接点继续执行,仍是用本身的返回值或异常来将链接点“短路”。 

前置通知(Before Advise):在某个链接点执行以前执行,可是不具有阻止链接点继续执行的能力(除非它抛出异常)。 

异常通知(Throws Advise):当方法(链接点)抛出异常时执行。Spring.NET的异常通知是强类型的(按:Spring.NET用标识接口来定义异常通知,异常通知的处理方法仅需遵循必定的命名规则,能够用具体的异常类型声明其参数,参见12.3.2.3节),因此,能够在代码中直接捕捉某个类型的异常(及其子类异常),没必要从Exception转型。 

后置通知(After returning Advise):在链接点正常执行完成后执行,例如,若是方法正常返回,没有抛出异常时,后置通知就会被执行。 

Spring java内置了以上全部类型的通知。在应用时,应尽可能使用功能最少(只要对要实现的行为来讲是足够的)的通知类型,这样可简化编程模型并减小出错的可能。例如,若是只需使用某个方法的返回值来更新缓存,那么用后置通知就比环绕通知合适。由于,尽管环绕通知能够完成一样的功能,但在后置通知中不用象环绕通知那样必须调用IMethodInvocation接口的Proceed()方法来容许链接点继续执行,因此链接点老是能正常执行。(按:换句话说,由于环绕通知能够控制链接点的继续执行,因此若是没有调用IMethodInvocation接口的Proceed()方法,链接点就会被“短路”;而使用后置通知就不存在这个问题)。 

切入点是AOP的关键概念,使AOP从根本上区别于旧的拦截技术。切入点使通知能够独立于OO的继承层次以外。例如,一个声明式事务处理的环绕通知能够应用于不一样对象的方法。切入点是AOP的结构性要素。spring

 

2.  jarexpress

     Spring框架的包,和aop相关的jar。编程

    

3.  学习例子缓存

如在给controller作切面,记录访问controller时的日志mvc

LogAspect.java框架

//@Component//扫描,等价<bean>模块化

//@Aspect//等价于<aop:aspect ref="">学习

public class LogAspect {

    

     private static Logger log = LoggerFactory.getLogger(getClass());

 

     //@Around("within(org.tedu.cloudnot.controller..*)")

     //等价于<aop:around method="logController" pointcut = "">

     public Object aroundController(ProceedingJoinPoint joinPoint) throws Throwable{

        String targetName = joinPoint.getTarget().getClass().getName();

        String methodName = joinPoint.getSignature().getName();

       

        String description = "";

        Class targetClass = targetClass.getMethods();

        Method[] methods = targetClass.getMethods();

        for(Method method : methods){

            if(method.getName().equals(methodName)){

            Class[] clazzs = method.getParameterTypes();

            for(Class<?> clas : clazzs){

                 String parameterName = clas.getName();

                 description = description = "" + parameterName;

            }

          }

         }

          log.info("enter into Controller---------------------------------");

          log.info("targetName:" + targetName + ";");

          log.info("methodName:" + methodName + ";");

          log.info("parameterTypes:" + description + ";");

          Object[] args = joinPoint.getArgs();

          log.info("parameterValues" + Arrays.toString(args));

          Object object = null;

          try{

               object = joinPoint.proceed();

          }catch(Exception ex){

               log.error("=============================controller方法执行异常==============");

               BaseResult rr = new BaseResult();

               rr.setErrorCode();

               rr.setErrorMsg);

               return rr;

          }

         

          Object[] objs = joinPoint.getArgs();

          log.info("returnResult:" + object);

          return object;

    }

    

     public void afterThrowingController(JoinPoint joinPoint, Throwable e){

         String params = "";

         if(joinPoint.getArgs() != null && joinPoint.getArgs().length > 0){

              for(int i = 0; i<joinPoint.getArgs().length; i++){

               params += joinPoint.getArgs()[i] + ";"; 

              }

         }

         try{

              System.out.println("------异常通知开始-------------");

              System.out.println("异常代码");

              System.out.println("异常信息");

              System.out.println("异常方法" + (joinPoint.getTarget().getClass.getName + "."

              + joinPoint.getSignature().getName()+"()"));

              System.out.println("请求参数"+ params);

         }catch(Exception ex){

              log.error("==异常通知异常=====");

              log.error("异常信息:{}", ex.getMessage());

         }

         /*===========记录本地异常日志============*/

         log.error("异常方法:{}异常代码:{}异常参数:{}参数{}", new Object[]{1,2,3,4});

     }

 

4.  spring.xml配置

<aop:config>

         <aop:pointcut expression="(within(com.me..*)or

         within(coom.me..*))"

         id="controllerPointcut"/>

         <aop:aspect id = "logAspect" ref="loggerBean">

         <aop:arount method="arountController" pointcut-ref="contrllerPointcut"/>

         <aop:after-throwing method="afterThrowingController" pointcut-ref="controllerPointcut" throwing="e"/>

         </aop:aspect>

         </aop:config>

*须要添加aop的schema配置

*可能须要添加aop的自定义扫描注解(这里不须要,已测试,使用注解则须要)

*可能若是aop的切面程序没法起做用,注意多是配置要写在spring-servlet.xml(即springmvc的配置文件中)

<context:component-scan base-package="com.spring.aop" />

<aop:aspectj-autoproxy />

<!-- 通知spring使用cglib而不是jdk的来生成代理方法 AOP能够拦截到Controller -->

<aop:aspectj-autoproxy proxy-target-class="true" />

 

         

4.  SpringAOP的表达式

任意公共方法的执行:  execution(public * *(..))  任何一个以“set”开始的方法的执行:  execution(* set*(..))  AccountService 接口的任意方法的执行:  execution(* com.xyz.service.AccountService.*(..))  定义在service包里的任意方法的执行:  execution(* com.xyz.service.*.*(..))  定义在service包或者子包里的任意方法的执行:  execution(* com.xyz.service..*.*(..))  在service包里的任意链接点(在Spring AOP中只是方法执行) :  within(com.xyz.service.*)  在service包或者子包里的任意链接点(在Spring AOP中只是方法执行) :  within(com.xyz.service..*)  实现了 AccountService 接口的代理对象的任意链接点(在Spring AOP中只是方法执行) :  this(com.xyz.service.AccountService)  'this'在binding form中用的更多:- 请常见如下讨论通知的章节中关于如何使得代理对象能够在通知体内访问到的部分。  实现了 AccountService 接口的目标对象的任意链接点(在Spring AOP中只是方法执行) :  target(com.xyz.service.AccountService)  'target'在binding form中用的更多:- 请常见如下讨论通知的章节中关于如何使得目标对象能够在通知体内访问到的部分。  任何一个只接受一个参数,且在运行时传入的参数实现了 Serializable 接口的链接点 (在Spring AOP中只是方法执行)  args(java.io.Serializable)  'args'在binding form中用的更多:- 请常见如下讨论通知的章节中关于如何使得方法参数能够在通知体内访问到的部分。 请注意在例子中给出的切入点不一样于 execution(* *(java.io.Serializable)): args只有在动态运行时候传入参数是可序列化的(Serializable)才匹配,而execution 在传入参数的签名声明的类型实现了 Serializable 接口时候匹配。  有一个 @Transactional 注解的目标对象中的任意链接点(在Spring AOP中只是方法执行)  @target(org.springframework.transaction.annotation.Transactional)  '@target' 也能够在binding form中使用:请常见如下讨论通知的章节中关于如何使得annotation对象能够在通知体内访问到的部分。  任何一个目标对象声明的类型有一个 @Transactional 注解的链接点(在Spring AOP中只是方法执行)  @within(org.springframework.transaction.annotation.Transactional)  '@within'也能够在binding form中使用:- 请常见如下讨论通知的章节中关于如何使得annotation对象能够在通知体内访问到的部分。  任何一个执行的方法有一个 @Transactional annotation的链接点(在Spring AOP中只是方法执行)  @annotation(org.springframework.transaction.annotation.Transactional)  '@annotation' 也能够在binding form中使用:- 请常见如下讨论通知的章节中关于如何使得annotation对象能够在通知体内访问到的部分。  任何一个接受一个参数,而且传入的参数在运行时的类型实现了 @Classified annotation的链接点(在Spring AOP中只是方法执行)  @args(com.xyz.security.Classified)

相关文章
相关标签/搜索