Spring源码学习篇之AOP-1

开启AOP相关注解,xml中配置如下:

<aop:aspectj-autoproxy />

1、AOP 相关组件注册

在这里插入图片描述
spring容器启动时,将会解析配置文件中的指令节点逐一解析,配置了aspectj-autoproxy指令后,在refresh()中的obtainFreshBeanFactory()阶段解析XML配置时,当解析到该指令时,触发AspectJAutoProxyBeanDefinitionParser解析器对其进行解析。

主要由AopNamespaceUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary()注册AOP相关注解组件并通知,便于监听器进一步处理。

public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
		ParserContext parserContext, Element sourceElement) {
	// 注册或升级AutoProxyCreator定义beanName为
	BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
			parserContext.getRegistry(), parserContext.extractSource(sourceElement));

	//对于proxy-target-class以及expose-proxy属性的处理
	useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);

	//注册组件并通知,便于监听器进一步处理
	//其中beanDefinition的className为AnnotationAwareAspectJAutoProxyCreator
	registerComponentIfNecessary(beanDefinition, parserContext);
}

2、AOP 创建代理

在上文组件注册章节中已经完成了AnnotationAwareAspectJAutoProxyCreator.class类型的bean注册。在其类层次结构中看出实现了BeanPostProcessor接口,即等于是bean的增强器。
在这里插入图片描述
所以我们只需关注bean初始化前后的两个增强逻辑(postProcessBeforeInitializationpostProcessAfterInitialization)即可。

2.1、postProcessBeforeInstantiation方法:

在该方法中,首先判断是否被处理,若被处理,则判断设置是否代理,紧接着判断是否基础设施类或者是否需要跳过该bean而跳过逻辑中:根据切点增强方法中的切面名称是否和该bean name一致,一致则跳过。

若未被处理,则根据自定义bean creator创建bean,最后根据切面中方法判断是否要创建该bean代理。

@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
	Object cacheKey = getCacheKey(beanClass, beanName);
	// 如果已经被处理过
	if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
		if (this.advisedBeans.containsKey(cacheKey)) {
			return null;
		}
		if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
			this.advisedBeans.put(cacheKey, Boolean.FALSE);
			return null;
		}
	}

	// Create proxy here if we have a custom TargetSource.
	// Suppresses unnecessary default instantiation of the target bean:
	// The TargetSource will handle target instances in a custom fashion.
	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;
}

注意:跳过判断方法中解析了切面中的方法,并添加缓存。下方贴出shouldSkip()代码:

protected boolean shouldSkip(Class<?> beanClass, String beanName) {
	// TODO: Consider optimization by caching the list of the aspect names
	List<Advisor> candidateAdvisors = findCandidateAdvisors();
	for (Advisor advisor : candidateAdvisors) {
		//若和切面名称一致,则跳过,无需创建代理类
		if (advisor instanceof AspectJPointcutAdvisor &&
				((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
			return true;
		}
	}
	return super.shouldSkip(beanClass, beanName);
}
protected List<Advisor> findCandidateAdvisors() {
	// Add all the Spring advisors found according to superclass rules.
	// 当时用注解方式配置AOP时,并不是丢弃了对XML的支持
	// 在这里调用父类方法加载配置中的AOP声明
	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;
}
public List<Advisor> buildAspectJAdvisors() {
	List<String> aspectNames = this.aspectBeanNames;
	//double check lock
	if (aspectNames == null) {
		synchronized (this) {
			aspectNames = this.aspectBeanNames;
			if (aspectNames == null) {
				List<Advisor> advisors = new ArrayList<>();
				aspectNames = new ArrayList<>();
				//获取所有的bean names
				String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
						this.beanFactory, Object.class, true, false);
				for (String beanName : beanNames) {
					Class<?> beanType = this.beanFactory.getType(beanName);
					// 如果存在aspect注解
					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);
							// 解析标记AspectJ注解中的 增强方法
							List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
							advisors.addAll(classAdvisors);
						}
					}
				}
				this.aspectBeanNames = aspectNames;
				return advisors;
			}
		}
	}
	return advisors;
}
/**
 * 解析 标记AspectJ注解bean中的  增强方法
 */
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
	// 获取标记AspectJ的类
	Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
	// 获取标记AspectJ的切面名称
	String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
	List<Advisor> advisors = new ArrayList<>();
	// getAdvisorMethods(aspectClass) 获取所有切面中非@PiontCut的方法
	for (Method method : getAdvisorMethods(aspectClass)) {
		/**
		 * 1、获取普通增强器的逻辑
		 * 		1.1、对切点的注解的获取
		 * 		1.2、根据不同的注解信息生成不同的增强(before、around、after...)
		 */
		Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
		if (advisor != null) {
			advisors.add(advisor);
		}
	}
	return advisors;
}

总之:在bean初始化前的增强逻辑中,就会把所有的切面及切面内的增强方法全部解析完成,并加入缓存LIST中,为后续的bean后置增强中创建代理提供支持。

2.2 postProcessAfterInitialization方法

bean的后置增强,则是在初始化bean属性后,如果需要代理,则返回代理后的bean。

🎈在这之前先介绍实例化的初始化(initializeBean)阶段,在此阶段将执行bean前置和后置逻辑增强。代码如下:

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			// 前置增强
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}
		try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		if (mbd == null || !mbd.isSynthetic()) {
			// 后置增强——在此处生成代理类如果需要的话
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
		return wrappedBean;
	}

后置增强方法

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
	if (bean != null) {
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		if (this.earlyProxyReferences.remove(cacheKey) != bean) {
			// 如果适合被代理,则需要封装指定bean
			return wrapIfNecessary(bean, beanName, cacheKey);
		}
	}
	return bean;
}

wrapIfNecessary方法

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
	// 如果已经被处理过
	if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
		return bean;
	}
	// 无需增强的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;
	}

	// Create proxy if we have advice.
	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;
	}

	this.advisedBeans.put(cacheKey, Boolean.FALSE);
	return bean;
}

针对不同的模式选择是JDK代理还是CGLIB代理。

该类是否继承接口,存在接口继承则使用JDK代理(生成接口的代理实现类),否则使用CDLIB进行代理(生成完成继承该类所有非final方法的兄弟类)。

注意:若是当前bean不存在实现接口,则直接采用CGLIB生成代理。

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
	if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
		Class<?> targetClass = config.getTargetClass();
		if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
			return new JdkDynamicAopProxy(config);
		}
		return new ObjenesisCglibAopProxy(config);
	}
	else {
		return new JdkDynamicAopProxy(config);
	}
}

后续学习深入后再进行补充!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值