如果我们需要根据方法的参数不同而决定事都进行切入,而不是不管方法是什么参数全部切入的话,我们就需要使用动态切入点,在每次方法调用时候都进行检查(确切的说是参数检查),;来决定是否执行通知
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();就会出现异常)
本文介绍如何使用Spring AOP的动态切入点来实现基于方法参数的条件性切面行为。通过示例展示了如何定义动态切入点,以及如何结合环绕通知实现特定条件下的方法拦截。
1243

被折叠的 条评论
为什么被折叠?



