Spring AOP 创建代理对象源码分析

1. SpringBoot 中代理对象的创建者

Spring 是基于动态代理实现的 aop,其核心在于代理类增强目标类的功能。这样对于每一个目标类,如何创建其代理对象就极为关键。从源码来看,Spring 中代理对象的创建都离不开AnnotationAwareAspectJAutoProxyCreator,这个类实现了 BeanPostProcessor接口,会在每个bean实例创建时检查该bean是否需要创建代理,需要的话就创建相应的代理

基于 SpringBoot 的自动配置机制,在注解 @EnableAspectJAutoProxy 的定义中会通过 @Import(AspectJAutoProxyRegistrar.class) 将注册类引入,而在 AspectJAutoProxyRegistrar 的注册 bean 定义方法中会通过代码AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary() 最终将 AnnotationAwareAspectJAutoProxyCreator 注册到 bean 工厂中

AnnotationAwareAspectJAutoProxyCreator 的继承结构如下:

在这里插入图片描述

2. 代理对象创建流程

在这里插入图片描述

2.1 代理对象创建者的注册

  1. SpringBoot 启动过程中会将各个自动配置类加载进容器,其中就包括了 Aop 的自动配置类 AopAutoConfiguration。在该类会根据配置属性spring.aop.auto来决定是否启用自动代理,一般默认为启用。另外也会启动注解 @EnableAspectJAutoProxy 来决定代理的实现方式

    @Configuration
    @ConditionalOnClass({ EnableAspectJAutoProxy.class, Aspect.class, Advice.class,
     	AnnotatedElement.class })
    @ConditionalOnProperty(prefix = "spring.aop", name = "auto", havingValue = "true", matchIfMissing = true)
    public class AopAutoConfiguration {
    
     @Configuration
     @EnableAspectJAutoProxy(proxyTargetClass = false)
     @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false)
     public static class JdkDynamicAutoProxyConfiguration {
    
     }
    
     @Configuration
     @EnableAspectJAutoProxy(proxyTargetClass = true)
     @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)
     public static class CglibAutoProxyConfiguration {
    
     }
    }
    
  2. @EnableAspectJAutoProxy 通过 @Import(AspectJAutoProxyRegistrar.class) 引入了注册类 AspectJAutoProxyRegistrar

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(AspectJAutoProxyRegistrar.class)
    public @interface EnableAspectJAutoProxy {
        boolean proxyTargetClass() default false;
        boolean exposeProxy() default false;
    }
    
  3. AspectJAutoProxyRegistrar 实现了接口 ImportBeanDefinitionRegistrar , 在框架启动过程中会回调其实现的接口方法 registerBeanDefinitions(),将相关 bean 注册到容器中,这个过程实际是由 AopConfigUtils 实现

    @Override
     public void registerBeanDefinitions(
     		AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    
     	AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
    
     	AnnotationAttributes enableAspectJAutoProxy =
     			AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
     	if (enableAspectJAutoProxy != null) {
     		if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
     			AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
     		}
     		if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
     			AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
     		}
     	}
     }
    
  4. AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary()最终调用到其内部方法 registerAspectJAnnotationAutoProxyCreatorIfNecessary(),将AnnotationAwareAspectJAutoProxyCreator bean 定义注册到了 bean 工厂中

    @Nullable
     public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
     		BeanDefinitionRegistry registry, @Nullable Object source) {
    
     	return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
     }
    

