Spring 动态切入点讲解

时间:2022-09-26 09:47:41

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

BeanOne.java

Spring 动态切入点讲解package  DynamicPointCutAdvisor;
Spring 动态切入点讲解
Spring 动态切入点讲解Spring 动态切入点讲解
public   class  BeanOne  ... {
Spring 动态切入点讲解Spring 动态切入点讲解    
public   void  foo() ... {
Spring 动态切入点讲解        System.out.println(
" foo-one " );
Spring 动态切入点讲解    }

Spring 动态切入点讲解Spring 动态切入点讲解    
public   void  bar() ... {
Spring 动态切入点讲解        System.out.println(
" bar-one " );
Spring 动态切入点讲解    }

Spring 动态切入点讲解Spring 动态切入点讲解    
public   void  dynamic( int  x) ... {
Spring 动态切入点讲解        System.out.println(x);
Spring 动态切入点讲解    }

Spring 动态切入点讲解 }

Spring 动态切入点讲解

 动态切入点:

Spring 动态切入点讲解package  DynamicPointCutAdvisor;
Spring 动态切入点讲解
Spring 动态切入点讲解
import  java.lang.reflect.Method;
Spring 动态切入点讲解
Spring 动态切入点讲解
import  org.springframework.aop.ClassFilter;
Spring 动态切入点讲解
import  org.springframework.aop.support.DynamicMethodMatcherPointcut;
Spring 动态切入点讲解
Spring 动态切入点讲解Spring 动态切入点讲解
public   class  SimpleDynamicPointcut  extends  DynamicMethodMatcherPointcut  ... {
Spring 动态切入点讲解
Spring 动态切入点讲解     
Spring 动态切入点讲解     
// 静态方法检查,为避免每次调用bar方法是都进行一次检测,导致效率降低
Spring 动态切入点讲解Spring 动态切入点讲解
     public   boolean  matches(Method method, Class cls)  ... {
Spring 动态切入点讲解         
return   " dynamic " .equals(method.getName());
Spring 动态切入点讲解     }

Spring 动态切入点讲解     
// 当参数不为100时候,进行切入
Spring 动态切入点讲解Spring 动态切入点讲解
     public   boolean  matches(Method method, Class cls, Object[] obj)  ... {
Spring 动态切入点讲解         
int  x = ((Integer)obj[ 0 ]).intValue();
Spring 动态切入点讲解         
return  (x != 100 );
Spring 动态切入点讲解     }

Spring 动态切入点讲解Spring 动态切入点讲解     
public  ClassFilter getClassFilter() ... {
Spring 动态切入点讲解Spring 动态切入点讲解         
return   new  ClassFilter() ... {
Spring 动态切入点讲解Spring 动态切入点讲解             
public   boolean  matches(Class cls) ... {
Spring 动态切入点讲解                 
return  cls == BeanOne. class ;
Spring 动态切入点讲解             }

Spring 动态切入点讲解         }
;
Spring 动态切入点讲解     }

Spring 动态切入点讲解
Spring 动态切入点讲解 }

Spring 动态切入点讲解

环绕通知:

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

Spring 动态切入点讲解
Spring 动态切入点讲解 }

Spring 动态切入点讲解

测试代码:

