zoukankan      html  css  js  c++  java
  • 【源码】按照自己的思路研究Spring AOP源码 ①

    一个例子

    // 定义一个切面
    package cn.eagle.li.source.aspect;
    
    @Component
    @Aspect
    public class ServiceAspect {
    	@Pointcut("execution(* cn.eagle.li.source.service.*.*(..))")
    	public void pointCut() {
    	}
    
    	@Before("pointCut()")
    	public void methodBefore() {
    		System.out.println("===== Before =====");
    	}
    
    	@After("pointCut()")
    	public void methodAfter() {
    		System.out.println("===== After =====");
    	}
    
    	@AfterReturning("pointCut()")
    	public void methodReturn() {
    		System.out.println("===== AfterReturning =====");
    	}
    
    	@Around("pointCut()")
    	public void doAround(ProceedingJoinPoint pjp) throws Throwable {
    		System.out.println("===== Around before =====");
    		pjp.proceed();
    		System.out.println("===== Around after =====");
    	}
    }
    
    // 一个接口
    package cn.eagle.li.source.service;
    public interface IService {
    	void doService();
    }
    
    // 一个实现类
    package cn.eagle.li.source.service.impl;
    @Service
    public class ServiceImpl implements IService {
    	@Override
    	public void doService() {
    		System.out.println("do service");
    	}
    }
    
    // Main类
    @Configuration
    @ComponentScan(basePackages = {"cn.eagle.li.source"})
    @EnableAspectJAutoProxy(exposeProxy = true)
    public class Main {
    	public static void main(String[] args) {
    		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Main.class);
    		IService service = context.getBean(IService.class);
    		service.doService();
    	}
    }
    

    执行结果如下:

    ===== Around before =====
    ===== Before =====
    do service
    ===== AfterReturning =====
    ===== After =====
    ===== Around after =====
    

    从@EnableAspectJAutoProxy注解入手

    下面是EnableAspectJAutoProxy注解类内容

    @Import(AspectJAutoProxyRegistrar.class)
    public @interface EnableAspectJAutoProxy {
            //代理的实现方式,true为CGLIB, false为JDK,默认false
    	boolean proxyTargetClass() default false;
      
     	// 要不要暴露代理对象
    	boolean exposeProxy() default false;
    }
    

    除了上面两个参数比较重要外,它还有一个Import注解,在Spring中,只要一种注解组合了另一种注解,它就具有该注解的功能,也就是这个注解拥有了@Import注解的功能。

    @Import(AspectJAutoProxyRegistrar.class)
    

    我们看到它import了AspectJAutoProxyRegistrar这个类,我们下面再看看这个类的内容,发现它主要的工作就是注册一个name为:

    org.springframework.aop.config.internalAutoProxyCreator,类为AnnotationAwareAspectJAutoProxyCreator的BeanDefinition。

    class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    	@Override
    	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    		AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
                 // ......
    	}
    }
    
    AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
    
    public abstract class AopConfigUtils {
    	@Nullable
    	public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
    			BeanDefinitionRegistry registry, @Nullable Object source) {
    		return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
    	}
    }
    
    public abstract class AopConfigUtils {
      
      	public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
    			"org.springframework.aop.config.internalAutoProxyCreator";
      
            @Nullable
    	private static BeanDefinition registerOrEscalateApcAsRequired(
    			Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
    
    		Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    
    		if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
    			BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
    			if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
    				int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
    				int requiredPriority = findPriorityForClass(cls);
    				if (currentPriority < requiredPriority) {
    					apcDefinition.setBeanClassName(cls.getName());
    				}
    			}
    			return null;
    		}
    
    		RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
    		beanDefinition.setSource(source);
    		beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
    		beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        
                    // 注册 BeanDefinition
                    // AUTO_PROXY_CREATOR_BEAN_NAME = org.springframework.aop.config.internalAutoProxyCreator
                    // beanDefinition = AnnotationAwareAspectJAutoProxyCreator.class
    		registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
    		return beanDefinition;
    	}
    }
    

    此时有一个疑问:那就是什么时候调用这个方法来加载AnnotationAwareAspectJAutoProxyCreator这个类的BeanDefinition呢?

    从下面这张图可以看到是在容器进行刷新的时候,调用invokeBeanFactoryPostProcessors这个方法来进行执行的,具体的执行过程就不展开了。

    	public void refresh() throws BeansException, IllegalStateException {
    		synchronized (this.startupShutdownMonitor) {
    			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
    
    			// Prepare this context for refreshing.
    			prepareRefresh();
    
    			// Tell the subclass to refresh the internal bean factory.
    			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
    			// Prepare the bean factory for use in this context.
    			prepareBeanFactory(beanFactory);
    
    			try {
    				// Allows post-processing of the bean factory in context subclasses.
    				postProcessBeanFactory(beanFactory);
    
    				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
    				// Invoke factory processors registered as beans in the context.
                                    // 在这里把beandefinition加载
    				invokeBeanFactoryPostProcessors(beanFactory);
                                    // ......
          }
        }
    

    现在这个类的BeanDefinition准备好了,那什么时候会创建AnnotationAwareAspectJAutoProxyCreator这个实例,然后加载到容器里呢?

    我们看一下这个类的继承关系,发现它是一个实现了BeanPostProcessor接口,也就是说它是一个后置处理器。在refresh()方法中有一个步骤是专门用来注册后置处理器的,也就是registerBeanPostProcessors()这个方法。

    	public void refresh() throws BeansException, IllegalStateException {
    		synchronized (this.startupShutdownMonitor) {
    			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
    
    			// Prepare this context for refreshing.
    			prepareRefresh();
    
    			// Tell the subclass to refresh the internal bean factory.
    			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
    			// Prepare the bean factory for use in this context.
    			prepareBeanFactory(beanFactory);
    
    			try {
    				// Allows post-processing of the bean factory in context subclasses.
    				postProcessBeanFactory(beanFactory);
    
    				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
    				// Invoke factory processors registered as beans in the context.
    				invokeBeanFactoryPostProcessors(beanFactory);
            
                                    // Register bean processors that intercept bean creation.
                                    // 在这里把BeanPostProcessor加载到容器中
    				registerBeanPostProcessors(beanFactory);
                                    // ......
          }
        }
    

    在调试的过程中,发现在PostProcessorRegistrationDelegate这个类下的registerBeanPostProcessors()这个方法下会创建AnnotationAwareAspectJAutoProxyCreator,并把它注册到容器中,如下图。

    PostProcessorRegistrationDelegate类下
    public static void registerBeanPostProcessors(
    			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
    }
    

    经过上面的一个讨论,我总结了一下它的一些关键触发路径,如下:

    refresh() -> invokeBeanFactoryPostProcessors() -> AspectJAutoProxyRegistrar.registerBeanDefinitions()
    name:"org.springframework.aop.config.internalAutoProxyCreator" beanDefinition:AnnotationAwareAspectJAutoProxyCreator -> registerBeanPostProcessors() -> 创建类实例并加载到容器中

    什么时候会创建代理对象?

    容器里有了AnnotationAwareAspectJAutoProxyCreator这个实例,它具体有什么用呢,它什么时候会生成代理对象呢?

    protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    		if (System.getSecurityManager() != null) {
    			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
    				invokeAwareMethods(beanName, bean);
    				return null;
    			}, getAccessControlContext());
    		}
    		else {
    			invokeAwareMethods(beanName, bean);
    		}
    
    		Object wrappedBean = bean;
    		if (mbd == null || !mbd.isSynthetic()) {
    			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    		}
    
    		try {
    			invokeInitMethods(beanName, wrappedBean, mbd);
    		}
    		catch (Throwable ex) {
    			throw new BeanCreationException(
    					(mbd != null ? mbd.getResourceDescription() : null),
    					beanName, "Invocation of init method failed", ex);
    		}
    		if (mbd == null || !mbd.isSynthetic()) {
    			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    		}
    
    		return wrappedBean;
    	}
    

    大家都知道,Spring在创建一个类实例后,会对这个类进行初始化,然后会执行一系列的后置处理器,就在applyBeanPostProcessorsAfterInitialization()这个方法里面。

    wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    

    它会依次地去调用每一个后置处理器,当然也包括了我们刚刚注册的AnnotationAwareAspectJAutoProxyCreator这个后置处理器,具体的执行方法就是postProcessAfterInitialization();

    	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;
    	}
    

    我们来看一下AnnotationAwareAspectJAutoProxyCreator类的postProcessAfterInitialization这个方法,发现如果没有包装过,就把它包装一下。

    	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    		if (bean != null) {
    			Object cacheKey = getCacheKey(bean.getClass(), beanName);
    			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
    				return wrapIfNecessary(bean, beanName, cacheKey);
    			}
    		}
    		return bean;
    	}
    
    return wrapIfNecessary(bean, beanName, cacheKey);
    

    我们看到它会获取一些适配这个类的Advices和Advisors,如果不为null,就创建一个代理对象。

    	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;
    		}
    
    		// Create proxy if we have advice.
    		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;
    		}
    
    		this.advisedBeans.put(cacheKey, Boolean.FALSE);
    		return bean;
    	}
    
    Object proxy = createProxy(
    					bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
    
    protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
    			@Nullable Object[] specificInterceptors, TargetSource targetSource) {
                    // ......
    		return proxyFactory.getProxy(targetClassLoader);
    	}
    
    	public Object getProxy(@Nullable ClassLoader classLoader) {
    		return createAopProxy().getProxy(classLoader);
    	}
    

    Spring AOP有两种代理类,Jdk代理类和Cglib代理类,具体要看proxyTargetClass这个配置项和这个类是否实现了接口。

    	public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
    		if (!NativeDetector.inNativeImage() &&
    				(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);
    		}
    	}
    

    我们以JDK动态代理为例,发现它就是用Java的api进行创建的,代理类JdkDynamicAopProxy这个类

    final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
    	@Override
    	public Object getProxy(@Nullable ClassLoader classLoader) {
    		if (logger.isTraceEnabled()) {
    			logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource());
    		}
    		return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
    	}
    }
    

    到现在,我们知道,当创建一个bean实例后,在它初始化后,会调用每个后置处理器的初始化后的方法

    当调用AOP的后置处理器的时候,会根据有没有适配它的advice和advitor来创建代理类

    创建代理类的时候,有两种选择,一是JDK代理类,二是Cglib代理类

    如果proxyTargetClass为true或者这个类没有实现接口的话,就选择Cglib代理类,否则选择JDK代理类。

    方法执行时怎么实现拦截的?

    现在我们获取一个bean时,获取的就是它的代理类,那在调用其方法时,那些符合的通知是怎么一步步执行的呢?

    我们以JDK代理类为例,我们都知道,在JDK动态代理中,实际执行的时候是执行的代理类的invoke方法,所以看一下它的具体内容:

    final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
      
    	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    		Object oldProxy = null;
    		boolean setProxyContext = false;
    
    		TargetSource targetSource = this.advised.targetSource;
    		Object target = null;
    
    		try {
    			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);
    			}
    			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;
    			
                            // 如果设置了exposeProxy参数
                            // 这里暴露了代理对象
                            // AopContext.currentProxy() 获得
    			if (this.advised.exposeProxy) {
    				// Make invocation available if necessary.
    				oldProxy = AopContext.setCurrentProxy(proxy);
    				setProxyContext = true;
    			}
    
    			// Get as late as possible to minimize the time we "own" the target,
    			// in case it comes from a pool.
    			target = targetSource.getTarget();
    			Class<?> targetClass = (target != null ? target.getClass() : null);
    
    			// Get the interception chain for this method.
    			List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
    
    			// Check whether we have any advice. If we don't, we can fallback on direct
    			// reflective invocation of the target, and avoid creating a MethodInvocation.
    			if (chain.isEmpty()) {
    				// We can skip creating a MethodInvocation: just invoke the target directly
    				// Note that the final invoker must be an InvokerInterceptor so we know it does
    				// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
    				Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
    				retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
    			}
    			else {
    				// We need to create a method invocation...
    				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);
    			}
    		}
    	}
    }
    

    总的看下来,主要关心以下内容:

    // 如果设置了exposeProxy参数
    // 这里暴露了代理对象
    // AopContext.currentProxy() 获得
    if (this.advised.exposeProxy) {
      // Make invocation available if necessary.
      // 这里是用ThreadLocal实现的
      oldProxy = AopContext.setCurrentProxy(proxy);
      setProxyContext = true;
    }
    
    // 创建拦截器链
    List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
    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);
      retVal = invocation.proceed();
    }
    

    这个执行链就是一个数组,然后一个一个向下执行,根据之前的例子,这个生成的执行链如下:

    AspectJAroundAdvice MethodBeforeAdviceInterceptor AspectJAfterAdvice AspectJAfterReturningAdvice
    

    最终包装成ReflectiveMethodInvocation这个类,调用其proceed()方法执行,如下:

    public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable {
    
    	public Object proceed() throws Throwable {
    		// 拦截器链中的最后一个拦截器执行完
    		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
                            // 执行目标方法
    			return invokeJoinpoint();
    		}
    
                    // 每次执行新的拦截器,下标+1
    		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.
                            // 上面的例子每次都会这个方法
    			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
    		}
    	}
    }
    
    public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor, Serializable {
    	public Object invoke(MethodInvocation mi) throws Throwable {
    		if (!(mi instanceof ProxyMethodInvocation)) {
    			throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
    		}
    		ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
    		ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi);
    		JoinPointMatch jpm = getJoinPointMatch(pmi);
                    // 调用通知的方法
    		return invokeAdviceMethod(pjp, jpm, null, null);
    	}
    }
    
    public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
    	public Object invoke(MethodInvocation mi) throws Throwable {
                    // 调用通知方法
    		this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
                    // 下一个拦截器
    		return mi.proceed();
    	}
    }
    
    public class AspectJAfterAdvice extends AbstractAspectJAdvice
    		implements MethodInterceptor, AfterAdvice, Serializable {
    	public Object invoke(MethodInvocation mi) throws Throwable {
    		try {
                            // 下一个拦截器
    			return mi.proceed();
    		}
    		finally {
                            // 调用通知方法
    			invokeAdviceMethod(getJoinPointMatch(), null, null);
    		}
    	}
    }
    
    public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable {
    		implements MethodInterceptor, AfterAdvice, Serializable {
    	public Object invoke(MethodInvocation mi) throws Throwable {
                    // 下一个拦截器
    		Object retVal = mi.proceed();
                    // 调用通知方法
    		this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
    		return retVal;
    	}
    }
    

    ===== Around before =====
    ===== Before =====
    do service
    ===== AfterReturning =====
    ===== After =====
    ===== Around after =====
    

    从上面可以看出,代理类执行的时候,就是将符合的advice排序得到一个数组,然后依次的进行执行。

    总结

    1. 从EnableAspectJAutoProxy注解入手,Spring会注册AnnotationAwareAspectJAutoProxyCreator这个类
    2. AnnotationAwareAspectJAutoProxyCreator是个BeanPostProcessor,在初始化后,会调用后置处理器,生成代理对象
    3. 在类执行方法时,会根据通知生成一个拦截器数组,然后将所有相关的通知一个一个的执行

    问题

    我们看到上面的通知顺序是: AspectJAroundAdvice MethodBeforeAdviceInterceptor AspectJAfterAdvice AspectJAfterReturningAdvice
    但是网上有好多文章都说的顺序是这样的:AspectJAfterReturningAdvice AspectJAfterAdvice AspectJAroundAdvice MethodBeforeAdviceInterceptor
    不同的执行顺序会对你的程序会有不同的影响
    后续将会写一篇文章专门介绍这个原因

    参考

    Spring Framework Documentation

    Spring AOP

    SpringAop源码分析(基于注解) 一

    SpringAop源码分析(基于注解) 三

    SpringAop源码分析(基于注解)四

    Spring AOP执行顺序

  • 相关阅读:
    使用django开发一个web项目初试
    关于github一些比较重要的命令
    删除github repository的方法
    Node、npm与Vue配置与问题记录
    [记忆]5月第二周
    git am patch冲突解决步骤
    git丢弃本地修改的几种方式
    Log4j 2.X 漏洞解决
    Maven依赖范围Scope及传递性依赖
    Mysql创建事件定时任务
  • 原文地址:https://www.cnblogs.com/eaglelihh/p/14627453.html
Copyright © 2011-2022 走看看