尋找入口
Spring 的AOP 是通過接入BeanPostProcessor 后置處理器開始的,它是Spring IOC 容器經(jīng)常使用到的一個(gè)特性,這個(gè)Bean 后置處理器是一個(gè)監(jiān)聽器,可以監(jiān)聽容器觸發(fā)的Bean 聲明周期事件。后置處理器向容器注冊(cè)以后,容器中管理的Bean 就具備了接收IOC 容器事件回調(diào)的能力。
BeanPostProcessor 的使用非常簡(jiǎn)單,只需要提供一個(gè)實(shí)現(xiàn)接口BeanPostProcessor 的實(shí)現(xiàn)類,然后在Bean 的配置文件中設(shè)置即可。
1、BeanPostProcessor 源碼
public interface BeanPostProcessor {
//為在Bean 的初始化前提供回調(diào)入口
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
//為在Bean 的初始化之后提供回調(diào)入口
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
這兩個(gè)回調(diào)的入口都是和容器管理的Bean 的生命周期事件緊密相關(guān),可以為用戶提供在Spring IOC容器初始化Bean 過程中自定義的處理操作。
2、AbstractAutowireCapableBeanFactory 類對(duì)容器生成的Bean 添加后置處理器
BeanPostProcessor 后置處理器的調(diào)用發(fā)生在Spring IOC 容器完成對(duì)Bean 實(shí)例對(duì)象的創(chuàng)建和屬性的依賴注入完成之后,在對(duì)Spring 依賴注入的源碼分析過程中我們知道,當(dāng)應(yīng)用程序第一次調(diào)用getBean()方法(lazy-init 預(yù)實(shí)例化除外)向Spring IOC 容器索取指定Bean 時(shí)觸發(fā)Spring IOC 容器創(chuàng)建Bean 實(shí)例對(duì)象并進(jìn)行依賴注入的過程, 其中真正實(shí)現(xiàn)創(chuàng)建Bean 對(duì)象并進(jìn)行依賴注入的方法是AbstractAutowireCapableBeanFactory 類的doCreateBean()方法,主要源碼如下:
//真正創(chuàng)建Bean 的方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
//創(chuàng)建Bean 實(shí)例對(duì)象
...
Object exposedObject = bean;
try {
//對(duì)Bean 屬性進(jìn)行依賴注入
populateBean(beanName, mbd, instanceWrapper);
//在對(duì)Bean 實(shí)例對(duì)象生成和依賴注入完成以后,開始對(duì)Bean 實(shí)例對(duì)象
//進(jìn)行初始化,為Bean 實(shí)例對(duì)象應(yīng)用BeanPostProcessor 后置處理器
exposedObject = initializeBean(beanName, exposedObject, mbd);
} catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
} else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
...
//為應(yīng)用返回所需要的實(shí)例對(duì)象
return exposedObject;
}
從上面的代碼中我們知道,為Bean 實(shí)例對(duì)象添加BeanPostProcessor 后置處理器的入口的是initializeBean()方法。
3、initializeBean()方法為容器產(chǎn)生的Bean 實(shí)例對(duì)象添加BeanPostProcessor 后置處理器
同樣在AbstractAutowireCapableBeanFactory 類中,initializeBean()方法實(shí)現(xiàn)為容器創(chuàng)建的Bean實(shí)例對(duì)象添加BeanPostProcessor 后置處理器,源碼如下:
//初始容器創(chuàng)建的Bean 實(shí)例對(duì)象,為其添加BeanPostProcessor 后置處理器
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
//JDK 的安全機(jī)制驗(yàn)證權(quán)限
if (System.getSecurityManager() != null) {
//實(shí)現(xiàn)PrivilegedAction 接口的匿名內(nèi)部類
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
} else {
//為Bean 實(shí)例對(duì)象包裝相關(guān)屬性,如名稱,類加載器,所屬容器等信息
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
//對(duì)BeanPostProcessor 后置處理器的postProcessBeforeInitialization
//回調(diào)方法的調(diào)用,為Bean 實(shí)例初始化前做一些處理
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
//調(diào)用Bean 實(shí)例對(duì)象初始化的方法,這個(gè)初始化方法是在Spring Bean 定義配置
//文件中通過init-Method 屬性指定的
try {
invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init Method failed", ex);
}
//對(duì)BeanPostProcessor 后置處理器的postProcessAfterInitialization
//回調(diào)方法的調(diào)用,為Bean 實(shí)例初始化之后做一些處理
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
@Override
//調(diào)用BeanPostProcessor 后置處理器實(shí)例對(duì)象初始化之前的處理方法
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
//遍歷容器為所創(chuàng)建的Bean 添加的所有BeanPostProcessor 后置處理器
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
//調(diào)用Bean 實(shí)例所有的后置處理中的初始化前處理方法,為Bean 實(shí)例對(duì)象在
//初始化之前做一些自定義的處理操作
Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
@Override
//調(diào)用BeanPostProcessor 后置處理器實(shí)例對(duì)象初始化之后的處理方法
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
//遍歷容器為所創(chuàng)建的Bean 添加的所有BeanPostProcessor 后置處理器
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
//調(diào)用Bean 實(shí)例所有的后置處理中的初始化后處理方法,為Bean 實(shí)例對(duì)象在
//初始化之后做一些自定義的處理操作
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
BeanPostProcessor 是一個(gè)接口,其初始化前的操作方法和初始化后的操作方法均委托其實(shí)現(xiàn)子類來實(shí)現(xiàn),在Spring 中,BeanPostProcessor 的實(shí)現(xiàn)子類非常的多,分別完成不同的操作,如:AOP 面向切面編程的注冊(cè)通知適配器、Bean 對(duì)象的數(shù)據(jù)校驗(yàn)、Bean 繼承屬性、方法的合并等等,我們以最簡(jiǎn)單的AOP 切面織入來簡(jiǎn)單了解其主要的功能。下面我們來分析其中一個(gè)創(chuàng)建AOP 代理對(duì)象的子類AbstractAutoProxyCreator 類。該類重寫了postProcessAfterInitialization()方法。
選擇代理策略
進(jìn)入postProcessAfterInitialization()方法,我們發(fā)現(xiàn)調(diào)到了一個(gè)非常核心的方法wrapIfNecessary(),其源碼如下:
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws
BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
...
/**
* Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
*
* @param bean the raw bean instance
* @param beanName the name of the bean
* @param cacheKey the cache key for metadata access
* @return a proxy wrapping the bean, or the raw bean instance as-is
*/
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 判斷是否不應(yīng)該代理這個(gè)bean
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
/**
*
*判斷是否是一些InfrastructureClass 或者是否應(yīng)該跳過這個(gè)bean。
*所謂InfrastructureClass 就是指Advice/PointCut / Advisor 等接口的實(shí)現(xiàn)類。
*shouldSkip 默認(rèn)實(shí)現(xiàn)為返回false, 由于是protected 方法,子類可以覆蓋。
*/
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 獲取這個(gè)bean 的advice
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName,
null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 創(chuàng)建代理
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
...
/**
* Create an AOP proxy for the given bean.
*
* @param beanClass the class of the bean
* @param beanName the name of the bean
* @param specificInterceptors the set of interceptors that is
* specific to this bean (may be empty, but not null)
* @param targetSource the TargetSource for the proxy,
* already pre-configured to access the bean
* @return the AOP proxy for the bean
* @see #buildAdvisors
*/
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory,
beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
} else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
整個(gè)過程跟下來,我發(fā)現(xiàn)最終調(diào)用的是proxyFactory.getProxy()方法。到這里我們大概能夠猜到proxyFactory 有JDK 和CGLib 的,那么我們?cè)撊绾芜x擇呢?最終調(diào)用的是DefaultAopProxyFactory的createAopProxy()方法:
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() ||
hasNoUserSuppliedProxyInterfaces(config)) {
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.");
}
if(targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
} else {
return new JdkDynamicAopProxy(config);
}
}
/**
* Determine whether the supplied {@link AdvisedSupport} has only the
* {@link org.springframework.aop.SpringProxy} interface specified
* (or no proxy interfaces specified at all).
*/
private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
Class<?>[] ifcs = config.getProxiedInterfaces();
return (ifcs.length == 0 || (ifcs.length == 1 &&
SpringProxy.class.isAssignableFrom(ifcs[0])));
}
}
調(diào)用代理方法
分析調(diào)用邏輯之前先上類圖,看看Spring 中主要的AOP 組件:

