一、AOP的配置使用
1、AOP入口
通過掃描註解@EnableAspectJAutoProxy(proxyTargetClass = true,exposeProxy = true)註冊了AOP 入口類,具體看看註解裏面的@Import(AspectJAutoProxyRegistrar.class)
/*
* TODO 開啓註解AOP
* 替代了:<aop:aspectj-autoproxy/>
* */
@Service
@EnableAspectJAutoProxy(proxyTargetClass = false,exposeProxy = true)
public class EnableAspectJAutoProxyBean {
}
org.springframework.context.annotation.EnableAspectJAutoProxy
在這個類中,註冊了AOP入口類 AnnotationAwareAspectJAutoProxyCreator
設置了兩個屬性:
proxyTargetClass = true
1)目標對象實現了接口 – 使用CGLIB代理機制
2)目標對象沒有接口(只有實現類) – 使用CGLIB代理機制
proxyTargetClass = false
1)目標對象實現了接口 – 使用JDK動態代理機制(代理所有實現了的接口)
2)目標對象沒有接口(只有實現類) – 使用CGLIB代理機制
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
/**
* Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
* to standard Java interface-based proxies. The default is {@code false}.
*/
boolean proxyTargetClass() default false;
/**
* Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
* for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
* Off by default, i.e. no guarantees that {@code AopContext} access will work.
* @since 4.3.1
*/
boolean exposeProxy() default false;
}
exposeProxy
該屬性設置代理對象是否需要暴露,說白了就是是否需要把代理對象設置到ThreadLocal中。
AOP的其他入口類的配置是基於xml的形式
例如:
<!--開啓註解aop-->
<aop:aspectj-autoproxy proxy-target-class="false" expose-proxy="true"/>
或者
<aop:config proxy-target-class="false">
<!--<aop:pointcut>在此處定義的pointcut是全局的pointcut可以供所有的aspect使用-->
<!--id:表示這個pointcut的名稱,以方便使用-->
<aop:pointcut id="addpointcut" expression="execution(public * com.chj.service..*.add(..))"/>
<aop:pointcut id="delpointcut" expression="execution(public * com.chj.service..*.del*(..))"/>
<aop:pointcut id="myMethods" expression="execution(public * com.chj.service..*.*(..))"/>
<!--advisor必須在aspect之前,要不然有xml約束報錯-->
<aop:advisor advice-ref="beforeAdviceBean" order="2" pointcut-ref="myMethods"/>
<aop:aspect id="aspect1" ref="aspectXml1" order="0">
<!--<aop:declare-parents types-matching="com.zhuguang.jack.service.MyServiceImpl"-->
<!--implement-interface="com.zhuguang.jack.aop.IntroductionIntf"-->
<!--delegate-ref="myintroduction"/>-->
<!--id:表示這個pointcut的名稱,以方便使用-->
<aop:pointcut id="myMethod2" expression="execution(public * com.chj.service..*.*(..))
and @annotation(org.springframework.web.bind.annotation.RequestMapping)"/>
<aop:before method="before" pointcut-ref="myMethods"/>
<aop:after method="after" pointcut-ref="myMethod2"/>
<!-- 後置通知 returning="returnVal" 定義返回值 必須與類中聲明的名稱一樣-->
<aop:after-returning method="afterReturning" returning="returnVal"
pointcut="execution(public * com.chj.service..*.*(..))"/>
<!--異常通知 throwing="throwable" 指定異常通知錯誤信息變量,必須與類中聲明的名稱一樣-->
<!--<aop:after-throwing method="afterthrowing" throwing="e" pointcut-ref="myMethods"/>-->
<aop:around method="around" pointcut-ref="myMethod2"/>
</aop:aspect>
</aop:config>
2、是否生成代理
當一個bean實例化完成後,會判斷該bean是否生成代理,AOP的入口如下:
2.1、Aop代理對象生產入口:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
// Initialize the bean instance.
Object exposedObject = bean;
try {
//ioc di,依賴注入的核心方法,該方法必須看,重要程度:5
populateBean(beanName, mbd, instanceWrapper);
//bean 實例化+ioc依賴注入完以後的調用,非常重要,重要程度:5
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
在這個方法裏面,具體是:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(String,Object, RootBeanDefinition)
if (mbd == null || !mbd.isSynthetic()) {
//這個地方可能生出代理實例,是aop的入口
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
這是一個BeanPostProcessor接口的運用,initializeBean方法我們都知道是一個bean實例化完成後做的操作,而這個代理實例生成也是在bean實例化完成後做的操作,其核心代碼如下:
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
2.2、如果這個bean有advice的話,創建當前bean的代理
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
//創建當前bean的代理,如果這個bean有advice的話,重點看,重要程度5
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
//如果有切面,則生成該bean的代理
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//把被代理對象bean實例封裝到SingletonTargetSource對象中
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;
}
這個方法就是判斷當前bean是否有切面advisor,如果有切面就會走到createProxy方法,生成代理對象然後返回。
2.3、尋找當前bean的切面簡單來說就兩步:
第一步:從spring中找所有的切面,然後找到合格的切面
找到候選的切面,其實就是一個尋找有@Aspectj註解的過程,把工程中所有有這個註解的類封裝成Advisor返回;判斷候選的切面是否作用在當前beanClass上面,就是一個匹配過程,現在就是一個匹配。
org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean();
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean( Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
//找到合格的切面,重點看
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//找到候選的切面,其實就是一個尋找有@Aspectj註解的過程,把工程中所有有這個註解的類封裝成Advisor返回
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//判斷候選的切面是否作用在當前beanClass上面,就是一個匹配過程。。現在就是一個匹配
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
//對有@Order@Priority進行排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
第二步:找到攔截當前bean的切面
從spring中找所有切面, 先找到所有的beanDefinition對象對應的beanName,拿到對應的Class對象,判斷該類上面是否有@Aspect註解,如果有則是我們要找的,循環該Class裏面的除了@PointCut註解的方法,找到方法上面的Around.class,Before.class, After.class, AfterReturning.class, AfterThrowing.class 註解,並且把註解裏面的信息,比如表達式:argNames,註解類型等信息封裝成對象AspectJAnnotation,然後創建pointCut對象,把註解對象中的表達式設置到pointCut對象中,然後就是創建Advice對象,根據不同的註解類型創建出不同的Advice對象,對象如下:
AspectJAroundAdvice,AspectJAfterAdvice,AspectJAfterThrowingAdvice,AspectJMethodBeforeAdvice,AspectJAfterReturningAdvice最終把註解對應的Advice對象和pointCut對象封裝成Advisor對象。
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
//看看當前類是否在這些切面的pointCut中
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
} finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
找到攔截當前bean的切面:
從收集到的所有切面中,每一個切面都會有pointCut來進行模塊匹配,其實這個過程就是一個匹配過程,看看pointCut表達式中的內容是否包含了當前bean,如果包含了,那麼這個bean就有切面,就會生成代理。
//創建當前bean的代理,如果這個bean有advice的話,重點看,重要程度5
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
//如果有切面,則生成該bean的代理
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//把被代理對象bean實例封裝到SingletonTargetSource對象中
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
二、代理類的調用
1、代理類調用入口
當判斷bean有切面時也就是
//如果有切面,則生成該bean的代理
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
//把被代理對象bean實例封裝到SingletonTargetSource對象中
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
這個數組不爲空時,就會往下走,走到createProxy方法裏面,這個方法就會生成bean的代理實例。
2、創建代理的過程:
1)創建代理工廠對象ProxyFactory
2)切面對象重新包裝,會把自定義的MethodInterceptor類型的類包裝成Advisor切面類並加入到代理工廠中
3)根據proxyTargetClass參數和是否實現接口來判斷是採用jdk代理還是cglib代理
4)創建代理對象,並且把代理工廠對象傳遞到jdk和cglib中,注意這裏的代理對象和jdk類和cglib類是一一對應的。
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy
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)) {
//proxyTargetClass 是否對類進行代理,而不是對接口進行代理,設置爲true時,使用CGLib代理。
proxyFactory.setProxyTargetClass(true);
}else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
//把advice類型的增強包裝成advisor切面
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
//用來控制代理工廠被配置後,是否還允許修改代理的配置,默認爲false
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
//獲取代理實例
return proxyFactory.getProxy(getProxyClassLoader());
}
3、獲取代理實例
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy
/獲取代理實例
return proxyFactory.getProxy(getProxyClassLoader());
org.springframework.aop.framework.ProxyFactory#getProxy(java.lang.ClassLoader)
public Object getProxy(@Nullable ClassLoader classLoader) {
//根據目標對象是否有接口來判斷採用什麼代理方式,cglib代理還是jdk動態代理
return createAopProxy().getProxy(classLoader);
}
org.springframework.aop.framework.ProxyCreatorSupport#createAopProxy
org.springframework.aop.framework.DefaultAopProxyFactory#createAopProxy
判斷是使用JDK代理還是cglib動態代理實現:
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.");
}
// 判斷代理類是否實現了接口(如果是使用JDK動態代理)
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
} else {
return new JdkDynamicAopProxy(config);
}
}
4、代理實例的調用
上面我們已經創建出來了代理對象了,現在是拿到代理對象調用,以 jdk動態代理爲例,cglib是一樣的調用邏輯。
當發生代理對象調用時,肯定會調用到實現了invocationHandler接口的類,這個類就是:JdkDynamicAopProxy必定會調用到該類的invoke方法。
我們看看invoke方法:
org.springframework.aop.framework.JdkDynamicAopProxy#invoke
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
該參數如果爲true會把代理對象存放到ThreadLocal中。我們在代理裏面通過AopContext.currentProxy方法就可以拿到當前調用的代理類。實際上沒啥用。
// Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
//這個target就是被代理實例
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// Get the interception chain for this method.
//從代理工廠中拿過濾器鏈 Object是一個MethodInterceptor類型的對象,其實就是一個advice對象
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
org.springframework.aop.framework.JdkDynamicAopProxy#getProxy(java.lang.ClassLoader)
public Object getProxy(@Nullable ClassLoader classLoader) {
//根據目標對象是否有接口來判斷採用什麼代理方式,cglib代理還是jdk動態代理
return createAopProxy().getProxy(classLoader);
}
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isTraceEnabled()) {
logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
}
//advised是代理工廠對象
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
從代理工廠中拿到切面,並且跟當前被代理類和當前被調用方法匹配,如果匹配就返回切面中的advice對象,這就是advice執行鏈。只是對advice進行了統一包裝,如下代碼:
5、advice執行鏈
方法入口:org.springframework.aop.framework.JdkDynamicAopProxy#invoke
//從代理工廠中拿過濾器鏈 Object是一個MethodInterceptor類型的對象,其實就是一個advice對象
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
org.springframework.aop.framework.AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice
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;
}
5.1、獲取過濾器鏈:
org.springframework.aop.framework.DefaultAdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice
@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
//從代理工廠中獲得該被代理類的所有切面advisor,config就是代理工廠對象
Advisor[] advisors = config.getAdvisors();
List<Object> interceptorList = new ArrayList<>(advisors.length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
Boolean hasIntroductions = null;
for (Advisor advisor : advisors) {
//大部分走這裏
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
//如果切面的pointCut和被代理對象是匹配的,說明是切面要攔截的對象
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
}else {
//接下來判斷方法是否是切面pointcut需要攔截的方法
match = mm.matches(method, actualClass);
}
//如果類和方法都匹配
if (match) {
//獲取到切面advisor中的advice,並且包裝成MethodInterceptor類型的對象
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
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;
}
5.2、獲取到切面advisor中的advice,並且包裝成MethodInterceptor類型的對象
org.springframework.aop.framework.adapter.DefaultAdvisorAdapterRegistry#getInterceptors
@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<>(3);
Advice advice = advisor.getAdvice();
//如果是MethodInterceptor類型的,如:AspectJAroundAdvice
//AspectJAfterAdvice
//AspectJAfterThrowingAdvice
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
//處理 AspectJMethodBeforeAdvice AspectJAfterReturningAdvice
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[0]);
}
org.springframework.aop.framework.adapter.DefaultAdvisorAdapterRegistry#getInterceptors
@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<>(3);
Advice advice = advisor.getAdvice();
//如果是MethodInterceptor類型的,如:AspectJAroundAdvice
//AspectJAfterAdvice
//AspectJAfterThrowingAdvice
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
//處理 AspectJMethodBeforeAdvice AspectJAfterReturningAdvice
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[0]);
}
5.3、默認創建的增強:
private final List<AdvisorAdapter> adapters = new ArrayList<>(3);
public DefaultAdvisorAdapterRegistry() {
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
6、Aop鏈式調用過程
最終會把箭頭指向的這兩種類型的advice包裝成MethodInterceptor類型的advice,方便後續統一調用。
org.springframework.aop.framework.JdkDynamicAopProxy#invoke
else {
// We need to create a method invocation...
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}
獲取到這個執行鏈後,判斷如果執行鏈爲空,則直接反射調用方法,說明該方法沒被攔截,如果不爲空就會有一個鏈式調用過程。
6.1、在ReflectiveMethodInvocation中維護了執行鏈數組和數組索引
@Override
@Nullable
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
//如果執行鏈中的advice全部執行完,則直接調用joinPoint方法,就是被代理方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
} else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
//調用MethodInterceptor中的invoke方法
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
6.2、通過索引獲取到數組裏面的advice然後調用mi.proceed()
我們舉例說明,如果第一個advice調用到了beforeAdvice,如下:
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
private final MethodBeforeAdvice advice;
/**
* Create a new MethodBeforeAdviceInterceptor for the given advice.
* @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();
}
}
BeforeAdvice首先會調用自己advice對象中的method對象,而這個method對象就是有@Before註解的方法,我們通過解析方法上面的註解類型生成advice對象時把對應的method對象封裝到了advice對象中,所以這裏就只要反射調用method對象即可。
6.3、Before方法與around方法鏈式調用
調用完後,這裏有一個mi.proceed()這個方法又會回到ReflectiveMethodInvocation這個類中
@Override
@Nullable
public Object proceed() throws Throwable {
//調用MethodInterceptor中的invoke方法
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
這時候索引又會+1,然後從鏈中後去下一個advice,然後下一個advice調用完後再mi.proceed()又會接着調用,其中後置增強是通過在finally塊中執行的,就這樣形成了一個鏈式調用過程。直到數組鏈中全部調用完後會調用到具體的joinPoint方法如下:
@Override
@Nullable
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
//如果執行鏈中的advice全部執行完,則直接調用joinPoint方法,就是被代理方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
//調用MethodInterceptor中的invoke方法
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
當判斷當前索引==執行鏈數組大小時就會調用到被代理方法,完成aop增強過程。
6.4、後置after增強處理方法
org.springframework.aop.aspectj.AspectJAfterAdvice#invoke
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
try {
return mi.proceed();
}
finally {
invokeAdviceMethod(getJoinPointMatch(), null, null);
}
}
三、AOP代理總結