一、創建代理準備工作
回顧之前的wrapIfNecessary方法,再獲取到匹配的增強器後,Spring就會爲攔截的bean創建代理對象:
//獲取匹配的增強器
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
//DO_NOT_PROXY = null
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//創建代理
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
創建代理createProxy:
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
//在bean對應的BeanDefinition中添加原Class對象屬性(保存bean原本的Class)
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
//獲取當前類中配置的屬性
proxyFactory.copyFrom(this);
//檢查proxyTargetClass屬性
if (!proxyFactory.isProxyTargetClass()) {
//檢查beanDefinitioin中是否包含preserveTargetClass屬性,且屬性爲true
//設置是否使用CGLib進行代理
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
//篩選代理接口並添加到proxyFactory
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
//獲取增強器(包括前面篩選出來的增強器,以及通過setInterceptorNames中添加的通用增強器,默認爲空)
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
for (Advisor advisor : advisors) {
//將所有增強器添加到proxyFactory
proxyFactory.addAdvisor(advisor);
}
//設置需要代理的bean對象信息
proxyFactory.setTargetSource(targetSource);
//模版方法,由子類定製化代理
customizeProxyFactory(proxyFactory);
//用來控制代理工程被配置後,是否還允許修改代理的配置,默認爲false
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//創建代理對象
return proxyFactory.getProxy(getProxyClassLoader());
}
上面代理流程爲:
- 在BeanDefinition中保存bean原Class對象,因爲創建代理後,bean的class會被修改(Spring4中新加入的帶你,Spring3中不包含)
- 創建ProxyFactory
- 設置屬性
- 過濾目標bean的接口,並添加到ProxyFactory
- 獲取增強器實例,添加到ProxyFactory中
- 創建代理
過濾接口
過濾接口中主要功能是,幫助判斷是否使用JDK的動態代理來創建代理。因爲JDK動態代理的條件是bean實現了接口,所以Spring會將目標bean實現的接口過濾後添加到ProxyFactory中,方便判斷是否使用JDK動態代理,下面是evaluateProxyInterfaces實現:
protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
//獲取所有實現的接口
Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
boolean hasReasonableProxyInterface = false;
for (Class<?> ifc : targetInterfaces) {
//不是Spring內部回調用的接口 && 不是語言內部接口 && 接口定義了一個以上的方法
if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
ifc.getMethods().length > 0) {
hasReasonableProxyInterface = true;
break;
}
}
//如果滿足上面三個條件,纔會將接口添加到proxyFactory
if (hasReasonableProxyInterface) {
// Must allow for introductions; can't just set interfaces to the target's interfaces only.
for (Class<?> ifc : targetInterfaces) {
proxyFactory.addInterface(ifc);
}
}
//條件不滿足,缺少合適的接口,無法使用JDK動態代理,使用CGLib
else {
proxyFactory.setProxyTargetClass(true);
}
}
下面是過濾條件:
1.Spring內部接口
會排除掉InitializingBean、DisposableBean、Aware接口
protected boolean isConfigurationCallbackInterface(Class<?> ifc) {
return (InitializingBean.class == ifc || DisposableBean.class == ifc ||
ObjectUtils.containsElement(ifc.getInterfaces(), Aware.class));
}
2、是否是語言內部接口 isInternalLanguageInterface
protected boolean isInternalLanguageInterface(Class<?> ifc) {
return (ifc.getName().equals("groovy.lang.GroovyObject") ||
ifc.getName().endsWith(".cglib.proxy.Factory"));
}
其實就是比較類名
3、接口中是否定義了方法
二、創建代理
ProxyFactory.getProxy:
public Object getProxy(ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
createAopProxy:
protected final synchronized AopProxy createAopProxy() {
//active會在在第一次創建代理後,設爲true
if (!this.active) {
//設置active爲true,並通知監聽器(如果沒有配置,爲空)
activate();
}
//getAopProxyFactory會返回aopProxyFactory變量,默認實現爲DefaultAopProxyFactory
return getAopProxyFactory().createAopProxy(this);
}
代碼流程:
- 如果是第一次創建代理,會通知ProxyFactory中註冊的監聽器
- 獲取類中定義的aopProxyFactory變量,默認實現爲DefaultAopProxyFactory
- 通過DefaultAopProxyFactory創建代理對象(會傳入當前對象,用於獲取配置信息)
DefaultAopProxyFactory-->createAopProxy:
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
//代理目標bean的Class不能爲空
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: Either an interface or a target is required for proxy creation.");
}
//如果是接口 或者 Class類型爲Proxy
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
Spring生成代理對象的方式有兩種,JDK動態代理和CGLib,分別生成JdkDynamicAopProxy和ObjenesisCglibAopProxy,從上面代碼可以看出Spring的判斷條件:
- optimize:用來控制通過CGLib創建的代理是否使用激進的優化策略(該僅對CGLib有效)
- proxyTargetClass:當屬性爲true,使用CGLib,設置方式:<aop:aspectj-autoproxy proxy-target-class="true">。
- 是否存在代理接口(也就是前面過濾接口一節中,添加進去的接口)
- 如果目標類是接口的話,還是會使用JDK的方式進行代理
JDK動態代理與CGLib的區別:
- JDK只能針對實現了接口的類生成代理
- CGLib是針對類實現代理,主要通過生成目標類的子類,覆蓋其中的方法來達到代理的目的。因此,目標類或方法不能被定義爲final
三、獲取代理對象
回顧之前getProxy創建代理的代碼:
public Object getProxy(ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
getAopProxy就是上一節中獲取到的AopProxy實例:JdkDynamicAopProxy或ObjenesisCglibAopProxy,後面會調用其getProxy獲取代理對象:
public Object getProxy(ClassLoader classLoader) {
//log...
//獲取代理接口
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
//檢查是否在接口中定義了equals或hashCode方法
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
//創建代理對象
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
上面代碼流程:
- 獲取代理接口
- 檢查是否在接口中定義了equals或hashCode方法
- 使用JDK動態代理Proxy.newProxyInstance創建代理對象
四、方法攔截過程
JDK生成代理對象需要調用return Proxy.newProxyInstance,並傳入類加載器、代理接口、以及一個InvocationHandler實例。其中InvocationHandler的invoke方法定義了代理的流程。
上面代碼中,傳入的InvocationHandler是this,即JdkDynamicAopProxy,該類實現了InvocationHandler接口,下面是其invoke方法實現:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
//獲取原對象信息
TargetSource targetSource = this.advised.targetSource;
Class<?> targetClass = null;
Object target = null;
try {
//如果接口中定義了equals或hashCode方法,則進行專門處理
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
//opaque屬性,表示是否禁止將代理對象轉換爲Advised對象,默認是false
//如果調用的方法來自Advised接口
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
//通過反射Method.invoke,調用advised(傳入的ProxyFactory實例,該類實現了Advised接口)對應的方法
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
//爲了解決目標對象內部的自我調用無法實施切面中的增強,需要暴露代理對象
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 獲取目標對象信息
target = targetSource.getTarget();
if (target != null) {
targetClass = target.getClass();
}
// 獲取當前方法的攔截器鏈
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// 如果沒有任何攔截器,則調用直接對原目標對象調用方法
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 將攔截器鏈封裝到ReflectiveMethodInvocation,方便使用其proceed進行鏈式調用攔截器
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 執行攔截器鏈
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// 特殊情況:爲了防止方法返回"return this",返回原目標對象,會將返回值替換爲代理對象
retVal = proxy;
}
//如果返回類型是基本類型兵器,但是返回結果爲null,拋出異常
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
代碼流程:
- 特殊方法的處理,包括equals、hashCode方法以及定義在Advised接口中的方法
- 獲取方法匹配的增強器,並生成攔截器鏈並調用
- 對方法返回結果進行處理:如果返回“this”,即原目標對象,則會替換爲返回代理對象;如果返回結果爲null,但返回類型爲基本數據類型(int、char等)則拋出異常
1、獲取匹配的攔截器:
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
//緩存的cacheKey,先嚐試從緩存獲取,不存在再從ProxyFactory中解析
MethodCacheKey cacheKey = new MethodCacheKey(method);
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
//通過實例方法和ProxyFactory中保存的信息,解析出匹配的增強
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}
方法匹配增強器的功能交由advisorChainFactory(DefaultAdvisorChainFactory)完成:
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, Class<?> targetClass) {
List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
//方法是否匹配引介增強
boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
//遍歷增強器
for (Advisor advisor : config.getAdvisors()) {
//PointcutAdvisor類型的增強器
//通過@Aspect加入的增強器類型爲InstantiationModelAwarePointcutAdvisorImpl,實現了PointcutAdvisor
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
//對於引介增強的處理
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
上面代碼首先會遍歷攔截增強器,然後根據目標類和目標方法(引介增強外)匹配增強器,如果匹配的話,返回增強器包裝的攔截器(Advice)
對於@Aspect註解配置類中,@Before、@After、@AfterThrowing配置的增強會被包裝爲AspectJMethodBeforeAdvice、AspectJAfterReturningAdvice、AspectJAfterThrowingAdvice等,在這一步驟中,這些Advice會分別被封裝爲MethodBeforeAdviceInterceptor、AfterReturningAdviceInterceptor、ThrowsAdviceInterceptor攔截器。
2、創建攔截器鏈並調用
Spring會在獲取到方法匹配的攔截器後,將代理對象、目標對象、調用方法、參數、攔截器等信息封裝到ReflectiveMethodInvocation中:
protected ReflectiveMethodInvocation(
Object proxy, Object target, Method method, Object[] arguments,
Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {
this.proxy = proxy;
this.target = target;
this.targetClass = targetClass;
this.method = BridgeMethodResolver.findBridgedMethod(method);
this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);
this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
}
然後調用ReflectiveMethodInvocation的proceed方法:
public Object proceed() throws Throwable {
// 執行完所有增強後,執行切點方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
//獲取下一個攔截器
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
//動態匹配
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
//不匹配則不執行攔截器
return proceed();
}
}
else {
// 普通攔截器。比如:MethodBeforeAdviceInterceptor、AfterReturningAdviceInterceptor、ThrowsAdviceInterceptor
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
通過currentInterceptorIndex記錄當前攔截器的索引,每調用一個攔截器就+1,再次調用proceed方法時就會獲取下一個攔截器調用。
3、攔截器調用
在獲取增強器的過程中,例如@Before註解標註的方法會被封裝爲AspectJMethodBeforeAdvice,然後會在 1.獲取匹配的攔截器 過程中,會被包裝爲MethodInterceptor(MethodBeforeAdviceInterceptor),下面是Advice轉換爲MethodInterceptor的過程:
DefaultAdvisorAdapterRegistry.getInterceptors:
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);
//獲取Advice
Advice advice = advisor.getAdvice();
//如果Advice實例同時已經實現MethodInterceptor接口,則直接使用
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
//需要使用適配器來轉換Advice接口
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[interceptors.size()]);
}
代碼流程:
- 如果Advice增強已經實現了MethodInterceptor,則不需要轉換,可以直接使用。例如:@After註解標註的增強方法會被表示爲AspectJAfterAdvice,該類同時實現了Advice和MethodInterceptor接口,也就是已經在類中規定好了攔截的邏輯。
- Advice實現了沒有同時實現MethodInterceptor,所以需要使用內置的適配器將Advice增強轉換爲MethodInterceptor攔截器。
a、內置的Advice適配器
在前面的代碼中,將Advice轉換爲MethodInterceptor的工作是交給this.adapters來完成的,該變量定義如下;
private final List<AdvisorAdapter> adapters = new ArrayList<AdvisorAdapter>(3);
並且在DefaultAdvisorAdapterRegistry的構造函數中,對該變量進行了初始化填充:
public DefaultAdvisorAdapterRegistry() {
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
可以看到,Spring實現會加入3個默認的是Advice適配器:MethodBeforeAdviceAdapter、AfterReturningAdviceAdapter、ThrowsAdviceAdapter。
這三個適配器通過support方法,驗證是否是否支持傳入的Advice對象,如果支持,會將Advice實例封裝爲對應的MethodInterceptor實例:
MethodBeforeAdviceAdapter:
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof MethodBeforeAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
return new MethodBeforeAdviceInterceptor(advice);
}
}
AfterReturningAdviceAdapter:
class AfterReturningAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof AfterReturningAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
AfterReturningAdvice advice = (AfterReturningAdvice) advisor.getAdvice();
return new AfterReturningAdviceInterceptor(advice);
}
}
ThrowsAdviceAdapter:
class ThrowsAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof ThrowsAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
return new ThrowsAdviceInterceptor(advisor.getAdvice());
}
}
下面是對三種適配器的總結:
適配器 | 支持的Advice接口 | Advice實現類 | 對應註解 |
---|---|---|---|
MethodBeforeAdviceAdapter | MethodBeforeAdvice | AspectJMethodBeforeAdvice | @Before |
AfterReturningAdviceAdapter | AfterReturningAdvice | AspectJAfterReturningAdvice | @AfterReturning |
ThrowsAdviceAdapter | ThrowsAdvice | 無 | 無 |
下面再來總結一下通過註解配置的增強對應的攔截器:
註解 | Advice | MethodInterceptor |
---|---|---|
@Before | AspectJMethodBeforeAdvice | MethodBeforeAdviceInterceptor |
@After | AspectJAfterAdvice | AspectJAfterAdvice |
@AfterReturning | AspectJAfterReturningAdvice | AfterReturningAdviceInterceptor |
@AfterThrowing | AspectJAfterThrowingAdvice | AspectJAfterThrowingAdvice |
@Around | AspectJAroundAdvice | AspectJAroundAdvice |
b、攔截器調用
攔截器的類型有多中,下面我們分析由@Before註解添加的攔截器MethodBeforeAdviceInterceptor。
MethodBeforeAdviceInterceptor定義:
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {
private MethodBeforeAdvice advice;
/**
* 將傳入的MethodBeforeAdvice封裝爲MethodBeforeAdviceInterceptor
* @param advice the MethodBeforeAdvice to wrap
*/
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
return mi.proceed();
}
}
從invoke方法中可以看到,攔截器會在調用真正方法前,調用MethodBeforeAdvice的before方法,在這一步,也就完成了方法的前置增強。
下面看一下AspectJMethodBeforeAdvice的before實現:
public void before(Method method, Object[] args, Object target) throws Throwable {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
protected Object invokeAdviceMethod(JoinPointMatch jpMatch, Object returnValue, Throwable ex) throws Throwable {
//將參數綁定後,傳入invokeAdviceMethodWithGivenArgs方法執行
return invokeAdviceMethodWithGivenArgs(argBinding(getJoinPoint(), jpMatch, returnValue, ex));
}
invokeAdviceMethodWithGivenArgs:
protected Object invokeAdviceMethodWithGivenArgs(Object[] args) throws Throwable {
Object[] actualArgs = args;
//如果advice增強方法參數爲空
if (this.aspectJAdviceMethod.getParameterTypes().length == 0) {
actualArgs = null;
}
try {
ReflectionUtils.makeAccessible(this.aspectJAdviceMethod);
// 通過反射,調用增強方法
return this.aspectJAdviceMethod.invoke(this.aspectInstanceFactory.getAspectInstance(), actualArgs);
}
catch (IllegalArgumentException ex) {
throw new AopInvocationException("Mismatch on arguments to advice method [" +
this.aspectJAdviceMethod + "]; pointcut expression [" +
this.pointcut.getPointcutExpression() + "]", ex);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}