首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringAop源码分析(基于注解)一

SpringAop源码分析(基于注解)一

作者头像
炳臣
发布2019-10-24 18:51:46
4480
发布2019-10-24 18:51:46
举报
文章被收录于专栏:一块自留地一块自留地

一、AOP原理

关于Aop的原理,简单来讲无非就是用代理模式为目标对象生产代理对象,对原有的方法进行增强。看上去挺简单,但在Spring中,有许多细节是要注意到的。比如:

  • AOP是怎么触发的?
  • 代理对象是什么时候生成的?
  • 怎么发现目标对象?
  • 怎么判断目标对象的哪些方法需要增强?
  • 怎么实现前置通知,后置通知,环绕通知?
  • 一个方法有多个切面代理怎么处理?

我们可以带着这些疑问来看源码,有助于我们的理解。

二、AOP术语

AOP的术语有很多并且很重要,看源码之前还是要对术语有所了解,这里就不一一介绍了

三、demo

先来一个注解方式实现AOP的demo,然后我们后面根据这个demo来分析源码。

@Aspect
@Component
@EnableAspectJAutoProxy
public class LogAspect {

	@Before("execution(* com.mydemo.work.StudentController.getName(..))")
	public void doBefore() {
		System.out.println("========before");
	}

	@After("execution(* com.mydemo.work.StudentController.getName(..))")
	public void doAfter() {
		System.out.println("========after");
	}
}

这是一个简单的日志AOP,对StudentController类的getName(..)方法进行增强,在这个方法执行前后会打印不同的信息。

四、准备

可以看到,在最开始的demo工程中,为了开启AOP功能,我使用了一个@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}.
	 */
	//代理的实现方式,true为CGLIB,false为JDK,默认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
	 */
	//代理的暴露方式,解决内部调用不能使用代理的场景,默认为false
	boolean exposeProxy() default false;

}

可以看到这个注解有2个属性proxyTargetClassexposeProxy。除此之外还使用@Import注解引入了一个配置类AspectJAutoProxyRegistrar。 我们来看下这个关键的类:

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) {

<1>     //注册一个专门管理AOP的Bean到IOC容器中
	AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

	//获取@EnableAspectJAutoProxy注解
<2>	AnnotationAttributes enableAspectJAutoProxy =
			AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
	if (enableAspectJAutoProxy != null) {
		//处理该注解的2个属性
		if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
			AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
		}
		if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
			AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
		}
	}
	}

}

这段代码看起来不难,我们肯定要有一个处理AOP逻辑的代码类,那在Spring中就要把这个类交给Spring容器来管理,所以有了第<1>步。我们来看下详细逻辑, 直接追踪到最后调用的地方:

//AopConfigUtils.java

/**
 * The bean name of the internally managed auto-proxy creator.
 */
public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
			"org.springframework.aop.config.internalAutoProxyCreator";

@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry,
		@Nullable Object source) {

	Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
	
	//检查容器中是否已经注册过该Bean
	if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
		//注册过,判断Bean的ClassName是否为AnnotationAwareAspectJAutoProxyCreator
		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;
	}
	//没有注册过,则注册
	//cls = AnnotationAwareAspectJAutoProxyCreator.class
	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这个类注册到SpringIOC容器中,实际上AnnotationAwareAspectJAutoProxyCreator这个类的BeanName就是org.springframework.aop.config.internalAutoProxyCreator

五、注册BeanPostProcessor

现在我们已经有了处理AOP的类AnnotationAwareAspectJAutoProxyCreator, 先来看下这个类的继承图:

可以看出,这个类间接实现了BeanPostProcessor接口,这个接口大家应该很熟悉,是Spring的一个后置处理器接口。

public interface BeanPostProcessor {

	//在Bean的初始化前回调
	@Nullable
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	
	//在Bean的初始化之后回调
	@Nullable
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

}

BeanPostProcessor 可以理解为是 Spring 的一个工厂钩子(其实 Spring 提供一系列的钩子,如 Aware 、InitializingBean、DisposableBean),它是 Spring 提供的对象实例化阶段强有力的扩展点,允许 Spring 在实例化 bean 的前后对其进行修改,比较常见的使用场景是处理标记接口实现类或者为当前对象提供代理实现(例如 AOP)。 一般普通的 BeanFactory 是不支持自动注册 BeanPostProcessor 的,需要我们手动调用addBeanostProcessor()方法进行注册。如下:

beanFactory.addBeanPostProcessor(BeanPostProcessor beanPostProcessor)

注册后的 BeanPostProcessor 适用于所有该 BeanFactory 创建的 bean,但是 ApplicationContext 可以在其 bean 定义中自动检测所有的 BeanPostProcessor 并自动完成注册,同时将他们应用到随后创建的任何 Bean 中。

在这里我们的容器是ApplicationContext,所以会自动检测所有BeanPostProcessor并完成注册。接下来我们就看下自动注册的逻辑。

我们都知道在 ApplicationContext 中有一个重要的方法refresh(),会在容器启动时执行,代码如下:

//AbstractApplicationContext.java

public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
	// Prepare this context for refreshing.
	//1、调用spring容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识
	prepareRefresh();

	// Tell the subclass to refresh the internal bean factory.
	//2、创建并初始化 BeanFactory   ---->  获取IOC容器
	ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

	// Prepare the bean factory for use in this context.
	//3、填充BeanFactory功能。    配置容器特性,例如类加载器、事件处理器等
	prepareBeanFactory(beanFactory);

	try {
		// Allows post-processing of the bean factory in context subclasses.
		//4、提供子类覆盖的额外处理,即子类处理自定义的BeanFactoryPostProcess
		postProcessBeanFactory(beanFactory);

		// Invoke factory processors registered as beans in the context.
		//5、激活各种BeanFactory处理器。 调用所有注册的BeanFactoryPostProcessor的Bean
		invokeBeanFactoryPostProcessors(beanFactory);

		// Register bean processors that intercept bean creation.
		//6、注册BeanPostProcessor后置处理器.
		//AutowiredAnnotationBeanPostProcessor(处理被@Autowired注解修饰的bean并注入)
		//RequiredAnnotationBeanPostProcessor(处理被@Required注解修饰的方法)
		//CommonAnnotationBeanPostProcessor(处理@PreDestroy、@PostConstruct、@Resource等多个注解的作用)等
		//AutoProxyCreator(aop代理 @Aspect)
		registerBeanPostProcessors(beanFactory);

		// Initialize message source for this context.
		//7、初始化信息源,和国际化相关.
		initMessageSource();

		// Initialize event multicaster for this context.
		//8、初始化容器事件传播器.
		initApplicationEventMulticaster();

		// Initialize other special beans in specific context subclasses.
		//9、调用子类的某些特殊Bean初始化方法
		onRefresh();

		// Check for listener beans and register them.
		//10、为事件传播器注册事件监听器.
		registerListeners();

		// Instantiate all remaining (non-lazy-init) singletons.
		//11、初始化剩下的单例Bean(非延迟加载的)
		finishBeanFactoryInitialization(beanFactory);

		// Last step: publish corresponding event.
		//12、初始化容器的生命周期事件处理器,并发布容器的生命周期事件
		finishRefresh();
	}

	catch (BeansException ex) {
		if (logger.isWarnEnabled()) {
			logger.warn("Exception encountered during context initialization - " +
					"cancelling refresh attempt: " + ex);
		}

		// Destroy already created singletons to avoid dangling resources.
		//13、销毁已创建的Bean
		destroyBeans();

		// Reset 'active' flag.
		//14、取消refresh操作,重置容器的同步标识。
		cancelRefresh(ex);

		// Propagate exception to caller.
		throw ex;
	}

	finally {
		// Reset common introspection caches in Spring's core, since we
		// might not ever need metadata for singleton beans anymore...
		//15、重设公共缓存
		resetCommonCaches();
	}
	}
	}

代码很长,其他的暂时先不管,直接看第6步registerBeanPostProcessors(beanFactory),这行代码是需要我们关注的,它就是对 BeanPostProcessors 进行自动注册的方法。

//PostProcessorRegistrationDelegate.java

public static void registerBeanPostProcessors(
		ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

<1>	//获取容器中所有的BeanPostProcessor名称
	String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

	// Register BeanPostProcessorChecker that logs an info message when
	// a bean is created during BeanPostProcessor instantiation, i.e. when
	// a bean is not eligible for getting processed by all BeanPostProcessors.
	int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
	//注册BeanPostProcessorChecker到容器中
	beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

	// Separate between BeanPostProcessors that implement PriorityOrdered,
	// Ordered, and the rest.
	List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
	List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
	List<String> orderedPostProcessorNames = new ArrayList<>();
	List<String> nonOrderedPostProcessorNames = new ArrayList<>();
<2>	//遍历所有BeanPostProcessor名称
	for (String ppName : postProcessorNames) {
		//判断当前BeanPostProcessor是否实现PriorityOrdered接口
		if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			priorityOrderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		//判断当前BeanPostProcessor是否实现Ordered接口
		else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
			orderedPostProcessorNames.add(ppName);
		}
		else {
			nonOrderedPostProcessorNames.add(ppName);
		}
	}

	// First, register the BeanPostProcessors that implement PriorityOrdered.