上面我們已經(jīng)了解到Spring 提供了兩種方式來生成代理方式有JDKProxy 和CGLib。下面我們來研究一下Spring 如何使用JDK 來生成代理對(duì)象,具體的生成代碼放在JdkDynamicAopProxy 這個(gè)類中,直接上相關(guān)代碼:
/**
* 獲取代理類要實(shí)現(xiàn)的接口,除了Advised 對(duì)象中配置的,還會(huì)加上SpringProxy, Advised(opaque=false)
* 檢查上面得到的接口中有沒有定義equals 或者h(yuǎn)ashcode 的接口
* 調(diào)用Proxy.newProxyInstance 創(chuàng)建代理對(duì)象
*/
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
通過注釋我們應(yīng)該已經(jīng)看得非常明白代理對(duì)象的生成過程,此處不再贅述。下面的問題是,代理對(duì)象生成了,那切面是如何織入的?
我們知道InvocationHandler 是JDK 動(dòng)態(tài)代理的核心,生成的代理對(duì)象的方法調(diào)用都會(huì)委托到InvocationHandler.invoke()方法。而從JdkDynamicAopProxy 的源碼我們可以看到這個(gè)類其實(shí)也實(shí)現(xiàn)了InvocationHandler,下面我們分析Spring AOP 是如何織入切面的,直接上源碼看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;
Object target = null;
try {
//eqauls()方法,具目標(biāo)對(duì)象未實(shí)現(xiàn)此方法
if (!this.equalsDefined && AopUtils.isEqualsMethod(Method)) {
return equals(args[0]);
}
//hashCode()方法,具目標(biāo)對(duì)象未實(shí)現(xiàn)此方法
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(Method)) {
return hashCode();
} else if (Method.getDeclaringClass() == DecoratingProxy.class) {
return AopProxyUtils.ultimateTargetClass(this.advised);
}
//Advised 接口或者其父接口中定義的方法,直接反射調(diào)用,不應(yīng)用通知
else if (!this.advised.opaque && Method.getDeclaringClass().isInterface() &&
Method.getDeclaringClass().isAssignableFrom(Advised.class)) {
return AopUtils.invokeJoinpointUsingReflection(this.advised, Method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
//獲得目標(biāo)對(duì)象的類
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
//獲取可以應(yīng)用到此方法上的Interceptor 列表
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(Method, targetClass);
//如果沒有可以應(yīng)用到此方法的通知(Interceptor),此直接反射調(diào)用Method.invoke(target, args)
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(Method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, Method, argsToUse);
} else {
//創(chuàng)建MethodInvocation
invocation = new ReflectiveMethodInvocation(proxy, target, Method, args, targetClass, chain);
retVal = invocation.proceed();
}
Class<?> returnType = Method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(Method.getDeclaringClass())) {
retVal = proxy;
} 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()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
}
主要實(shí)現(xiàn)思路可以簡(jiǎn)述為:首先獲取應(yīng)用到此方法上的通知鏈(Interceptor Chain)。如果有通知,則應(yīng)用通知,并執(zhí)行JoinPoint;如果沒有通知,則直接反射執(zhí)行JoinPoint。而這里的關(guān)鍵是通知鏈?zhǔn)侨绾潍@取的以及它又是如何執(zhí)行的呢?現(xiàn)在來逐一分析。首先,從上面的代碼可以看到,通知鏈?zhǔn)峭ㄟ^Advised.getInterceptorsAndDynamicInterceptionAdvice()這個(gè)方法來獲取的,我們來看下這個(gè)方法的實(shí)現(xiàn)邏輯:
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method Method, @Nullable Class<?> targetClass) {
MethodCacheKey cacheKey = new MethodCacheKey(Method);
List<Object> cached = this.MethodCache.get(cacheKey);
if (cached == null) {
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, Method, targetClass);
this.MethodCache.put(cacheKey, cached);
}
return cached;
}
通過上面的源碼我們可以看到, 實(shí)際獲取通知的實(shí)現(xiàn)邏輯其實(shí)是由AdvisorChainFactory 的getInterceptorsAndDynamicInterceptionAdvice()方法來完成的,且獲取到的結(jié)果會(huì)被緩存。下面來分析getInterceptorsAndDynamicInterceptionAdvice()方法的實(shí)現(xiàn):
/**
* 從提供的配置實(shí)例config 中獲取advisor 列表,遍歷處理這些advisor.如果是IntroductionAdvisor,
* 則判斷此Advisor 能否應(yīng)用到目標(biāo)類targetClass 上.如果是PointcutAdvisor,則判斷
* 此Advisor 能否應(yīng)用到目標(biāo)方法Method 上.將滿足條件的Advisor 通過AdvisorAdaptor 轉(zhuǎn)化成Interceptor 列表返回.
*/
@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method Method, @Nullable Class<?> targetClass) {
List<Object> interceptorList = new ArrayList<>(config.getAdvisors().length);
Class<?> actualClass = (targetClass != null ? targetClass : Method.getDeclaringClass());
//查看是否包含IntroductionAdvisor
boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
//這里實(shí)際上注冊(cè)一系列AdvisorAdapter,用于將Advisor 轉(zhuǎn)化成MethodInterceptor
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
for (Advisor advisor : config.getAdvisors()) {
if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
//這個(gè)地方這兩個(gè)方法的位置可以互換下
//將Advisor 轉(zhuǎn)化成Interceptor
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
//檢查當(dāng)前advisor 的pointcut 是否可以匹配當(dāng)前方法
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
if (MethodMatchers.matches(mm, Method, actualClass, hasIntroductions)) {
if (mm.isRuntime()) {
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;
}
這個(gè)方法執(zhí)行完成后,Advised 中配置能夠應(yīng)用到連接點(diǎn)(JoinPoint)或者目標(biāo)類(Target Object)的Advisor 全部被轉(zhuǎn)化成了MethodInterceptor,接下來我們?cè)倏聪碌玫降臄r截器鏈?zhǔn)窃趺雌鹱饔玫摹?/p>
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(Method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, Method, argsToUse);
} else {
//創(chuàng)建MethodInvocation
invocation = new ReflectiveMethodInvocation(proxy, target, Method, args, targetClass, chain);
retVal = invocation.proceed();
}
從這段代碼可以看出, 如果得到的攔截器鏈為空, 則直接反射調(diào)用目標(biāo)方法, 否則創(chuàng)建MethodInvocation,調(diào)用其proceed()方法,觸發(fā)攔截器鏈的執(zhí)行,來看下具體代碼:
public Object proceed() throws Throwable {
//如果Interceptor 執(zhí)行完了,則執(zhí)行joinPoint
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
//如果要?jiǎng)討B(tài)匹配joinPoint
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
//動(dòng)態(tài)匹配:運(yùn)行時(shí)參數(shù)是否滿足匹配條件
if (dm.MethodMatcher.matches(this.Method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
//動(dòng)態(tài)匹配失敗時(shí),略過當(dāng)前Intercetpor,調(diào)用下一個(gè)Interceptor
return proceed();
}
}
else {
//執(zhí)行當(dāng)前Intercetpor
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
至此,通知鏈就完美地形成了。我們?cè)偻聛韎nvokeJoinpointUsingReflection()方法,其實(shí)就是反射調(diào)用:
public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method,
Object[] args) throws Throwable {
// Use reflection to invoke the method.
try {
ReflectionUtils.makeAccessible(method);
return method.invoke(target, args);
} catch (InvocationTargetException ex) {
// Invoked method threw a checked exception.
// We must rethrow it. The client won't see the interceptor.
throw ex.getTargetException();
} catch (IllegalArgumentException ex) {
throw new AopInvocationException("AOP configuration seems to be invalid: tried calling
method[" +
method + "] on target [" + target + "]", ex);
} catch (IllegalAccessException ex) {
throw new AopInvocationException("Could not access method [" + method + "]", ex);
}
}