跟着小马哥学系列之 Spring AOP(AbstractAutoProxyCreator 详解)

学成路更宽,吊打面试官。 ——小马哥

版本修订

  • 2021.5.19:去除目录

简介

大家好,我是小马哥成千上万粉丝中的一员!2019年8月有幸在叩丁狼教育举办的猿圈活动中知道有这么一位大咖,从此结下了不解之缘!此系列在多次学习极客时间《小马哥讲Spring AOP 编程思想》基础上形成的个人一些总结。希望能帮助各位小伙伴, 祝小伙伴早日学有所成。

AbstractAutoProxyCreator 功能

从命名可知这个抽象类主要功能就是自动创建代理,怎么实现自动?这就得与 Spring IoC 容器打通。所以此抽象类实现了 SmartInstantiationAwareBeanPostProcessorBeanFactoryAware

  • 使用 AOP 代理包装每个合格 bean 用 BeanPostProcessor 实现,在调用 bean 本身之前将委托给指定的拦截器。
  • 这个类区分了公共的拦截器(为它创建的所有代理共享)以及 特定的拦截器(每个 bean 实例都是唯一的)。如果有公共的拦截器,则使用 interceptorNames 属性设置它们(与 ProxyFactoryBean 一样,使用当前工厂中的拦截器名称而不是 bean 引用来允许正确处理原型 advisor 和拦截器)
  • 如果有大量 bean 需要用类似的代理进行包装,即委托给相同的拦截器,那么这种自动代理特别有用。您可以向 bean 工厂注册一个这样的后处理程序来实现相同的效果,而不是为 x 个目标 bean 重复定义 x 个代理。
  • 子类可以应用任何策略(子类可以实现 getAdvicesAndAdvisorsForBean 方法)来决定一个 bean 是否要被代理,例如根据类型、名称、定义细节等。它们还可以返回应该只应用于特定 bean 实例的额外拦截器。一个简单的具体实现是 BeanNameAutoProxyCreator,它通过给定的名称标识要代理的 bean。
  • 任意的 TargetSourceCreator 实现都可以用于创建自定义目标源:例如,将原型对象池化。即使没有 advice,只要 TargetSourceCreator 指定了自定义 TargetSource,也会发生自动代理。如果没有设置 TargetSourceCreators ,或者没有匹配的,默认情况下将使用 SingletonTargetSource 来包装目标 bean 实例。

AbstractAutoProxyCreator 类图

跟着小马哥学系列之 Spring AOP(AbstractAutoProxyCreator 详解)_第1张图片

相关类介绍

AopInfrastructureBean

标记接口,用于识别 Spring AOP 基础结构一部分的 bean,避免当 Pointcut 匹配时生成代理对象。

ProxyConfig

用于创建代理时配置的便利超类,以确保所有代理创建器具有一致的属性。

主要配置:

  1. proxyTargetClass:同 @EnableAspectJAutoProxy 中的属性 proxyTargetClass 一样语义,是否使用 CGLIB 代理,默认是 false 使用 JDK 基于接口的动态代理
  2. optimize:设置代理是否应该执行主动优化。主动优化的确切含义在不同的代理之间是不同的,但通常会有一些权衡。默认设置是 false。例如,优化通常意味着在创建代理之后通知更改不会生效。因此,优化在默认情况下是禁用的。如果其他设置排除了优化,那么“true”的优化值可能会被忽略;例如,如果 exposeProxy 被设置为 true,而这与优化不兼容。
  3. opaque:默认值是 false,任何 AOP 代理都可以强制转换为 Advised
  4. exposeProxy:同 @EnableAspectJAutoProxy 中的属性 exposeProxy 一样语义,是否将代理对象暴露在 AopContext 类中。
  5. frozen:设置该配置是否应该被冻结。当一个配置被冻结时,不能做出任何 Advice 更改。这对于优化很有用,当我们不希望调用方能够在强制转换为 Adviced 后操作配置时也很有用。

ProxyProcessorSupport

具有代理处理器通用功能的基类,特别是 ClassLoader 管理和 evaluateProxyInterfaces 算法。