2.2 代理对象创建的入口

  1. 容器启动的过程中,会在环境准备完成的时候进行 bean 的创建工作。这部分可参考 Spring 启动流程源码解析,在刷新容器的时候 AbstractApplicationContext#refresh() 方法被调用,该方法会调用到 AbstractApplicationContext#registerBeanPostProcessors()将所有实现了BeanPostProcessor接口的类从 bean 工厂注册到容器中。bean 对象的创建最终在方法 finishBeanFactoryInitialization() 完成

    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
     	// Initialize conversion service for this context.
     	if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
     			beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
     		beanFactory.setConversionService(
     				beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
     	}
     	......
    
  2. beanFactory.getBean() 的实现在 AbstractBeanFactory 中,会调用到 AbstractBeanFactory#doGetBean() 方法,进一步调用 getObjectForBeanInstance()方法对 bean 对象做处理

     protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
     		@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
    
     	final String beanName = transformedBeanName(name);
     	Object bean;
    
     	// Eagerly check singleton cache for manually registered singletons.
     	Object sharedInstance = getSingleton(beanName);
     	if (sharedInstance != null && args == null) {
     		......
     		bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
     	}
     	......
     }
    
  3. getObjectForBeanInstance() 会判断当前 bean 实例的相关属性,从而决定是否通过方法 getObjectFromFactoryBean() 去获取工厂 bean

    protected Object getObjectForBeanInstance(
     		Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
    
     	// Don't let calling code try to dereference the factory if the bean isn't a factory.
     	if (BeanFactoryUtils.isFactoryDereference(name)) {
     		if (beanInstance instanceof NullBean) {
     			return beanInstance;
     		}
     		if (!(beanInstance instanceof FactoryBean)) {
     			throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
     		}
     	}
    
     	// Now we have the bean instance, which may be a normal bean or a FactoryBean.
     	// If it's a FactoryBean, we use it to create a bean instance, unless the
     	// caller actually wants a reference to the factory.
     	if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
     		return beanInstance;
     	}
    
     	Object object = null;
     	if (mbd == null) {
     		object = getCachedObjectForFactoryBean(beanName);
     	}
     	if (object == null) {
     		// Return bean instance from factory.
     		FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
     		// Caches object obtained from FactoryBean if it is a singleton.
     		if (mbd == null && containsBeanDefinition(beanName)) {
     			mbd = getMergedLocalBeanDefinition(beanName);
     		}
     		boolean synthetic = (mbd != null && mbd.isSynthetic());
     		object = getObjectFromFactoryBean(factory, beanName, !synthetic);
     	}
     	return object;
     }
    
  4. getObjectFromFactoryBean() 的实现在 FactoryBeanRegistrySupport 中,根据 boolean 参数 shouldPostProcess 来决定是否对 bean 实例调用postProcessObjectFromFactoryBean()方法进行处理

    protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
     	if (factory.isSingleton() && containsSingleton(beanName)) {
     		synchronized (getSingletonMutex()) {
     			Object object = this.factoryBeanObjectCache.get(beanName);
     			if (object == null) {
     				object = doGetObjectFromFactoryBean(factory, beanName);
     				// Only post-process and store if not put there already during getObject() call above
     				// (e.g. because of circular reference processing triggered by custom getBean calls)
     				Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
     				if (alreadyThere != null) {
     					object = alreadyThere;
     				}
     				else {
     					if (shouldPostProcess) {
     						if (isSingletonCurrentlyInCreation(beanName)) {
     							// Temporarily return non-post-processed object, not storing it yet..
     							return object;
     						}
     						beforeSingletonCreation(beanName);
     						try {
     							object = postProcessObjectFromFactoryBean(object, beanName);
     						}
     						catch (Throwable ex) {
     							throw new BeanCreationException(beanName,
     									"Post-processing of FactoryBean's singleton object failed", ex);
     						}
     						finally {
     							afterSingletonCreation(beanName);
     						}
     					}
     					if (containsSingleton(beanName)) {
     						this.factoryBeanObjectCache.put(beanName, object);
     					}
     				}
     			}
     			return object;
     		}
     	}
     	else {
     		Object object = doGetObjectFromFactoryBean(factory, beanName);
     		if (shouldPostProcess) {
     			try {
     				object = postProcessObjectFromFactoryBean(object, beanName);
     			}
     			catch (Throwable ex) {
     				throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
     			}
     		}
     		return object;
     	}
     }
    
  5. postProcessObjectFromFactoryBean()方的实现在AbstractAutowireCapableBeanFactory中,在该方法内会调用其内部方法applyBeanPostProcessorsAfterInitialization()遍历调用 BeanPostProcessor 实现类的 postProcessAfterInitialization() 方法

    @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;
     }
    
  6. 上文已经提及 AnnotationAwareAspectJAutoProxyCreator 的继承结构,以上步骤最终会调用到 AnnotationAwareAspectJAutoProxyCreator 的超类 AbstractAutoProxyCreatorpostProcessAfterInitialization() 方法,在该方法内调用的wrapIfNecessary()方法就是创建代理对象的核心入口

    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.3 切面的解析与适配

  1. AbstractAutoProxyCreator#wrapIfNecessary() 方法中首先会调用 getAdvicesAndAdvisorsForBean()方法尝试去获取能够应用到给定 bean 上的切面,这个方法由其子类AbstractAdvisorAutoProxyCreator 实现;之后通过createProxy()方法将切面应用到 bean 上去创建代理对象

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
     	......
     	// Create proxy if we have advice.
     	// 1. 尝试获取能够应用到 bean 上的切面
     	Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
     	if (specificInterceptors != DO_NOT_PROXY) {
     		this.advisedBeans.put(cacheKey, Boolean.TRUE);
     		// 2. 将切面应用到 bean 上创建代理对象
     		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;
     }
    
  2. AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean()方法调用其内部方法findEligibleAdvisors()去搜索切面,其中又包含了两个步骤,第一步是findCandidateAdvisors()去搜索候选的切面,第二步是findAdvisorsThatCanApply()从候选切面中选择能够应用到给定 bean 的切面

    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;
     }
    
  3. 搜索候选切面的方法findCandidateAdvisors()AnnotationAwareAspectJAutoProxyCreator中实现,流程是先调用父类的同名方法初步获取切面列表,然后通过 BeanFactoryAspectJAdvisorsBuilder 去创建切面

    @Override
     protected List<Advisor> findCandidateAdvisors() {
     	// Add all the Spring advisors found according to superclass rules.
     	List<Advisor> advisors = super.findCandidateAdvisors();
     	// Build Advisors for all AspectJ aspects in the bean factory.
     	if (this.aspectJAdvisorsBuilder != null) {
     		advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
     	}
     	return advisors;
     }
    
  4. BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors() 方法主要流程是首先调用 this.advisorFactory.isAspect(beanType)方法根据注解@Aspect等条件判断给定bean是否是切面类,其次调用this.advisorFactory.getAdvisors(factory) 去获取增强切面 Advisor

    public List<Advisor> buildAspectJAdvisors() {
     	List<String> aspectNames = this.aspectBeanNames;
    
     	......
     					// We must be careful not to instantiate beans eagerly as in this case they
     					// would be cached by the Spring container but would not have been weaved.
     					Class<?> beanType = this.beanFactory.getType(beanName);
     					if (beanType == null) {
     						continue;
     					}
     					if (this.advisorFactory.isAspect(beanType)) {
     						aspectNames.add(beanName);
     						AspectMetadata amd = new AspectMetadata(beanType, beanName);
     						if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
     							MetadataAwareAspectInstanceFactory factory =
     									new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
     							List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
     							if (this.beanFactory.isSingleton(beanName)) {
     								this.advisorsCache.put(beanName, classAdvisors);
     							}
     							else {
     								this.aspectFactoryCache.put(beanName, factory);
     							}
     							advisors.addAll(classAdvisors);
     						}
     						else {
     							// Per target or per this.
     							if (this.beanFactory.isSingleton(beanName)) {
     								throw new IllegalArgumentException("Bean with name '" + beanName +
     										"' is a singleton, but aspect instantiation model is not singleton");
     							}
     							MetadataAwareAspectInstanceFactory factory =
     									new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
     							this.aspectFactoryCache.put(beanName, factory);
     							advisors.addAll(this.advisorFactory.getAdvisors(factory));
     						}
     					}
     				}
     				this.aspectBeanNames = aspectNames;
     				return advisors;
     			}
     		}
     	}
    ......
     }
    
  5. getAdvisors() 的实现为 ReflectiveAspectJAdvisorFactory#getAdvisors(),该方法会调用getAdvisorMethods(aspectClass) 获取切面类的所有增强方法,之后调用 getAdvisor()将每个增强方法组装为一个增强切面 Advisor

    @Override
     public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
     ......
     	
     	List<Advisor> advisors = new ArrayList<>();
     	for (Method method : getAdvisorMethods(aspectClass)) {
     		Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
     		if (advisor != null) {
     			advisors.add(advisor);
     		}
     	}
    
     ......
    
     	return advisors;
     }
    
  6. getAdvisor() 返回一个 InstantiationModelAwarePointcutAdvisorImpl实例,该实例保存了切面的类名增强方法的方法名切入点等信息。切入点 AspectJExpressionPointcutgetPointcut()返回值,该方法会解析增强方法上的注解 @Before @After 等,将注解的属性保存为切入点表达式,用于匹配被增强的方法

    public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
     		int declarationOrderInAspect, String aspectName) {
    
     	validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
    
     	AspectJExpressionPointcut expressionPointcut = getPointcut(
     			candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
     	if (expressionPointcut == null) {
     		return null;
     	}
    
     	return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
     			this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
     }
    
  7. 至此搜索候选切面完成,接下来就是 步骤2findAdvisorsThatCanApply()从候选切面中选择能够应用到给定 bean 的切面。可以看到其核心代码为调用 AopUtils.findAdvisorsThatCanApply()方法

    protected List<Advisor> findAdvisorsThatCanApply(
     		List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
    
     	ProxyCreationContext.setCurrentProxiedBeanName(beanName);
     	try {
     		return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
     	}
     	finally {
     		ProxyCreationContext.setCurrentProxiedBeanName(null);
     	}
     }
    
  8. AopUtils 判断切面是否可以应用到 bean 对象的核心方法是 canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions),这个方法会从切入点实例中获取 方法匹配者 MethodMatcher,然后调用 methodMatcher.matches()去完成匹配判断

    public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
     	......
    
     	MethodMatcher methodMatcher = pc.getMethodMatcher();
     	
     	......
     	
     	for (Class<?> clazz : classes) {
     		Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
     		for (Method method : methods) {
     			if (introductionAwareMethodMatcher != null ?
     					introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
     					methodMatcher.matches(method, targetClass)) {
     				return true;
     			}
     		}
     	}
     	return false;
     }
    

