• Spring源码分析之AOP


    AOP是什么

    面向切面的程序设计(Aspect-oriented programming,AOP,又译作面向方面的程序设计剖面导向程序设计),是计算机科学中的一种程序设计思想,旨在将横切关注点与业务主体进行进一步分离,以提高程序代码的模块化程度。通过在现有代码基础上增加额外的通知(Advice)机制,能够对被声明为“切点(Pointcut)”的代码块进行统一管理与装饰。

    怎么在Spring里使用AOP

    Spring里,AOP通过EnableAspectJAutoProxy注解开启。默认情况下,Spring会通过AopAutoConfiguration自动引入这个注解

    @Configuration(proxyBeanMethods = false)
    @ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
    public class AopAutoConfiguration {
    
    	@Configuration(proxyBeanMethods = false)
    	@ConditionalOnClass(Advice.class)
    	static class AspectJAutoProxyingConfiguration {
    
    		@Configuration(proxyBeanMethods = false)
    		@EnableAspectJAutoProxy(proxyTargetClass = false)
    		@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false")
    		static class JdkDynamicAutoProxyConfiguration {
    
    		}
    
    		@Configuration(proxyBeanMethods = false)
    		@EnableAspectJAutoProxy(proxyTargetClass = true)
    		@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true",
    				matchIfMissing = true)
    		static class CglibAutoProxyConfiguration {
    
    		}
    
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    可以看到,如果我们不主动设置spring.aop.auto=false。那么Spring默认会启用AOP。接下来,我们可以通过在类上标注Aspect即可使用AOP

    package org.example.aspect;
    
    @Aspect
    @Component
    public class SampleAspect {
    
        @Pointcut("execution(* org.example.xxx.*.*(..))")
        private void executionPointcut() {
    
        }
    
        @After(value = "executionPointcut()")
        public void doAfter() {
            
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    源码分析

    1. AOP初始化

    1.1 初始化AspectJAutoProxyRegistrar

    EnableAspectJAutoProxy通过Import注解引入了AspectJAutoProxyRegistrar

    @Import(AspectJAutoProxyRegistrar.class)
    public @interface EnableAspectJAutoProxy {
    }
    
    • 1
    • 2
    • 3

    AspectJAutoProxyRegistrar实现了ImportBeanDefinitionRegistrarSpring在初始化AopAutoConfiguration时把所有通过Import注解引入的ImportBeanDefinitionRegistrar实现类拿出来进行初始化,并调用其registerBeanDefinitions函数

    class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    
    	@Override
    	public void registerBeanDefinitions(
    			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    
    		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    1.2 初始化AnnotationAwareAspectJAutoProxyCreator

    AspectJAutoProxyRegistrar 则在registerBeanDefinitions注册了一个AnnotationAwareAspectJAutoProxyCreatorBeanDefinition

    public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
    			BeanDefinitionRegistry registry, @Nullable Object source) {
    
    		return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5

    AnnotationAwareAspectJAutoProxyCreator实现了BeanPostProcessorSpring会在初始化普通Bean之前初始化所有BeanPostProcessor

    public abstract class AbstractApplicationContext extends DefaultResourceLoader
    		implements ConfigurableApplicationContext {
    
    		public void refresh() throws BeansException, IllegalStateException {
    					// 初始化BeanProcessor来拦截Bean的创建
    					registerBeanPostProcessors(beanFactory);
    	
    					// 初始化所有剩下的非懒加载的Bean,比如我们写的Service
    					finishBeanFactoryInitialization(beanFactory);
    		}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    1.3 初始化切面方法跟切点

    另外,AnnotationAwareAspectJAutoProxyCreator实现了InstantiationAwareBeanPostProcessorSpring 会在Bean创建时调用其postProcessBeforeInstantiation方法对Bean进行处理。

    在第一次调用该方法时,AnnotationAwareAspectJAutoProxyCreator会初始化切面

    public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
    		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
    	
    	@Override
    	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
    		Object cacheKey = getCacheKey(beanClass, beanName);
    
    		if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
    			//判断当前BeanName对应的Bean是否应该被代理
    			//并将判断结果保存下来,避免后续的后处理方法重复计算
    			//在第一次判断时,会在shouldSkip里扫描所有Bean进行切面初始化
    			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
    				this.advisedBeans.put(cacheKey, Boolean.FALSE);
    				return null;
    			}
    		}
    
    		//如果为AbstractAutoProxyCreator注入了自定义的TargetSourceCreator
    		//则通过TargetSourceCreator创建的Bean都被被AOP代理
    		//TargetSourceCreator默认为空
    		TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
    		if (targetSource != null) {
    			if (StringUtils.hasLength(beanName)) {
    				this.targetSourcedBeans.add(beanName);
    			}
    			Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
    			Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
    			this.proxyTypes.put(cacheKey, proxy.getClass());
    			return proxy;
    		}
    
    		return null;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    切面初始化

    public class BeanFactoryAspectJAdvisorsBuilder {
    
    		public List<Advisor> buildAspectJAdvisors() {
    				List<String> aspectNames = this.aspectBeanNames;
    				
    				//如果还未进行初始化
    				if (aspectNames == null) {
    					synchronized (this) {
    						aspectNames = this.aspectBeanNames;
    						if (aspectNames == null) {
    							List<Advisor> advisors = new ArrayList<>();
    							aspectNames = new ArrayList<>();
    							
    							//拿到容器里所有的beanName
    							String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
    									this.beanFactory, Object.class, true, false);
    							for (String beanName : beanNames) {
    
    								Class<?> beanType = this.beanFactory.getType(beanName, false);
    								
    								//判断类上是否标注Aspect,以及判断该class是否已经被代码式的Aspectj处理过
    								if (this.advisorFactory.isAspect(beanType)) {
    									aspectNames.add(beanName);
    									AspectMetadata amd = new AspectMetadata(beanType, beanName);
    									MetadataAwareAspectInstanceFactory factory =
    												new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
    
    										//从类中拿到所有带有Before、Around等注解的方法,
    										//将这些方法包装成MethodInterceptor放入Advisor,MethodInterceptor#invoke为增强方法的调用入口
    										//将Advisor排好顺序组成List返回
    										List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
    
    										this.advisorsCache.put(beanName, classAdvisors);
    										advisors.addAll(classAdvisors);
    								}
    							}
    							this.aspectBeanNames = aspectNames;
    							return advisors;
    						}
    					}
    				}
    			}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    Advisor排序

    public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
    		private static final Comparator<Method> adviceMethodComparator;
    	
    		static {
    			
    			Comparator<Method> adviceKindComparator = new ConvertingComparator<>(
    					//按照注解顺序设置方法对应的advisor的顺序
    					//在AspectJAfterAdvice里,会先将请求继续向拦截器链后传播,
    					//对增强方法的调用是在后面的finnaly块里。所以这里的After顺序即使在AfterReturning前面也没关系
    					//另外,因为在finnly块里触发,所以即使后续的调用抛出了未捕获的异常,After指定的增强方法也会被执行
    					new InstanceComparator<>(
    							Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),
    	
    					(Converter<Method, Annotation>) method -> {
    							//如果方法上没有标注上面的几个注解,则返回null,null会排在最后
    						AspectJAnnotation<?> ann = AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
    						return (ann != null ? ann.getAnnotation() : null);
    					});
    			Comparator<Method> methodNameComparator = new ConvertingComparator<>(Method::getName);
    			adviceMethodComparator = adviceKindComparator.thenComparing(methodNameComparator);
    		}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    判断method是否属于切面方法

    	
    public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
    		public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
    				int declarationOrderInAspect, String aspectName) {
    	
    				//获取切点信息,如果candidateAdviceMethod不是切面方法,则返回null
    				AspectJExpressionPointcut expressionPointcut = getPointcut(
    						candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
    				if (expressionPointcut == null) {
    					return null;
    				}
    		
    				return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
    						this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
    		}	
    
    		private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
    				//在方法上查找Aspectj的相关注解(Around、After等)
    				AspectJAnnotation<?> aspectJAnnotation =
    						AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
    				if (aspectJAnnotation == null) {
    					return null;
    				}
    		
    				...
    		}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    2. 生成代理对象

    AbstractAutoProxyCreator实现了BeanPostProcessor,在创建Bean时,Spring会调用AbstractAutoProxyCreator#postProcessAfterInitializationBean进行处理

    public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
    		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
    	
    		@Override
    		public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    			if (bean != null) {
    				Object cacheKey = getCacheKey(bean.getClass(), beanName);
    				if (this.earlyProxyReferences.remove(cacheKey) != bean) {
    					//对bean进行包装,返回代理bean
    					return wrapIfNecessary(bean, beanName, cacheKey);
    				}
    			}
    			return bean;
    		}
    
    		protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    				//如果bean有TargetSourceCreator创建,说明已经被代理过了,直接返回
    				if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
    					return bean;
    				}
    				//拿出缓存的检测的结果进行判断
    				if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
    					return bean;
    				}
    				//初步判断bean是否可以被代理
    				if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
    					this.advisedBeans.put(cacheKey, Boolean.FALSE);
    					return bean;
    				}
    		
    				//根据切点Point的表达式获得符合当前bean的所有advisor
    				//如果当前bean不在切点的指向中,则返回DO_NOT_PROXY
    				Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    				if (specificInterceptors != DO_NOT_PROXY) {
    					this.advisedBeans.put(cacheKey, Boolean.TRUE);
    					//创建代理对象,将所有advisor包装成DynamicAdvisedInterceptor,
    					//其intercept方法为所有增强方法的统一入口,这个类来自Spring
    					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;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    选择代理对象的创建方式

    public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {	
    		@Override
    		public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    			if (!NativeDetector.inNativeImage() &&
    					(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
    				Class<?> targetClass = config.getTargetClass();
    				
    				//如果targetClass是接口类型或者是通过Proxy.getProxyClass生成的或者类名里包含$$Lambda
    				//则使用JDK动态代理
    				if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
    					return new JdkDynamicAopProxy(config);
    				}
    				//使用cglib,ASM修改字节码的方式生产代理类
    				return new ObjenesisCglibAopProxy(config);
    			}
    			else {
    				return new JdkDynamicAopProxy(config);
    			}
    		}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    3. 访问代理对象

    DispatcherServlet 找到对应的实例跟方法后通过反射进行调用(前面Spring Mvc博文里已分析过),此时会遍历代理对象上的所有MethodInterceptor,

    public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {
    
    		public Object proceed() throws Throwable {
    			//如果拦截器遍历完了,则调用目标方法
    			if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
    				return invokeJoinpoint();
    			}
    	
    			//遍历所有增强器MethodInterceptor,
    			//遍历方式是在MethodInterceptor里调用MethodInvocation#proceed
    			//每次进入该方法,都会使currentInterceptorIndex增加1,从而达成遍历
    			Object interceptorOrInterceptionAdvice =
    					this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    			
    			//调用MethodInterceptor#invoke
    			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    		}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    增强方法实际执行的顺序图

    在这里插入图片描述

    接下来看看每个增强注解对应的MethodInterceptor处理类是怎么进行请求处理与传递的

    1. AspectJAroundAdvice

    public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor, Serializable {
    
    	@Override
    	@Nullable
    	public Object invoke(MethodInvocation mi) throws Throwable {
    		...
    		ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
    		ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
    		JoinPointMatch jpm = getJoinPointMatch(pmi);
    		//调用Around对应的增强方法,并将mi传如增强方法
    		//mi持有了所有的拦截/增强器信息,通过Joinpoint#proceed实现请求的传递
    		//所以,around增强方法里需要注意接收Joinpont的实例并调用其proceed方法
    		return invokeAdviceMethod(pjp, jpm, null, null);
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    2. MethodBeforeAdviceInterceptor

    public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
    
    	private final MethodBeforeAdvice advice;
    
    	public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
    		Assert.notNull(advice, "Advice must not be null");
    		this.advice = advice;
    	}
    
    	@Override
    	@Nullable
    	public Object invoke(MethodInvocation mi) throws Throwable {
    		//调用before增强方法
    		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
    		//向后传递
    		return mi.proceed();
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    3. AspectJAfterAdvice

    public class AspectJAfterAdvice extends AbstractAspectJAdvice
    		implements MethodInterceptor, AfterAdvice, Serializable {
    
    		public AspectJAfterAdvice(
    				Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
    	
    			super(aspectJBeforeAdviceMethod, pointcut, aif);
    		}
    	
    	
    		@Override
    		@Nullable
    		public Object invoke(MethodInvocation mi) throws Throwable {
    			try {
    				//先向后传递
    				return mi.proceed();
    			}
    			finally {
    				//执行After方法
    				invokeAdviceMethod(getJoinPointMatch(), null, null);
    			}
    		}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    4. AfterReturningAdviceInterceptor

    public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {
    
    	private final AfterReturningAdvice advice;
    
    	public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) {
    		Assert.notNull(advice, "Advice must not be null");
    		this.advice = advice;
    	}
    
    	@Override
    	@Nullable
    	public Object invoke(MethodInvocation mi) throws Throwable {
    
    		//向后传递
    		Object retVal = mi.proceed();
    		//调用AfterReturning方法
    		this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
    		return retVal;
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    5. AspectJAfterThrowingAdvice

    public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice
    		implements MethodInterceptor, AfterAdvice, Serializable {
    
    		public AspectJAfterThrowingAdvice(
    				Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) {
    	
    			super(aspectJBeforeAdviceMethod, pointcut, aif);
    		}
    	
    		@Override
    		@Nullable
    		public Object invoke(MethodInvocation mi) throws Throwable {
    			try {
    				//向后传递
    				return mi.proceed();
    			}
    			catch (Throwable ex) {
    				//判断增强器上定义的异常类型是否匹配
    				if (shouldInvokeOnThrowing(ex)) {
    					//调用AfterThrowing方法
    					invokeAdviceMethod(getJoinPointMatch(), null, ex);
    				}
    				throw ex;
    			}
    		}
    	
    		/**
    		 * In AspectJ semantics, after throwing advice that specifies a throwing clause
    		 * is only invoked if the thrown exception is a subtype of the given throwing type.
    		 */
    		private boolean shouldInvokeOnThrowing(Throwable ex) {
    			return getDiscoveredThrowingType().isAssignableFrom(ex.getClass());
    		}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    6. ExposeInvocationInterceptor

    public final class ExposeInvocationInterceptor implements MethodInterceptor, PriorityOrdered, Serializable {
    	
    		private static final ThreadLocal<MethodInvocation> invocation =
    					new NamedThreadLocal<>("Current AOP method invocation");
    
    		@Override
    		@Nullable
    		public Object invoke(MethodInvocation mi) throws Throwable {
    			MethodInvocation oldInvocation = invocation.get();
    			//将MethodInvocation绑定到当前线程的本地变量里,
    			//从而实现在其他地方访问MethodInvocation
    			//但不建议这样做,因为AOP对于被代理对象来说应该是无感知的,不应该产生这种依赖
    			invocation.set(mi);
    			try {
    				return mi.proceed();
    			}
    			finally {
    				invocation.set(oldInvocation);
    			}
    		}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
  • 相关阅读:
    【零基础学Java】第二十篇 包装类3(Math,Arrays,System,BigInteger,BigDecimal,日期)
    Jquery 将 JSON 列表的 某个属性值,添加到数组中,并判断一个值,在不在数据中
    百位上的数字(蓝桥杯真题)
    一种多媒体框架中的零buffer拷贝实现机制
    自举电容充电回路分析
    excel表格乱码怎么解决呢?
    USB PD v1.0快速充电通信原理
    如何在 Windows 10/11 上编辑 PDF [4 种简单方法]
    测试用例:四步测试设计法
    【干货分享】2022软件测试面试题汇总
  • 原文地址:https://blog.csdn.net/scientificCommunity/article/details/127574946