管理 ClassLoader

通过属性 boolean classLoaderConfigured 管理属性 proxyClassLoader 只允许设置一次

evaluateProxyInterfaces() 方法解读

检查给定 bean 类上的接口,并将它们应用到 ProxyFactory(如果可用的话)。调用 isConfigurationCallbackInterface(Class) 和 sInternalLanguageInterface(Class) 来过滤合理的代理接口。如果没有可用接口则使用 CGLIB 代理。

protected void evaluateProxyInterfaces(Class<?> beanClass, ProxyFactory proxyFactory) {
	// 获取类中的所有接口,如果是接口返回它自己
	Class<?>[] targetInterfaces = ClassUtils.getAllInterfacesForClass(beanClass, getProxyClassLoader());
	boolean hasReasonableProxyInterface = false;
	/**
	 *  获取的接口列表,只要接口列表满足一个不是 Spring 框架 InitializingBean、DisposableBean、Aware 接口扩展接口和
	 *  不是 Jdk 中 AutoCloseable 和 Closeable 接口并且不是内部语言接口(接口名称是 groovy.lang.GroovyObject
	 *  或者是以 .cglib.proxy.Factory 结尾或者 .bytebuddy.MockAccess 结尾)并且不是空接口
	 */
	for (Class<?> ifc : targetInterfaces) {
		if (!isConfigurationCallbackInterface(ifc) && !isInternalLanguageInterface(ifc) &&
				ifc.getMethods().length > 0) {
			hasReasonableProxyInterface = true;
			break;
		}
	}
	// 如果有可代理的接口添加到代理工厂中
	if (hasReasonableProxyInterface) {
		for (Class<?> ifc : targetInterfaces) {
			proxyFactory.addInterface(ifc);
		}
	}
	else {
		// 没有接口就设置 CGLIB 代理
		proxyFactory.setProxyTargetClass(true);
	}
}

BeanFactoryAware

实现 setBeanFactory((BeanFactory beanFactory) 方法。并且该实现类交由 Spring IoC 管理。则由 Spring IoC 容器在填充普通 bean 属性之后,但在初始化回调(如 iinitializingBean.afterPropertiesSet() 或自定义初始化方法之前调用。

BeanPostProcessor

Bean 的后置处理器,可以通过实现此接口覆写 postProcessBeforeInitialization 和 postProcessAfterInitialization 方法对 bean 进行修改,比如 AbstractAutoProxyCreato 就是通过覆写 postProcessAfterInitialization 返回代理对象

InstantiationAwareBeanPostProcessor

BeanPostProcessor 的子接口,它添加了一个实例化之前的回调函数和一个实例化之后但在显式属性设置或自动装配发生之前的回调函数。通常用于抑制特定目标 bean 的默认实例化,例如创建带有特殊 targetsource 的代理(池化目标、延迟初始化目标等),或者实现额外的注入策略,如字段注入。

SmartInstantiationAwareBeanPostProcessor

此接口扩展了 InstantiationAwareBeanPostProcessor接口,添加一个 predictBeanType 回调,用于预测已处理 bean 的最终类型。

AopProxy

通过委派已配置的 Aop 代理接口,创建实际的代理对象。Spring AOP 通过 DefaultAopProxyFactory 提供了开箱即用 的 JDK 动态代理(JdkDynamicAopProxy) 和 CGLIB 代理(ObjenesisCglibAopProxy)

  • 通过 getProxy方法获取代理对象(默认的 ClassLoader)
  • 通过指定 ClassLoadergetProxy(@Nullable ClassLoader classLoader) 方法获取代理对象

AopProxyFactory

基于 AdvisedSupport 配置对象新增 AOP 代理的工厂接口

代理应该遵守以下契约:

  • 应该实现配置的所有接口
  • 实现 Advised 接口
  • 实现 equals 方法用于比较代理接口、advice 和 目标对象
  • 如果所有的 advisor 和 目标对象都是可序列化的,代理对象应该也是可序列化的
  • 如果 advisor 和目标对象是线程安全的则代理对象也应该是线程安全的

唯一实现:DefaultAopProxyFactory#createAopProxy(AdvisedSupport config) 方法分析

AopProxyFactory 默认实现,创建不是 JDK 动态代理就是 CGLIB 代理。

@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
	/**
	 * 对于给定的 AdvisedSupport 实例,如果满足以下任意条件,则创建一个 CGLIB 代理:
	 * 1. 优化标志被设置
	 * 2. proxyTargetClass 标志被设置(即使设置了如果被代理对象是接口还是使用 JDK 动态代理)
	 * 3. 没有指定代理接口
	 */ 
	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 动态代理代理过的对象则创建 JDK 动态代理
		if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
			return new JdkDynamicAopProxy(config);
		}
		return new ObjenesisCglibAopProxy(config);
	}
	else {
		return new JdkDynamicAopProxy(config);
	}
}

