Spring源码------AOP源码分析
目录
1、AOP简介
AOP是什么?
AOP技术利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即切面。所谓“切面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。AOP代表的是一个横向的关系,如果说“对象”是一个空心的圆柱体,其中封装的是对象的属性和行为;那么面向方面编程的方法,就仿佛一把利刃,将这些空心圆柱体剖开,以获得其内部的消息。而剖开的切面,也就是所谓的“方面”了。然后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹。
AOP相关概念
- 方面(Aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是一个很好的横切关注点例子。方面用Spring的Advisor或拦截器实现。
- 连接点(Joinpoint): 程序执行过程中明确的点,如方法的调用或特定的异常被抛出。
- 通知(Advice): 在特定的连接点,AOP框架执行的动作。各种类型的通知包括“around”、“before”和“throws”通知。通知类型将在下面讨论。许多AOP框架包括Spring都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链。Spring中定义了四个advice: BeforeAdvice, AfterAdvice, ThrowAdvice和DynamicIntroductionAdvice
- 切入点(Pointcut): 指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点:例如,使用正则表达式。 Spring定义了Pointcut接口,用来组合MethodMatcher和ClassFilter,可以通过名字很清楚的理解, MethodMatcher是用来检查目标类的方法是否可以被应用此通知,而ClassFilter是用来检查Pointcut是否应该应用到目标类上
- 目标对象(Target Object): 包含连接点的对象。也被称作被通知或被代理对象。
- AOP代理(AOP Proxy): AOP框架创建的对象,包含通知。 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。
AOP原理
AOP 实现的关键就在于 AOP 框架自动创建的 AOP 代理,AOP 代理则可分为静态代理和动态代理两大类
- 静态代理是指使用 AOP 框架提供的命令进行编译,从而在编译阶段就可生成 AOP 代理类,因此也称为编译时增强;
- 而动态代理则在运行时借助于 JDK 动态代理、CGLIB 等在内存中“临时”生成 AOP 动态代理类,因此也被称为运行时增强。Spring AOP则采用的是动态代理来实现。
2、AOP时序图
3、源码分析(简约版)
3.1 准备工作
首先定义一个Spring AOP的配置文件spring-aop.xml
-
<?xml version=
"1.0" encoding=
"UTF-8"?>
-
<beans xmlns=
"http://www.springframework.org/schema/beans"
-
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
-
xsi:schemaLocation=
"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
-
-
<aop:config>
-
<aop:aspect id=
"TestAspect" ref=
"aspect">
-
<aop:pointcut id=
"pointcut" expression=
"execution(* org.study.spring.aop.*.*(..))"/>
-
<aop:before method=
"doBefore" pointcut-ref=
"pointcut"/>
-
</aop:aspect>
-
</aop:config>
-
-
<bean id=
"aspect"
class=
"org.study.spring.aop.Aspect"/>
-
<bean id=
"test"
class=
"org.study.spring.aop.TestAOP"/>
-
-
</beans>
由于我们只分析JDK动态代理的实现方式,所以需要定义一个接口。
-
public
interface ITestAOP{
-
public void doSomething();
-
}
目标对象实现上面定义的接口。
-
public
class Test implements ITestAOP {
-
public void doSomething() {
-
System.out.println(
"do something");
-
}
-
}
定义Aspect,这里我们以前置通知为例
-
public
class Aspect {
-
public void doBefore(JoinPoint jp) {
-
System.out.println(
"do before");
-
}
-
}
编写程序入口代码,可以直接打断点进行调试。
-
ApplicationContext context =
new ClassPathXmlApplicationContext(
"spring.xml");
-
Test bean = context.getBean(
"test", TestAOP.class);
-
bean.doSomething();
3.2 源码分析
1.进入AbstractAutowireCapableBeanFactory的initializeBean()
从源码中可以看到,AOP其实就是通过后置处理对bean的一种增强,而它用到的是代理技术
-
//初始容器创建的Bean实例对象,为其添加BeanPostProcessor后置处理器
-
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
-
//JDK的安全机制验证权限
-
if (System.getSecurityManager() !=
null) {
-
//实现PrivilegedAction接口的匿名内部类
-
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
-
invokeAwareMethods(beanName, bean);
-
return
null;
-
}, getAccessControlContext());
-
}
-
else {
-
//为Bean实例对象包装相关属性,如名称,类加载器,所属容器等信息
-
invokeAwareMethods(beanName, bean);
-
}
-
-
Object wrappedBean = bean;
-
//对BeanPostProcessor后置处理器的postProcessBeforeInitialization
-
//回调方法的调用,为Bean实例初始化前做一些处理
-
if (mbd ==
null || !mbd.isSynthetic()) {
-
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
-
}
-
-
//调用Bean实例对象初始化的方法,这个初始化方法是在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);
-
}
-
//对BeanPostProcessor后置处理器的postProcessAfterInitialization
-
//回调方法的调用,为Bean实例初始化之后做一些处理
-
if (mbd ==
null || !mbd.isSynthetic()) {
-
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
-
}
-
-
return wrappedBean;
-
}
2. 在applyBeanPostProcessorsAfterInitialization方法上,
按住Ctrl+鼠标左键进入applyBeanPostProcessorsAfterInitialization方法
-
//调用BeanPostProcessor后置处理器实例对象初始化之后的处理方法
-
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
-
throws BeansException {
-
Object result = existingBean;
-
//遍历容器为所创建的Bean添加的所有BeanPostProcessor后置处理器
-
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
-
//调用Bean实例所有的后置处理中的初始化后处理方法,为Bean实例对象在
-
//初始化之后做一些自定义的处理操作
-
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
-
if (current ==
null) {
-
return result;
-
}
-
result = current;
-
}
-
return result;
-
}
3. 在postProcessAfterInitialization方法上,
按住Ctrl+Alt+B选择AbstractAutoProxyCreator进入postProcessAfterInitialization()
-
@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;
-
}
4.在wrapIfNecessary方法上,按住Ctrl+鼠标左键进入自身wrapIfNecessary方法
-
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
-
if (beanName !=
null &&
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;
-
}
-
-
// 获取通知列表
-
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName,
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;
-
}
-
-
this.advisedBeans.put(cacheKey, Boolean.FALSE);
-
return bean;
-
}
从上面我们可以看到,Spring在这里先获取配置好的Advisor信息,然后调用createProxy方法为目标对象创建了代理,接着将创建的代理对象返回。
5. 在getAdvicesAndAdvisorsForBean方法上,按住Ctrl+Alt+B选择AbstractAdvisorAutoProxyCreator的getAdvicesAndAdvisorsForBean
-
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) {
-
List<Advisor> candidateAdvisors = findCandidateAdvisors();
-
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
-
extendAdvisors(eligibleAdvisors);
-
if (!eligibleAdvisors.isEmpty()) {
-
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
-
}
-
return eligibleAdvisors;
-
}
-
-
protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
-
AnnotationAwareOrderComparator.sort(advisors);
-
return advisors;
-
}
-
-
public static void sort(List<?> list) {
-
if (list.size() >
1) {
-
Collections.sort(list, INSTANCE);
-
}
-
}
从上面可以知道,代理前需要先拿到通知的列表(包括前置通知,后置通知,异常通知等等)
6.按住Ctrl+Alt+左方向键返回到第4步的wrapIfNecessary方法,
找到createProxy方法,按住Ctrl+鼠标左键进入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)) {
-
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());
-
}
代理前各种属性操作------
8.直接进入JdkDynamicAopProxy 的 getProxy()方法
-
/**
-
* 获取代理类要实现的接口,除了Advised对象中配置的,还会加上SpringProxy, Advised(opaque=false)
-
* 检查上面得到的接口中有没有定义 equals或者hashcode的接口
-
* 调用Proxy.newProxyInstance创建代理对象
-
*/
-
@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);
-
}
看到这里,大家一定非常的兴奋,Proxy.newProxyInstance(classLoader, proxiedInterfaces, this)不就是反射获取实例对象吗?没错,那么疑问来了,Aop切面是如何织入的呢?
9. 在proxyFactory.getProxy方法上,Ctrl+Alt+B进入ProxyFactory的getProxy方法
-
protected final synchronized AopProxy createAopProxy() {
-
if (!
this.active) {
-
activate();
-
}
-
return getAopProxyFactory().createAopProxy(
this);
-
}
10. 在createAopProxy(this)方法上,按住Ctrl+Alt+B进入DefaultAopProxyFactory的createAopProxy方法
从下面源码可以得出:会根据判断进入不同的代理模式
-
@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);
-
}
-
//cglib动态代理
-
return
new ObjenesisCglibAopProxy(config);
-
}
-
else {
-
return
new JdkDynamicAopProxy(config);
-
}
-
}
11.进入JdkDynamicAopProxy的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()方法,具目标对象未实现此方法
-
if (!
this.equalsDefined && AopUtils.isEqualsMethod(method)) {
-
// The target does not implement the equals(Object) method itself.
-
return equals(args[
0]);
-
}
-
//hashCode()方法,具目标对象未实现此方法
-
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);
-
}
-
//Advised接口或者其父接口中定义的方法,直接反射调用,不应用通知
-
else
if (!
this.advised.opaque && method.getDeclaringClass().isInterface() &&
-
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
-
// Service invocations on ProxyConfig with the proxy config...
-
return AopUtils.invokeJoinpointUsingReflection(
this.advised, method, args);
-
}
-
-
Object retVal;
-
-
if (
this.advised.exposeProxy) {
-
oldProxy = AopContext.setCurrentProxy(proxy);
-
setProxyContext =
true;
-
}
-
//获得目标对象的类
-
target = targetSource.getTarget();
-
Class<?> targetClass = (target !=
null ? target.getClass() :
null);
-
//获取可以应用到此方法上的Interceptor列表
-
List<Object> chain =
this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
-
//如果没有可以应用到此方法的通知(Interceptor),此直接反射调用 method.invoke(target, args)
-
if (chain.isEmpty()) {
-
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
-
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
-
}
-
else {
-
//创建MethodInvocation
-
invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
-
// Proceed to the joinpoint through the interceptor 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())) {
-
// Special case: it returned "this" and the return type of the method
-
// is type-compatible. Note that we can't help if the target sets
-
// a reference to itself in another returned object.
-
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()) {
-
// Must have come from TargetSource.
-
targetSource.releaseTarget(target);
-
}
-
if (setProxyContext) {
-
// Restore old proxy.
-
AopContext.setCurrentProxy(oldProxy);
-
}
-
}
-
}
这里有一个很重要的方法:获取可以应用到此方法上的Interceptor列表
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
- 所以 按住Ctrl+Alt+B****getInterceptorsAndDynamicInterceptionAdvice方法,进入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;
-
}
- 继续进入在advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice方法上,
按住Ctrl+Alt+B进入DefaultAdvisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice方法
-
/**
-
* 从提供的配置实例config中获取advisor列表,遍历处理这些advisor.如果是IntroductionAdvisor,
-
* 则判断此Advisor能否应用到目标类targetClass上.如果是PointcutAdvisor,则判断
-
* 此Advisor能否应用到目标方法method上.将满足条件的Advisor通过AdvisorAdaptor转化成Interceptor列表返回.
-
*/
-
@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.
-
List<Object> interceptorList =
new ArrayList<>(config.getAdvisors().length);
-
Class<?> actualClass = (targetClass !=
null ? targetClass : method.getDeclaringClass());
-
//查看是否包含IntroductionAdvisor
-
boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);
-
//这里实际上注册一系列AdvisorAdapter,用于将Advisor转化成MethodInterceptor
-
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
-
-
for (Advisor advisor : config.getAdvisors()) {
-
if (advisor
instanceof PointcutAdvisor) {
-
// Add it conditionally.
-
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
-
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
-
//这个地方这两个方法的位置可以互换下
-
//将Advisor转化成Interceptor
-
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
-
//检查当前advisor的pointcut是否可以匹配当前方法
-
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;
-
}
上面搞了这么多,就是为了拿到一条将通知封装成MethodInvoation的通知链,为了以下使用责任链模式进行invoke时可以顺序的织入所有的通知。继续搞下去:
12. 返回11步,进入invocation.proceed方法,进入到 ReflectiveMethodInvocation 的proceed() 方法
-
Override
-
@Nullable
-
public Object proceed() throws Throwable {
-
// We start with an index of -1 and increment early.
-
//如果Interceptor执行完了,则执行joinPoint
-
if (
this.currentInterceptorIndex ==
this.interceptorsAndDynamicMethodMatchers.size() -
1) {
-
return invokeJoinpoint();
-
}
-
-
Object interceptorOrInterceptionAdvice =
-
this.interceptorsAndDynamicMethodMatchers.get(++
this.currentInterceptorIndex);
-
//如果要动态匹配joinPoint
-
if (interceptorOrInterceptionAdvice
instanceof InterceptorAndDynamicMethodMatcher) {
-
// Evaluate dynamic method matcher here: static part will already have
-
// been evaluated and found to match.
-
InterceptorAndDynamicMethodMatcher dm =
-
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
-
//动态匹配:运行时参数是否满足匹配条件
-
if (dm.methodMatcher.matches(
this.method,
this.targetClass,
this.arguments)) {
-
return dm.interceptor.invoke(
this);
-
}
-
else {
-
// Dynamic matching failed.
-
// Skip this interceptor and invoke the next in the chain.
-
//动态匹配失败时,略过当前Intercetpor,调用下一个Interceptor
-
return proceed();
-
}
-
}
-
else {
-
// It's an interceptor, so we just invoke it: The pointcut will have
-
// been evaluated statically before this object was constructed.
-
//执行当前Intercetpor
-
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(
this);
-
}
-
}
13.进入dm.interceptor.invoke(this);按住Ctrl+Alt+B选择选择MethodBeforeAdviceInterceptor的invoke方法
-
@Override
-
public Object invoke(MethodInvocation mi) throws Throwable {
-
-
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
-
-
return mi.proceed();
-
-
}
14. 在.invoke(this)方法上,按住Ctrl+Alt+B选择AfterReturningAdviceInterceptor的invoke方法
-
@Override
-
public Object invoke(MethodInvocation mi) throws Throwable {
-
Object retVal = mi.proceed();
-
this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
-
return retVal;
-
}
从12、13、14可以知道Spring AOP多个通知的执行顺序应该像一个同心圆,
从12、13、14可以知道Spring AOP多个通知的执行顺序应该像一个同心圆:
spring aop就是一个同心圆,要执行的方法为圆心,最外层的order最小。从最外层按照AOP1、AOP2的顺序依次执行doAround方法,doBefore方法。然后执行method方法,最后按照AOP2、AOP1的顺序依次执行doAfter、doAfterReturn方法。也就是说对多个AOP来说,先before的,一定后after。
如果我们要在同一个方法事务提交后执行自己的AOP,那么把事务的AOP order设置为2,自己的AOP order设置为1,然后在doAfterReturn里边处理自己的业务逻辑。
转载:https://blog.csdn.net/qqq3117004957/article/details/106087315