2.4 代理对象的最终创建

  1. 回到 AbstractAutoProxyCreator#wrapIfNecessary(),经过以上流程 Spring 已经为给定的 bean 对象找到了可应用的切面列表,接下来就是调用createProxy()创建代理对象将切面应用到 bean 上

    protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
     	......
     	
     	if (specificInterceptors != DO_NOT_PROXY) {
     		this.advisedBeans.put(cacheKey, Boolean.TRUE);
     		// 2. 将切面应用到 bean 上创建代理对象
     		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;
     }
    
  2. createProxy()中首先是新建代理工厂ProxyFactory,之后设置代理工厂的各项属性,将切面列表目标类都设置进去,最后调用proxyFactory.getProxy(getProxyClassLoader())去生成代理对象

    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());
     }
    
  3. 创建代理对象主要通过代理工厂来进行,而对于不同的代理方式,又分为了 JdkDynamicAopProxyObjenesisCglibAopProxy,其中 ObjenesisCglibAopProxy 继承了 CglibAopProxy。此处以 CglibAopProxy 代理为例,创建代理对象最终调用到 getProxy()方法,其中极为关键的流程为调用 getCallbacks()方法获取目标方法被 aop 拦截的回调函数列表

    @Override
     public Object getProxy(@Nullable ClassLoader classLoader) {
     	......
             // 获取拦截回调函数
     		Callback[] callbacks = getCallbacks(rootClass);
     		Class<?>[] types = new Class<?>[callbacks.length];
     		for (int x = 0; x < types.length; x++) {
     			types[x] = callbacks[x].getClass();
     		}
     		// fixedInterceptorMap only populated at this point, after getCallbacks call above
     		enhancer.setCallbackFilter(new ProxyCallbackFilter(
     				this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
     		enhancer.setCallbackTypes(types);
    
     		// Generate the proxy class and create a proxy instance.
     		return createProxyClassAndInstance(enhancer, callbacks);
     ......
     }
    
  4. getCallbacks() 会创建一个用于实现 aop 的拦截方法类 DynamicAdvisedInterceptor,当目标方法被调用的时候,该拦截类的方法 DynamicAdvisedInterceptor#intercept()就会被触发,从而完成 Aop 拦截增强目标方法的逻辑

    private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
     	......
     	
     	// Choose an "aop" interceptor (used for AOP calls).
     	Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
    
     	......
    
     	Callback[] mainCallbacks = new Callback[] {
     			aopInterceptor,  // for normal advice
     			targetInterceptor,  // invoke target without considering advice, if optimized
     			new SerializableNoOp(),  // no override for methods mapped to this
     			targetDispatcher, this.advisedDispatcher,
     			new EqualsInterceptor(this.advised),
     			new HashCodeInterceptor(this.advised)
     	};
     	......
     	
     	return callbacks;
     }
    
发布了97 篇原创文章 · 获赞 88 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_45505313/article/details/103495439