SpringAOP源码分析

前言

SpringAOP在Spring框架中占据了非常重要的位置,所提供的面向切面编程(AOP)是对面向对象编程(OOP)的一种补充。AOP采用横切的的方式,将核心业务与通用逻辑切分开来。可以更好的服用代码以及项目管理。

理论部分

Aspect:切面

aspect是由pointcutadvice组成的。它包含了横切逻辑定义和横切点定义。Spring AOP就是实现切面编程的框架,它将切面所定义的横切逻辑织入连接点中。Spring AOP的重心在如何将横切逻辑织入到目标连接点上,这里包含两个工作:

1. 如何通过pointcut和advice定位到joinpoint上

2. 如何在advice中编写切面代码

Advice:增强

由aspect添加到特定的joinpoint上的一段代码,在许多的AOP框架中,也包括Spring AOP,都会将advice模拟为一个拦截器(interceptor),并且在joinpoint上维护多个advice,进行层层拦截。

Joinpoint:连接点

方法的执行点。

Pointcut:切点

Advice和特定的pointcut相关联,并且在匹配的joinpoint中执行。

关于join point 和 point cut 的区别

joinpoint是描述那些方法可以被advice增强,joinpoint是具体的织入的地方。advice是在joinpoint上执行,而pointcut规定了那些joinpoint可以执行哪些advice。

入口

我们的自定义代码中,扫描到包含有@EnableAspectJAutoProxy注解的,就引入了AOP的依赖。其中的引入逻辑是在AspectJAutoProxyRegistrar中定义的。 

@Aspect
@Component
@EnableAspectJAutoProxy
public class AspectDefinition {

	@Pointcut("execution(* com.chudichen.spring.aop.*.getTestStr(..))")
	public void pointcut() {
	}

	@Around("pointcut()")
	public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
		System.out.println("Execute aop method");
		return proceedingJoinPoint.proceed();
	}
}

 继续点击进入@EnableAspectJAutoProxy可以看到AspectJAutoProxyRegistrar

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {

	/**
	 * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
	 * to standard Java interface-based proxies. The default is {@code false}.
	 */
	boolean proxyTargetClass() default false;

	/**
	 * Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
	 * for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
	 * Off by default, i.e. no guarantees that {@code AopContext} access will work.
	 * @since 4.3.1
	 */
	boolean exposeProxy() default false;

}

具体的注册逻辑,调用了AopConfigUtils的registerAspectJAnnotationAutoProxyCreatorIfNecessary方法。

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

	/**
	 * Register, escalate, and configure the AspectJ auto proxy creator based on the value
	 * of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
	 * {@code @Configuration} class.
	 */
	@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);
			}
		}
	}

}

向registry中注册AnnotationAwareAspectJAutoProxyCreator.class

	@Nullable
	public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
		return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
	}

	@Nullable
	public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
			BeanDefinitionRegistry registry, @Nullable Object source) {

		return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
	}
	@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);
		registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
		return beanDefinition;
	}

深入AnnotationAwareAspectJAutoProxyCreator

首先AnnotationAwareAspectJAutoProxyCreator的类结构图如下:

可以看到AnnotationAwareAspectJAutoProxyCreator实现了BeanPostProcessor,BeanPostProcessor中有两个方法postProcessBeforeInitialization和postProcessAfterInitialization,这里的AOP实现是在postProcessAfterInitialization中。

根据之前分析IOC源码的过程,可以知道Spring容器中的单例实例的创建是在AbstractApplicationContext中的refresh()里面的finishBeanFactoryInitialization()里面完成的。

因此AOP的增强逻辑的入口也是从finishBeanFactoryInitialization开始逐步的分析。