AbstractAutoProxyCreator 简介

AdvisorAdapterRegistry 管理

  • 通过 advisorAdapterRegistry 属性管理 AdvisorAdapterRegistry 默认是 GlobalAdvisorAdapterRegistry(DefaultAdvisorAdapterRegistry),
  • 可以通过 setAdvisorAdapterRegistry() 方法进行设置

TargetSourceCreator 使用

在前面 AbstractAutoProxyCreator 功能介绍最后一条中介绍即使没有 Advice,只要 TargetSourceCreator 指定了自定义 TargetSource,也会发生自动代理,将会在 postProcessBeforeInstantiation 介绍

  • 可以通过 setCustomTargetSourceCreators(TargetSourceCreator… targetSourceCreators) 方法设置

公共拦截器管理

  • 通过 interceptorNames 属性管理公共拦截器
  • 通过 setInterceptorNames(String... interceptorNames)方法进行设置
  • 通过 setApplyCommonInterceptorsFirst(boolean applyCommonInterceptorsFirst) 方法设置公共拦截器与特殊拦截的先后顺序

BeanFactory 管理

由于 AbstractAutoProxyCreator 实现了 BeanFactoryAware 便于底层 IoC 打通,具有依赖查找的能力

  • 通过 getBeanFactory() 获取 BeanFactory
  • setBeanFactory 方法由 Spring IoC 容器回调

SmartInstantiationAwareBeanPostProcessor 实现

	@Override
	@Nullable
	public Class<?> predictBeanType(Class<?> beanClass, String beanName) {
		// 如果代理类型缓存为空则跳过
		if (this.proxyTypes.isEmpty()) {
			return null;
		}
	   /**
         * 如果 bean 名称为空则 cacheKey 则是类对象;
         * 如果有 bean 类型是 FactoryBean 则 cacheKey 则是 &beanName;
         * 否则 cacheKey 就是 beanName
         */
		Object cacheKey = getCacheKey(beanClass, beanName);
		// 通过 cacheKey 去代理类型缓存获取
		return this.proxyTypes.get(cacheKey);
	}
	
	@Override
	@Nullable
	public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) {
		return null;
	}
	
	@Override
	public Object getEarlyBeanReference(Object bean, String beanName) {
		 /**
         * 如果 bean 名称为空把 bean Class 对象作为 cacheKey ;
         * 如果有 bean 类型是 FactoryBean 则 cacheKey 则是 &beanName;
         * 否则 cacheKey 就是 beanName
         */
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		// 缓存早期代理引用
		this.earlyProxyReferences.put(cacheKey, bean);
		// 根据条件生成代理
		return wrapIfNecessary(bean, beanName, cacheKey);
	}

获取代理对象

