Spring 动态切入点讲解

    技术2022-05-20  71

    如果我们需要根据方法的参数不同而决定事都进行切入,而不是不管方法是什么参数全部切入的话,我们就需要使用动态切入点,在每次方法调用时候都进行检查(确切的说是参数检查),;来决定是否执行通知

    BeanOne.java

    package  DynamicPointCutAdvisor; public   class  BeanOne  {     public   void  foo() {        System.out.println( " foo-one " );    }     public   void  bar() {        System.out.println( " bar-one " );    }     public   void  dynamic( int  x) {        System.out.println(x);    } }

     动态切入点:

    package  DynamicPointCutAdvisor; import  java.lang.reflect.Method; import  org.springframework.aop.ClassFilter; import  org.springframework.aop.support.DynamicMethodMatcherPointcut; public   class  SimpleDynamicPointcut  extends  DynamicMethodMatcherPointcut  {           // 静态方法检查,为避免每次调用bar方法是都进行一次检测,导致效率降低      public   boolean  matches(Method method, Class cls)  {          return   " dynamic " .equals(method.getName());     }      // 当参数不为100时候,进行切入      public   boolean  matches(Method method, Class cls, Object[] obj)  {          int  x = ((Integer)obj[ 0 ]).intValue();          return  (x != 100 );     }      public  ClassFilter getClassFilter() {          return   new  ClassFilter() {              public   boolean  matches(Class cls) {                  return  cls == BeanOne. class ;             }         } ;     } }

    环绕通知:

    package  DynamicPointCutAdvisor; import  org.aopalliance.intercept.MethodInterceptor; import  org.aopalliance.intercept.MethodInvocation; public   class  SimpleAdvise  implements  MethodInterceptor  {      public  Object invoke(MethodInvocation invocation)  throws  Throwable  {         System.out.println( " before " );         Object retVal = invocation.proceed();         System.out.println( " after " );          return  retVal;     } }

    测试代码:

    package  DynamicPointCutAdvisor; import  org.aopalliance.aop.Advice; import  org.springframework.aop.Advisor; import  org.springframework.aop.Pointcut; import  org.springframework.aop.framework.ProxyFactory; import  org.springframework.aop.support.DefaultPointcutAdvisor; public   class  Test  {      /**      *  @param  args       */      public   static   void  main(String[] args)  {          BeanOne one = new  BeanOne();                   BeanOne proxyOne;                         Pointcut pc = new  SimpleDynamicPointcut();          Advice advice = new  SimpleAdvise();          Advisor advisor = new  DefaultPointcutAdvisor(pc,advice);                               // 创建BeanOne代理          ProxyFactory pf1 = new  ProxyFactory();          pf1.addAdvisor(advisor);          pf1.setTarget(one);          proxyOne = (BeanOne)pf1.getProxy();                                              proxyOne.dynamic( 100 );          System.out.println( " ------------------- " );          proxyOne.dynamic( 101 );          System.out.println( " ------------------- " );          proxyOne.bar();     } }

    运行结果:

    100 ------------------- before 101 after ------------------- bar-one

    后记

    如果我们在切入点类中的方法检查代码中加入提示,如:

    package  DynamicPointCutAdvisor; import  java.lang.reflect.Method; import  org.springframework.aop.ClassFilter; import  org.springframework.aop.support.DynamicMethodMatcherPointcut; public   class  SimpleDynamicPointcut  extends  DynamicMethodMatcherPointcut  {           // 静态方法检查,为避免每次调用bar方法是都进行一次检测,导致效率降低      public   boolean  matches(Method method, Class cls)  {         System.out.println( " static check for  " + method.getName());          return   " dynamic " .equals(method.getName());     }      // 当参数不为100时候,进行切入      public   boolean  matches(Method method, Class cls, Object[] obj)  {         System.out.println( " dynamic check for  " + method.getName());          int  x = ((Integer)obj[ 0 ]).intValue();          return  (x != 100 );     }      public  ClassFilter getClassFilter() {          return   new  ClassFilter() {              public   boolean  matches(Class cls) {                  return  cls == BeanOne. class ;             }         } ;     } }

    可以看到结果如下:

    static check for dynamic static check for bar static check for foo static check for clone static check for toString static check for dynamic dynamic check for dynamic 100 ------------------- dynamic check for dynamic before 101 after ------------------- static check for bar bar-one

    可以看到,红色部分代表静态方法类型检查,绿色代表动态方法类型检查

    当我们实现了静态检查|(public boolean matches(Method method, Class cls) )时候,动态类型对不匹配的方法,如本例中的bar不再进行动态检查,提高了效率,如果没有public boolean matches(Method method, Class cls) 方法,则所有方法势必都会进行类型检查,不仅降低效率,还有可能因为方法参数的不同导致异常(如bar是没有参数的,使用动态检查中的 int x=((Integer)obj[0]).intValue();就会出现异常)


    最新回复(0)