Spring AOP Advice

Advice

前置额外功能

public class MyBeforeAdvice implements MethodBeforeAdvice{

   /**
    * @param method 当前执行的方法
    * @param args   当前执行的方法中的参数
    * @param target 目标对象
    * @throws Throwable
    */
   @Override
   public void before(Method method, Object[] args, Object target) throws Throwable {
       System.out.println("before~~~");
   }
}

后置额外功能

public class MyAfterAdvice implements AfterReturningAdvice{

   /**
    * @param returnValue  目标业务方法返回值
    * @param method       当前执行的业务方法对象
    * @param args         方法的参数
    * @param target       目标对象
    * @throws Throwable
    */
   @Override
   public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
       System.out.println("after~~~");
   }
}

环绕额外功能

public class MyMethodInterceptor implements MethodInterceptor{

   @Override
   public Object invoke(MethodInvocation invocation) throws Throwable {
       System.out.println("begin~~");
       Object ret = invocation.proceed();//执行目标业务方法
       System.out.println("end~~");
       return ret;//返回目标业务方法返回值
   }
}

异常额外功能(了解)

public class MyThrows implements ThrowsAdvice{
   //目标业务方法中抛出异常时,执行此方法。ex=抛出的异常对象
   public void afterThrowing(Exception ex){
       System.out.println(ex.getMessage()+"~~~");
   }
}

最终额外功能(了解)

  • 在核心之后执行( 即使核心中出现了异常,依然执行额外 )

编织

<!-- 声明 target+advice -->
<bean id="userService" class="xxxxx"></bean>
<bean id="myXXAdvice" class="xxxxx"></bean>
<aop:config>
   <aop:pointcut id="pc" expression="execution(* com..UserService*.*(..))"/>
   <aop:advisor advice-ref="advice的BeanId" pointcut-ref="pc"/>
</aop:config>

切入点表达式

execution

  • com.service.UserServiceImpl.queryUser(..)
    • 修饰符:任意
    • 返回值:任意
    • 包:com.service
    • 类:UserServiceImpl
    • 方法:queryUser
    • 参数表:任意
  • com.service.UserServiceImpl.*(..)
    • 修饰符:任意
    • 返回值:任意
    • 包:com.service
    • 类:UserServiceImpl
    • 方法:所有,任意
    • 参数表:任意
  • com..UserServiceImpl.*(..)
    • 修饰符:任意
    • 返回值:任意
    • 包:com包,及其子包
    • 类:UserServiceImpl
    • 方法:所有,任意
    • 参数表:任意
  • com.service..(..)
    • 修饰符:任意
    • 返回值:任意
    • 包:com.service
    • 类:所有,任意
    • 方法:所有,任意
    • 参数表:任意
  • *(..) 不建议
    • 修饰符:任意
    • 返回值:任意
    • 包:任意
    • 类:所有,任意
    • 方法:所有,任意
    • 参数表:任意
  • com.service.UserServiceImpl.query*(..) 【技巧:批量切入】
    • 修饰符:任意
    • 返回值:任意
    • 包:com.service
    • 类:UserServiceImpl
    • 方法:所有,任意
    • 参数表:任意
  • 注意:尽量精确,避免不必要的切入

within

  • 描述中所有方法都切入
  • within(com.service.UserServiceImpl) 类中的所有方法
  • within(com..UserServiceImpl) com包和com子包下的类中的所有方法
<aop:pointcut id="pc" expression="within(com..UserServiceImpl)"/>

args

  • 描述参数表,符合的方法都切入
  • args(int,String,com.entity.User) 参数表如此的方法
<aop:pointcut id="pc" expression="args(int,String,com.entity.User)"/>

联用

  • 不同种类的表达式之间,可以使用逻辑运算:
    • and or not
<aop:pointcut id="pc" expression="execution(* com.xxx.service.UserServiceImpl.*(..)) and args(com.User)"/>
<aop:pointcut id="pc" expression="within(com.service.UserServiceImpl) or args(com.User)"/>
<aop:pointcut id="pc" expression="within(com.service.UserServiceImpl) and not args(com.User)"/>

使用注解增强

@AspectJ

@Aspect // AspectJ的注解
@Component
public class MyAdvice {
   private final String pc = "execution(* com.xxx.service.UserServiceImpl.*(..))";
   @Before(pc) // AspectJ的注解
   public void beforeXxx(JoinPoint a) {
       System.out.println("target:"+a.getTarget());
       System.out.println("args:"+a.getArgs());
       System.out.println("method's name:"+a.getSignature().getName());
       System.out.println("before~~~~");
   }

   @AfterReturning(value=pc,returning="ret9") // AspectJ的注解
   public void myAfterReturning(JoinPoint a,Object ret9){
       System.out.println("after~~~~:"+ret9);
   }
   @Around(pc) // AspectJ的注解
   public Object myInterceptor(ProceedingJoinPoint p) throws Throwable {
       System.out.println("interceptor1~~~~");
       Object ret = p.proceed();
       System.out.println("interceptor2~~~~");
       return ret;
   }
   @AfterThrowing(value=pc,throwing="ex") // AspectJ的注解
   public void myThrows(JoinPoint jp,Exception ex){
       System.out.println("throws");
       System.out.println("===="+ex.getMessage());
   }
}

添加配置

<!-- 添加如下配置 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<context:component-scan base-package="com.xxx"/>


转载请注明:Memory的博客 » 点击阅读原文

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