<3>	//对实现PriorityOrdered接口的BeanPostProcessors进行排序
	sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
	//注册
	registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

	// Next, register the BeanPostProcessors that implement Ordered.
	List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
	for (String ppName : orderedPostProcessorNames) {
		BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
		orderedPostProcessors.add(pp);
		if (pp instanceof MergedBeanDefinitionPostProcessor) {
			internalPostProcessors.add(pp);
		}
	}
<4>	//对实现Ordered接口的BeanPostProcessors进行排序
	sortPostProcessors(orderedPostProcessors, beanFactory);
	//注册
	registerBeanPostProcessors(beanFactory, orderedPostProcessors);

	// Now, register all regular BeanPostProcessors.
	List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
	for (String ppName : nonOrderedPostProcessorNames) {
		BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
		nonOrderedPostProcessors.add(pp);
		if (pp instanceof MergedBeanDefinitionPostProcessor) {
			internalPostProcessors.add(pp);
		}
	}
<5>	//注册没有实现排序接口的BeanPostProcessors
	registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

	// Finally, re-register all internal BeanPostProcessors.
<6>	//排序并注册内部BeanPostProcessors
	sortPostProcessors(internalPostProcessors, beanFactory);
	registerBeanPostProcessors(beanFactory, internalPostProcessors);

	// Re-register post-processor for detecting inner beans as ApplicationListeners,
	// moving it to the end of the processor chain (for picking up proxies etc).
	beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}
//PostProcessorRegistrationDelegate.java

//具体注册方法
private static void registerBeanPostProcessors(
		ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {

	for (BeanPostProcessor postProcessor : postProcessors) {
	        //核心
		beanFactory.addBeanPostProcessor(postProcessor);
	}
}

这段代码看起来很长,但其实很简单。

  • <1>处,先从容器中获取所有BeanPostProcessors类型的BeanName。 在上一步我们已经通过@EnableAspectJAutoProxy注解把处理AOP的Bean->internalAutoProxyCreator给注册到容器中了,所以这里可以拿到。
  • <2>处,遍历所有BeanName,进行分类,分为4类。
    • 实现PriorityOrdered接口的BeanPostProcessors
    • 实现Ordered接口的BeanPostProcessors
    • 没有实现排序接口的BeanPostProcessors
    • Spring内部的BeanPostProcessors

    我们通过@EnableAspectJAutoProxy注解注册的internalAutoProxyCreator是属于第2类。

  • <3>处,排序并注册实现PriorityOrdered接口的BeanPostProcessors
  • <4>处,排序并注册实现Ordered接口的BeanPostProcessors
  • <5>处,注册没有实现排序接口的BeanPostProcessors
  • <6>处,排序并注册Spring内部的BeanPostProcessors

至此,我们已经把所有的BeanPostProcessors注册到了容器ApplicationContext中,包括我们专门处理AOP的BeanPostProcessors,接下来就可以使用了。

总结

总结一下到目前位置的步骤:

  • 通过@EnableAspectJAutoProxy注解把专门处理AOP的Bean注册到IOC容器中
  • 通过ApplicationContext.refresh()方法把专门处理AOP的BeanPostProcessors注册到IOC容器中。

那这两步之间有什么关联呢?

  • 首先,我们要把专门处理AOP的Bean注册到IOC容器中,交给spring来管理。-->@EnableAspectJAutoProxy
  • 然后,通过IOC容器的getBean()方法生成实例AnnotationAwareAspectJAutoProxyCreator。-->refresh()
  • 最后,因为该实例间接实现了BeanPostProcessors,而BeanPostProcessors想起作用的话,必须要调用beanFactory.addBeanPostProcessor()方法注册到容器中。-->refresh()

下篇文章我们将分析AnnotationAwareAspectJAutoProxyCreator类是怎么起作用的。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年10月18日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、AOP原理
  • 二、AOP术语
  • 三、demo
  • 四、准备
  • 五、注册BeanPostProcessor
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档