Spring 动态切入点讲解package  DynamicPointCutAdvisor;
Spring 动态切入点讲解
Spring 动态切入点讲解
import  org.aopalliance.aop.Advice;
Spring 动态切入点讲解
import  org.springframework.aop.Advisor;
Spring 动态切入点讲解
import  org.springframework.aop.Pointcut;
Spring 动态切入点讲解
import  org.springframework.aop.framework.ProxyFactory;
Spring 动态切入点讲解
import  org.springframework.aop.support.DefaultPointcutAdvisor;
Spring 动态切入点讲解
Spring 动态切入点讲解Spring 动态切入点讲解
public   class  Test  ... {
Spring 动态切入点讲解
Spring 动态切入点讲解Spring 动态切入点讲解     
/** */ /**
Spring 动态切入点讲解      * 
@param  args
Spring 动态切入点讲解      
*/

Spring 动态切入点讲解Spring 动态切入点讲解     
public   static   void  main(String[] args)  ... {
Spring 动态切入点讲解          BeanOne one
= new  BeanOne();
Spring 动态切入点讲解         
Spring 动态切入点讲解          BeanOne proxyOne;
Spring 动态切入点讲解     
Spring 动态切入点讲解          
Spring 动态切入点讲解          Pointcut pc
= new  SimpleDynamicPointcut();
Spring 动态切入点讲解          Advice advice
= new  SimpleAdvise();
Spring 动态切入点讲解          Advisor advisor
= new  DefaultPointcutAdvisor(pc,advice);
Spring 动态切入点讲解          
Spring 动态切入点讲解          
Spring 动态切入点讲解          
// 创建BeanOne代理
Spring 动态切入点讲解
         ProxyFactory pf1 = new  ProxyFactory();
Spring 动态切入点讲解          pf1.addAdvisor(advisor);
Spring 动态切入点讲解          pf1.setTarget(one);
Spring 动态切入点讲解          proxyOne
= (BeanOne)pf1.getProxy();
Spring 动态切入点讲解          
Spring 动态切入点讲解      
Spring 动态切入点讲解          
Spring 动态切入点讲解          
Spring 动态切入点讲解          proxyOne.dynamic(
100 );
Spring 动态切入点讲解          System.out.println(
" ------------------- " );
Spring 动态切入点讲解          proxyOne.dynamic(
101 );
Spring 动态切入点讲解          System.out.println(
" ------------------- " );
Spring 动态切入点讲解          proxyOne.bar();
Spring 动态切入点讲解
Spring 动态切入点讲解     }

Spring 动态切入点讲解
Spring 动态切入点讲解 }

Spring 动态切入点讲解

运行结果:

100
-------------------
before
101
after

-------------------
bar-one

后记

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

Spring 动态切入点讲解package  DynamicPointCutAdvisor;
Spring 动态切入点讲解
Spring 动态切入点讲解
import  java.lang.reflect.Method;
Spring 动态切入点讲解
Spring 动态切入点讲解
import  org.springframework.aop.ClassFilter;
Spring 动态切入点讲解
import  org.springframework.aop.support.DynamicMethodMatcherPointcut;
Spring 动态切入点讲解
Spring 动态切入点讲解Spring 动态切入点讲解
public   class  SimpleDynamicPointcut  extends  DynamicMethodMatcherPointcut  ... {
Spring 动态切入点讲解
Spring 动态切入点讲解     
Spring 动态切入点讲解     
// 静态方法检查,为避免每次调用bar方法是都进行一次检测,导致效率降低
Spring 动态切入点讲解Spring 动态切入点讲解
     public   boolean  matches(Method method, Class cls)  ... {
Spring 动态切入点讲解         System.out.println(
" static check for  " + method.getName());
Spring 动态切入点讲解         
return   " dynamic " .equals(method.getName());
Spring 动态切入点讲解     }

Spring 动态切入点讲解     
// 当参数不为100时候,进行切入
Spring 动态切入点讲解Spring 动态切入点讲解
     public   boolean  matches(Method method, Class cls, Object[] obj)  ... {
Spring 动态切入点讲解         System.out.println(
" dynamic check for  " + method.getName());
Spring 动态切入点讲解         
int  x = ((Integer)obj[ 0 ]).intValue();
Spring 动态切入点讲解         
return  (x != 100 );
Spring 动态切入点讲解     }

Spring 动态切入点讲解Spring 动态切入点讲解     
public  ClassFilter getClassFilter() ... {
Spring 动态切入点讲解Spring 动态切入点讲解         
return   new  ClassFilter() ... {
Spring 动态切入点讲解Spring 动态切入点讲解             
public   boolean  matches(Class cls) ... {
Spring 动态切入点讲解                 
return  cls == BeanOne. class ;
Spring 动态切入点讲解             }

Spring 动态切入点讲解         }
;
Spring 动态切入点讲解     }

Spring 动态切入点讲解
Spring 动态切入点讲解 }

Spring 动态切入点讲解


可以看到结果如下:

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();就会出现异常)