Spring AOP 流程简述

博文目录


SpringBoot 注解方式使用 @EnableAspectJAutoProxy 开启 AOP 功能, 该注解通过 @Import(ImportBeanDefinitionRegistrar) 的方式导入并注册了一个 BeanDefinition, 即 AnnotationAwareAspectJAutoProxyCreator

AnnotationAwareAspectJAutoProxyCreator

在这里插入图片描述
最终实现了 3 个 BeanPostProcessor, 在 IoC 的第二阶段发光发热

接口方法实现类#实现方法用途调用时机
InstantiationAwareBeanPostProcessorpostProcessBeforeInstantiationAbstractAutoProxyCreator解析切面实例化之前
BeanPostProcessorpostProcessAfterInitailizationAbstractAutoProxyCreato创建动态代理初始化之后
SmartInstantiationAwareBeanPostProcessorgetEarlyBeanReferenceAbstractAutoProxyCreator循环依赖下创建动态代理循环依赖时(实例化后初始化前)

基础 - Spring AOP 实现方式

Spring AOP 实现方式

  • Advice: 增强方法的逻辑
  • PointCut: 指定实现某种规则的 matches 方法来匹配类和方法, 匹配到的方法会使用 Advice 做增强. 如果一个 Bean 里面有方法被匹配到了, 说明该 Bean 需要做动态代理
  • Advisor: 封装了 Advice 和 PointCut. 调用方法时, 使用责任链的方式逐个调用 Advisor

Spring AOP 注解方式 的大致流程

Spring IoC 分两个阶段, 第一阶段解析配置类, 得到所有的 BeanDefinition, 第二阶段遍历并 getBean 生成对象

createBean 分三个步骤, 实例化, 填充属性, 初始化

  • 在实例化之前, 解析切面, 获取所有的 Advisor
  • 创建代理对象, 分初始化后的正常创建和循环依赖中(getEarlyBeanReference)的提前创建. 生成代理对象时会找到适用的 Advisor 列表并设值到代理对象中
  • 调用方法时应用 Advisor

解析切面

首先从 BeanFactory(包含层级) 中找到所有 Advisor 类型的 Bean, 然后再找到被 @Aspect 注解标记的 Bean, 将其中的 @Before, @After 等增强逻辑构建成为 Advisor 对象, 将所有的

正常创建代理

创建一个动态代理类(jdk/cglib)

循环依赖创建代理

调用增强方法

调用被代理类的方法时,找到他的所有增强器,并增强当前的方法

解析切面

createBean - resolveBeforeInstantiation - applyBeanPostProcessorsBeforeInstantiation - 遍历所有 BeanPostProcessor, 判断是 InstantiationAwareBeanPostProcessor 的话, 调用其 postProcessBeforeInstantiation 方法, AnnotationAwareAspectJAutoProxyCreator 的该方法在这时被执行