时序图:

 第一步就是先找到增强逻辑advice,入口是从创建单例bean之后的initializeBean(),在此方法包含有执行后置处理器的逻辑,AOP的增强就是在后置处理器中实现的。

	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()) {
			// 执行后置处理器,AOP增强
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

接着进入到applyBeanPostProcessorsBeforeInitialization,这里的逻辑就是依次执行在容器中注册的后置处理器。AOP的后置处理器是AnnotationAwareAspectJAutoProxyCreator,后置处理器的实现是在AbstractAutoProxyCreator中。

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

执行AOP的后置处理器逻辑,具体构建逻辑是在wrapIfNecessary中。

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

上半段的逻辑是验证是否需要增强,不需要则直接跳过,如果需要增强,进一步来寻找增强逻辑(Advice)。

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

通过getAdvicesAndAdvisorsForBean()方法来寻找增强逻辑,之前配置的pointcut也在这里使用。实现部分的代码是在AbstractAdvisorAutoProxyCreator里面。具体的查询逻辑还需要更进一步到findEligibleAdvisors当中,首先是查询出所有的Advisor,然后进行匹配,最后按照设置好的优先级进行排序。

	protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
		// 查询出所有的Advisor
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		// 匹配到合适的Advisor
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			// 按照优先级进行排序
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}
findCandidateAdvisors()的逻辑是在子类AnnotationAwareAspectJAutoProxyCreator中实现的,通过BeanFactoryAspectJAdvisorsBuilder来构建Advisor列表。
	public List<Advisor> buildAspectJAdvisors() {
		List<String> aspectNames = this.aspectBeanNames;

		if (aspectNames == null) {
			synchronized (this) {
				aspectNames = this.aspectBeanNames;
				if (aspectNames == null) {
					List<Advisor> advisors = new ArrayList<>();
					aspectNames = new ArrayList<>();
					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);
						if (beanType == null) {
							continue;
						}
						// 如果是Aspect的bean就添加到Advisor列表中
						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;
				}
			}
		}

		if (aspectNames.isEmpty()) {
			return Collections.emptyList();
		}
		List<Advisor> advisors = new ArrayList<>();
		for (String aspectName : aspectNames) {
			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;
	}

创建代理对象

解析完匹配的拦截器(Advisor)列表之后,就可以进行代理对象的创建了,进入到创建的核心逻辑createProxy()当中。首先就是按照Spring的惯例套路,在执行创建之前,先做大量的准备工作,比如说验证以及ProxyFactory的创建。

	protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {

		// 将beanName设置为目标代理类
		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);
			}
		}

		// 封装通知,然后将Advisors添加到ProxyFactory中
		Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
		proxyFactory.addAdvisors(advisors);
		// 设置dialing类
		proxyFactory.setTargetSource(targetSource);
		// 定制代理
		customizeProxyFactory(proxyFactory);

		// 用来控制代理工厂被装配之后,是否允许修改通知,默认值为false,即在代理配置之后,不允许修改代理配置。
		proxyFactory.setFrozen(this.freezeProxy);
		if (advisorsPreFiltered()) {
			proxyFactory.setPreFiltered(true);
		}

		return proxyFactory.getProxy(getProxyClassLoader());
	}

中间的过程包含了一步转换的操作buildAdvisors()。

	protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
		// 解析拦截器名并注册
		// Handle prototypes correctly...
		Advisor[] commonInterceptors = resolveInterceptorNames();

		List<Object> allInterceptors = new ArrayList<>();
		if (specificInterceptors != null) {
			// 将通知都封装在allInterceptors中
			allInterceptors.addAll(Arrays.asList(specificInterceptors));
			if (commonInterceptors.length > 0) {
				if (this.applyCommonInterceptorsFirst) {
					allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
				}
				else {
					allInterceptors.addAll(Arrays.asList(commonInterceptors));
				}
			}
		}
		if (logger.isTraceEnabled()) {
			int nrOfCommonInterceptors = commonInterceptors.length;
			int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
			logger.trace("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
					" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
		}

		Advisor[] advisors = new Advisor[allInterceptors.size()];
		for (int i = 0; i < allInterceptors.size(); i++) {
			// 使用advisorAdapterRegistry这个适配器来包装通知
			advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
		}
		return advisors;
	}

最后则是使用创建好的工厂来生成代理对象。到此AOP的源码解析完成了一大步了,由于篇幅较长,h2后续的CGlib和JDK生成代理的过程单独拆分出来。

总结

1. 首先可以借鉴的是Spring的代码结构,层层包裹,子类为父类提供具体的实现逻辑,父类来定义比较宏观的操作,也可以利用模板方法设计模式。

2. 将解析到的通知存储到缓存中。

3. 从缓存中获取通知,再筛选通知。

4. 包装通知,初始化ProxyFactory。

5. 使用ProxyFactory来创建代理(JDK动态代理、CGlib代理)。

6. 代理最终实现AOP的核心逻辑。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值