SpringAOP中@EnableAspectJAutoProxy注解的作用

文章目录

  • 前言
    • 从注解开始
    • Import注解
    • 封装对象、注入容器
  • AnnotationAwareAspectJAutoProxyCreator的作用
    • 类图
    • 回顾IOC对象初始化
    • 后置处理器
  • 总结

前言

如果要使用SpringAOP的功能,必须要添加一个@EnableAspectJAutoProxy注解,有了这个注解才能支持@Aspect等相关的一系列AOP注解的功能,这个注解就相当于在传统的xml配置文件中添加 一样。

在学习SpringAOP相关的知识之前,建议一定要先搞清楚IOC相关的知识,如果不清楚的可以先阅读Spring专栏中IOC系列的文章。

从注解开始

接下来就来看一下@EnableAspectJAutoProxy注解到底做了什么?

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

}

Import注解

看到@Import注解,直接跟进去。@Import注解不了解的可以看这篇文章,解析Spring中@Import的实现原理

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.
	 */
	// spring启动时,会调用到这个方法
	@Override
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		// 注册AnnotationAwareAspectJAutoProxyCreator
		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);
			}
		}
	}

}
@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;
	}
	// 把AnnotationAwareAspectJAutoProxyCreator封装成RootBeanDefinition
	RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
	beanDefinition.setSource(source);
	beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
	beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
	// 把需要spring管理的bean放入beanDefinitionMap和beanDefinitionNames,分别是一个map和list容器。
	// spring在实例化bean时,就会遍历容器中的bean然后依次处理。
	registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
	return beanDefinition;
}

可以看出@EnableAspectJAutoProxy注解最主要的作用实际上就是通过@Import注解把AnnotationAwareAspectJAutoProxyCreator这个对象注入到spring容器中。

AnnotationAwareAspectJAutoProxyCreator的作用

类图

再看一下AnnotationAwareAspectJAutoProxyCreator类的结构图
SpringAOP中@EnableAspectJAutoProxy注解的作用_第1张图片

AnnotationAwareAspectJAutoProxyCreator类间接的实现了BeanPostProcessor接口,实现这个接口的目的就是为了能够通过前置处理器、后置处理器完成一些事情。

回顾IOC对象初始化

这部分代码来自IOC初始化bean对象的过程

	protected Object initializeBean(final String beanName, final 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()) {
			//调动后置处理器
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}
	@Override
	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			//从刚刚的类图中可以看出AnnotationAwareAspectJAutoProxyCreator类或者继承类中,肯定有重写这个方法
			Object current = processor.postProcessAfterInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

后置处理器

分析一下这段流程,AnnotationAwareAspectJAutoProxyCreator因为间接继承了抽象类AbstractAutoProxyCreator,而这个抽象类又间接实现了BeanPostPorcessor接口,所以在每个bean对象最后初始化的时候,通过postProcessAfterInitialization方法完成了AOP相关的处理。

总结

本文就没有继续接着postProcessAfterInitialization方法继续深入,因为还是打算另起一篇文章着重分析,可以先下一个结论,这个方法就是扫描并解析aop注解的入口,如果当前bean对象符合配置的增加规则,最终就会返回实现增加方法的代理类。

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