// AbstractAutoProxyCreator#postProcessBeforeInstantiation
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
	Object cacheKey = getCacheKey(beanClass, beanName);

	if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
		// 判断该 Bean 是否已经被解析过了, 则跳过, advisedBeans 里面存的就是解析过的 Bean
		if (this.advisedBeans.containsKey(cacheKey)) {
			return null;
		}
		// 如果该 Bean 是 Advice, PointCut, Advisor, AopInfrastructureBean 等类型
		// 不用把它们当做是 Bean, 而是作为 Bean 的增强会在 shouldSkip 里面单独处理
		// 为什么要 shouldSkip? 其实没太看明白
		// shouldSkip, 注意子类覆盖该方法, AspectJAwareAdvisorAutoProxyCreator.shouldSkip
		if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
			// 将该 Bean 标记为无需增强
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return null;
		}
	}

	// ...
	
	return null;
}
// AspectJAwareAdvisorAutoProxyCreator#shouldSkip
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
	// TODO: Consider optimization by caching the list of the aspect names
	// 找到所有的 Advisor, 包含 BeanFactory(包含层级) 中的和 @Aspect 注解中定义的方法(封装成为 Advisor), 然后缓存起来
	// 这个查找 Advisor 的过程和当前判断的 BeanName 是没有关系的
	// findCandidateAdvisors, 注意子类覆盖方法
	// org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator.findCandidateAdvisors
	List<Advisor> candidateAdvisors = findCandidateAdvisors();
	for (Advisor advisor : candidateAdvisors) {
		// AspectJPointcutAdvisor, 通过 xml <aop:advisor> 解析出来的 advisor
		// 从 Advisor 里拿到 切面类的 BeanName, 如果 beanName 是个切面, 和 advice, advisor, aspect 一样, 无需代理, 需要跳过
		if (advisor instanceof AspectJPointcutAdvisor &&
				((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
			return true;
		}
	}
	return super.shouldSkip(beanClass, beanName);
}
// AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
// 找到所有的 Advisor, 包含 BeanFactory(包含层级) 中的和 @Aspect 注解中定义的方法(封装成为 Advisor)
protected List<Advisor> findCandidateAdvisors() {
	// Add all the Spring advisors found according to superclass rules.
	// 从 BeanFactory(包含层级) 中找到所有实现了 Advisor 接口的 Bean
	List<Advisor> advisors = super.findCandidateAdvisors();
	// Build Advisors for all AspectJ aspects in the bean factory.
	// 找到被 @Aspect 注解标记的 Bean, 将其中的 @Before,@After 等增强逻辑构建成为 Advisor 对象, 并添加到找到的 Advisor 列表中
	if (this.aspectJAdvisorsBuilder != null) {
		// buildAspectJAdvisors 方法是有缓存的
		advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
	}
	return advisors;
}
// AbstractAdvisorAutoProxyCreator#findCandidateAdvisors
protected List<Advisor> findCandidateAdvisors() {
	Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
	return this.advisorRetrievalHelper.findAdvisorBeans();
}

// BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans
// 从 BeanFactory(包含层级) 中找到所有实现了 Advisor 接口的 Bean
public List<Advisor> findAdvisorBeans() {
	// Determine list of advisor bean names, if not cached already.
	String[] advisorNames = this.cachedAdvisorBeanNames;
	if (advisorNames == null) {
		// Do not initialize FactoryBeans here: We need to leave all regular beans
		// uninitialized to let the auto-proxy creator apply to them!
		advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
				this.beanFactory, Advisor.class, true, false);
		this.cachedAdvisorBeanNames = advisorNames;
	}
	if (advisorNames.length == 0) {
		return new ArrayList<>();
	}

	List<Advisor> advisors = new ArrayList<>();
	for (String name : advisorNames) {
		if (isEligibleBean(name)) {
			if (this.beanFactory.isCurrentlyInCreation(name)) {
				if (logger.isTraceEnabled()) {
					logger.trace("Skipping currently created advisor '" + name + "'");
				}
			}
			else {
				try {
					advisors.add(this.beanFactory.getBean(name, Advisor.class));
				}
				catch (BeanCreationException ex) {
					Throwable rootCause = ex.getMostSpecificCause();
					if (rootCause instanceof BeanCurrentlyInCreationException) {
						BeanCreationException bce = (BeanCreationException) rootCause;
						String bceBeanName = bce.getBeanName();
						if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
							if (logger.isTraceEnabled()) {
								logger.trace("Skipping advisor '" + name +
										"' with dependency on currently created bean: " + ex.getMessage());
							}
							// Ignore: indicates a reference back to the bean we're trying to advise.
							// We want to find advisors other than the currently created bean itself.
							continue;
						}
					}
					throw ex;
				}
			}
		}
	}
	return advisors;
}
// BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors
// 找到被 @Aspect 注解标记的 Bean, 将其中的 @Before,@After 等增强逻辑构建成为 Advisor 对象, 并添加到找到的 Advisor 列表中
public List<Advisor> buildAspectJAdvisors() {
	// 存放切面 Bean 的 name
	List<String> aspectNames = this.aspectBeanNames;

	if (aspectNames == null) {
		synchronized (this) {
			aspectNames = this.aspectBeanNames;
			if (aspectNames == null) {
				List<Advisor> advisors = new ArrayList<>();
				aspectNames = new ArrayList<>();
				// 从 BeanFactory(包含层级) 中拿到所有的 BeanName
				String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
						this.beanFactory, Object.class, true, false);
				for (String beanName : beanNames) {
					if (!isEligibleBean(beanName)) {
						continue;
					}
					// 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, false);
					if (beanType == null) {
						continue;
					}
					// 如果 Bean 对应的类上有 @Aspect 注解, 且该类不是被 AspectJ 的 Ajc 编译器编译来的, 那就算是一个切面
					// 搭建环境的时候, 把编译器设置成为 Ajc, 所有类都会被 Ajc 编译, 所以常规的切面在这里并不会被判定为切面, 理论上并不会被解析, 但是方法确实被增强了, 不知道哪里还做了其他操作
					// 正确的做法是: 设置 Ajc 编译器的时候, 记得勾选 "Delegate to Javac", 这样只有 .aj 的会被 Ajc 编译器编译, 其他的 .java 还是 javac 编译器编译
					if (this.advisorFactory.isAspect(beanType)) {
						aspectNames.add(beanName);
						AspectMetadata amd = new AspectMetadata(beanType, beanName);
						if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
							// 1.找到所有的切面类
							// 2.筛选出来包含 @Around,@Before,@After,@AfterReturning,@AfterThrowing 注解的方法
							// 3.封装为List<Advisor>
							MetadataAwareAspectInstanceFactory factory =
									new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
							List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
							if (this.beanFactory.isSingleton(beanName)) {
								// 将上面找出来的 Advisor 按照 key 为beanName,value 为 List<Advisor> 的形式存入 advisorsCache
								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;
			}
		}
	}

	if (aspectNames.isEmpty()) {
		return Collections.emptyList();
	}
	List<Advisor> advisors = new ArrayList<>();
	for (String aspectName : aspectNames) {
		// 当再次进入该方法,会直接从 advisorsCache 缓存中获取
		List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
		if (cachedAdvisors != null) {
			advisors.addAll(cachedAdvisors);
		}
		else {
			MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
			advisors.addAll(this.advisorFactory.getAdvisors(factory));
		}
	}
	return advisors;
}

正常创建代理

设计模式 代理模式(Proxy)

createBean - doCreateBean - initializeBean(创建 Bean 的第三步, 初始化) - applyBeanPostProcessorsAfterInitialization - 遍历所有 BeanPostProcessor, 调用其 postProcessAfterInitialization 方法, AnnotationAwareAspectJAutoProxyCreator 的该方法在这时被执行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值