Spring 之 AOP 原理

概念

面向切面编程

Aspect Oriented Programming

底层使用了动态代理,指在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式。

原理

阅读源码

要实现 AOP 必须添加注解 @EnableAspectJAutoProxy,点击该注解,进入接口 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(AspectJAutoProxyRegistrar.class)

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.getBoolean("proxyTargetClass")) {
			AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
		}
		if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
			AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
		}
	}
}

看到 AspectJAutoProxyRegistrar 实现了 ImportBeanDefinitionRegistrar 接口,继续点击该接口

public interface ImportBeanDefinitionRegistrar {
	/**
	 * Register bean definitions as necessary based on the given annotation metadata of
	 * the importing {@code @Configuration} class.
	 * <p>Note that {@link BeanDefinitionRegistryPostProcessor} types may <em>not</em> be
	 * registered here, due to lifecycle constraints related to {@code @Configuration}
	 * class processing.
	 * @param importingClassMetadata annotation metadata of the importing class
	 * @param registry current bean definition registry
	 */
	public void registerBeanDefinitions(
			AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry);
}

该接口定义了可以给容器中自定义给 BeanDefinitionRegistry 注册组件

分析

利用 AspectJAutoProxyRegistrar 自定义给容器中注册 bean

在方法 registerBeanDefinitions 上打断点,以 DEBUG 执行之前的程序,在断点处

执行了 registerAspectJAnnotationAutoProxyCreatorIfNecessary() 方法,以单步模式继续下一步,看到依次执行了 registerAspectJAnnotationAutoProxyCreatorIfNecessary 的两个重载方法

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

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
	return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}

继续单步执行,执行到 registerOrEscalateApcAsRequired() 方法,

private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, 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;
}

在第 110 行判断,如果容器中有此 AUTO_PROXY_CREATOR_BEAN_NAME 自动代理的 bean 名字,那就。。。,否则执行第 121 行开始的创建工作

我这次由于是直接运行,容器里没有该 bean,所以在经过几次断言后,执行创建工作

创建 bean 的定义信息:
org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator

查看该组件 AnnotationAwareAspectJAutoProxyCreator

看给容器注册了什么组件,这个组件什么时候工作,这个组件的功能是什么?


有点复杂,未完待续…

没有修不好的电脑
原文地址:https://www.cnblogs.com/duniqb/p/12702441.html