wrapIfNecessary() 方法分析

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
	// 如果通过了自定义 TargetSourceCreator 方式处理过目标实例则不需要代理
	if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
		return bean;
	}
	// 内部基础 bean 或者不需要代理的 bean 则不代理
	if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
		return bean;
	}
	/**
	 * 是否是基础设施(默认规则 Advice、Pointcut、Advisor、AopInfrastructureBean)
	 * 或者不需要进行代理(默认规则是否是类名与 bean 名称长度必须相同并且 bean 名称以类名开头以 .ORIGINAL)则不代理。并放入 advisedBeans 缓存中
	 */
	if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {		// 方入 advisedBean 缓存以便重复创建 bean 时提供性能
		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}
	
	// 根据子类实现不同的规则获取 Advice/Advisor.
	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;
	}
	// 如果没有符合条件的 advice 则不生成代理并缓存
	this.advisedBeans.put(cacheKey, Boolean.FALSE);
	return bean;
}

createProxy() 方法分析

protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
	@Nullable Object[] specificInterceptors, TargetSource targetSource) {
	/**
	 *  获取 beanName 的 BeanDefinition 并设置一个
	 *  属性名为 org.springframework.aop.framework.autoproxy.AutoProxyUtils.originalTargetClass 值为 beanClass 属性
	 */
	if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
		AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
	}
	// 通过 ProxyFactory 来创建代理对象
	ProxyFactory proxyFactory = new ProxyFactory();
	proxyFactory.copyFrom(this);
	// 使用 JDK 动态代理
	if (!proxyFactory.isProxyTargetClass()) {
	/**
	 *  通过 beanName 的 BeanDefinition 获取属性名  
	 *  org.springframework.aop.framework.autoproxy.AutoProxyUtils.originalTargetClass.preserveTargetClass
	 *  的属性值是否为 true 如果是 true 即使 proxyFactory.isProxyTargetClass() 是 false 还是会使用 CGLIB 动态代理
	 */
		if (shouldProxyTargetClass(beanClass, beanName)) {
			proxyFactory.setProxyTargetClass(true);
		}
		else {
			// 父类 ProxyProcessorSupport#evaluateProxyInterfaces 方法在上面已经分析过了
			evaluateProxyInterfaces(beanClass, proxyFactory);
		}
	}
	// 构建 Advisor(后面分析)
	Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
	proxyFactory.addAdvisors(advisors);
	proxyFactory.setTargetSource(targetSource);
	// 空方法留给子类扩展
	customizeProxyFactory(proxyFactory);
	// 是否冻结代理对象(默认是 false)
	proxyFactory.setFrozen(this.freezeProxy);
	// 是否对 Advisor 预过滤(默认是 false 留给子类扩展 AbstractAdvisorAutoProxyCreator 是 true)
	if (advisorsPreFiltered()) {
		proxyFactory.setPreFiltered(true);
	}
	// 通过代理工厂根据 ClassLoader 获取代理对象 
	return proxyFactory.getProxy(getProxyClassLoader());
}

buildAdvisors() 方法分析

确定给定 bean 的 Advisor,包括特定的拦截器和公共拦截器,然后把这些拦截器都适配成 Advisor 对象。

protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
	/**
	 * 根据内部关联 BeanFactory 通过 IoC 根据公共的拦截器的 bean 名称获取 bean 
	 * 然后再通过内部关联的 DefaultAdvisorAdapterRegistry 包装成类型为`DefaultPointcutAdvisor` 的 Advisor
	 */
	Advisor[] commonInterceptors = resolveInterceptorNames();

	List<Object> allInterceptors = new ArrayList<>();
	// 特定的拦截器不为空再根据是否设置了公共拦截器在前,合并这些拦截器
	if (specificInterceptors != null) {
		allInterceptors.addAll(Arrays.asList(specificInterceptors));
		if (commonInterceptors.length > 0) {
			if (this.applyCommonInterceptorsFirst) {
				allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
			}
			else {
				allInterceptors.addAll(Arrays.asList(commonInterceptors));
			}
		}
	}
	
	Advisor[] advisors = new Advisor[allInterceptors.size()];
	for (int i = 0; i < allInterceptors.size(); i++) {
		// 通过内部关联的 DefaultAdvisorAdapterRegistry 把拦截器包装成 Advisor
		advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
	}
	return advisors;
}

子类

AbstractAdvisorAutoProxyCreator

自动构建 Advisor 代理列表,子类覆写 findCandidateAdvisors() 获取 Advisor 列表。也可以通过覆写 AbstractAutoProxyCreator.shouldSkip(java.lang.Class, java.lang.String) 方法跳过自动代理。 通过 @Order 注解或者实现 Ordered 接口来控制 Adivosr/Advice。通过 AnnotationAwareOrderComparator 来排序 Advisor/Advice。没有 @Order 注释或没有实现 Ordered 接口的 Advisor 将被认为是无序的;它们将以未定义的顺序出现在 Advisor 链的末尾。

方法

getAdvicesAndAdvisorsForBean() 方法

实现 AbstractAutoProxyCreator#getAdvicesAndAdvisorsForBean 方法,委派给本类 findEligibleAdvisors() 方法(子类可以覆写)

@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
	Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
	// 委派给 findEligibleAdvisors() 方法(子类可以覆写)
	List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
	if (advisors.isEmpty()) {
		return DO_NOT_PROXY;
	}
	return advisors.toArray();
}
findEligibleAdvisors() 方法
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
	// 通过 IoC 容器获取所有 Advisor 实例
	List<Advisor> candidateAdvisors = findCandidateAdvisors();
	/**
	 *  如果 Advisor 类型是 IntroductionAdvisor 获取关联的 ClassFilter 进行匹配
	 *  如果 Advisor 类型是 PointcutAdvisor 获取关联的 ClassFilter 进行匹配,如果匹配成功再获取 MethodMatcher 进行静态匹配(2个参数 matches() 方法 )
	 */
	List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
	// 扩展接口子类实现
	extendAdvisors(eligibleAdvisors);
	if (!eligibleAdvisors.isEmpty()) {
		// 进行排序
		eligibleAdvisors = sortAdvisors(eligibleAdvisors);
	}
	return eligibleAdvisors;
}

AspectJAwareAdvisorAutoProxyCreator

AbstractAdvisorAutoProxyCreator 子类,它暴露 AspectJ 的调用上下文,并在多个 advice 来自相同的 aspect 时推断 AspectJ 的 advice 优先级规则(AspectJPrecedenceComparator 比较器)。

主要覆盖方法

  • extendAdvisors:通过 ExposeInvocationInterceptorMethodInvocation 暴露到上下文,以便在 AspectJ 中操作(例如 AbstractAspectJAdvice#currentJoinPoint 方法和 AspectJExpressionPointcut#matches(Method method, Class targetClass, Object… args) 方法)
  • shouldSkip:通过定义的 Aspect
  • sortAdvisors:通过 PartiallyComparableAdvisorHolder 中关联的AnnotationAwareOrderComparator 进行排序

AnnotationAwareAspectJAutoProxyCreator

AspectJAwareAdvisorAutoProxyCreator 子类,它处理当前应用上下文用中所有的 AspectJ 中 @Aspect 注解 以及 Spring Advisor ,通过 ReflectiveAspectJAdvisorFactory 和 BeanFactoryAspectJAdvisorsBuilderAdapter 相互搭配实现

主要覆盖方法

findCandidateAdvisors() 方法
@Override
protected List<Advisor> findCandidateAdvisors() {
	// 通过 Spring IoC 容器获取所有 Advisor Bean
	List<Advisor> advisors = super.findCandidateAdvisors();
	// 通过 Spring IoC 容器获取所有标注 @AspectJ 注解的 Bean,再获取标注 AspectJ 注解(除了@Pointcut 其他的注解 @After、@Before、@AfterReturning 等)的方法
	if (this.aspectJAdvisorsBuilder != null) {
		advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
	}
return advisors;
}

总结

自动代理创建主要利用 Spring IoC 的 BeanPostProcessor#postProcessAfterInitialization 方法进行扩展,再利用 getAdvicesAndAdvisorsForBean 模板方法根据不同规则获取 Advice/Advisor(比如 Bean 名称,Bean 类型以及 AspectJ ),然后由 ProxyFactory 委派给 DefaultAopProxyFactory(默认,也可以替换)获取代理对象

你可能感兴趣的:(Spring,AOP,spring,java)