Анализ исходного кода SpringAop (на основе аннотаций) 1

Java

В предыдущей статье я изучил исходный код Spring Ioc и имел предварительное представление о принципе работы Spring, поэтому был готов ковать железо, пока горячо, и читать исходники SpringAop, следующие статьи будут посвящены Aop.

Во-первых, принцип АОП

Что касается принципа Aop, то, говоря простым языком, это не что иное, как использование прокси-режима для создания прокси-объектов для целевого объекта и улучшения исходного метода. Это кажется простым, но в Spring есть много деталей, о которых нужно знать. Например:

  • Как запускается АОП?
  • Когда создается прокси-объект?
  • Как найти целевой объект?
  • Как определить, какие методы целевого объекта необходимо улучшить?
  • Как реализовать предварительное уведомление, последующее уведомление и объемное уведомление?
  • Как работать с несколькими аспектными прокси для метода?

Мы можем посмотреть исходный код с этими вопросами, которые помогут нашему пониманию.

2. Терминология АОП

Есть много и очень важных терминов АОП. Прежде чем читать исходный код, вам все равно нужно понять термины. Я не буду вводить их здесь по одному. Заинтересованные студенты могут двигатьсяТерминология SpringAOP

3. демо

Во-первых, давайте воспользуемся методом аннотации для реализации демонстрации АОП, а затем мы проанализируем исходный код в соответствии с этой демонстрацией позже.

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

Это простой АОП ведения журнала, который расширяет метод getName(..) класса StudentController и выводит различную информацию до и после выполнения этого метода.

4. Подготовка

Как видите, в начальном демонстрационном проекте для включения функции АОП я использовал@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 атрибутаproxyTargetClassа такжеexposeProxy. Кроме того, класс конфигурации вводится с помощью аннотации @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);
		}
	}
	}

}

Этот код не выглядит сложным, у нас должен быть класс кода, который обрабатывает логику АОП, в Spring этот класс должен быть передан в контейнер Spring для управления, поэтому есть шаг . Давайте посмотрим на подробную логику, Проследите непосредственно до места, где был сделан последний звонок:

//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.На самом деле BeanName класса AnnotationAwareAspectJAutoProxyCreatororg.springframework.aop.config.internalAutoProxyCreator.

5. Зарегистрируйте BeanPostProcessor

Теперь у нас есть классы, которые обрабатывают АОП.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 применяется ко всем bean-компонентам, созданным этим BeanFactory, ноApplicationContextВсе BeanPostProcessors могут быть автоматически обнаружены в их определениях bean-компонентов и автоматически зарегистрированы, применяя их к любому 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();
	}
	}
	}

Код очень длинный, остальное пока проигнорируем, просто посмотрите на шаг 6registerBeanPostProcessors(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);
	}
}

Этот код выглядит длинным, но на самом деле он довольно прост.

  • , сначала получить все из контейнераBeanPostProcessorsBeanName типа.
    На предыдущем шаге мы прошли@EnableAspectJAutoProxyАннотации обрабатывают AOP Bean->internalAutoProxyCreatorОн прописан в контейнере, поэтому его можно получить здесь.

  • В все имена BeanName просматриваются и классифицируются по 4 категориям.

    • BeanPostProcessors, реализующие интерфейс PriorityOrdered
    • BeanPostProcessors, реализующие интерфейс Ordered
    • BeanPostProcessors, которые не реализуют интерфейс сортировки
    • BeanPostProcessors внутри Spring

    мы проходим@EnableAspectJAutoProxyАннотированный зарегистрированныйinternalAutoProxyCreatorотносится ко 2 категории.

  • В отсортируйте и зарегистрируйте BeanPostProcessors, которые реализуют интерфейс PriorityOrdered.

  • В отсортируйте и зарегистрируйте BeanPostProcessors, которые реализуют интерфейс Ordered.

  • В зарегистрируйте BeanPostProcessors, которые не реализуют интерфейс сортировки.

  • В отсортируйте и зарегистрируйте внутренние BeanPostProcessors Spring.

На данный момент мы зарегистрировали все BeanPostProcessors в контейнере.ApplicationContext, включая наши BeanPostProcessors, специализирующиеся на обработке AOP, которые можно использовать далее.

总结

Подводя итог шагам на данный момент:

  • пройти через@EnableAspectJAutoProxyАннотация регистрирует bean-компонент, который обрабатывает AOP, в контейнере IOC.
  • пройти черезApplicationContext.refresh()Метод регистрирует BeanPostProcessors, специализирующиеся на обработке AOP, в контейнере IOC.

Итак, какова связь между этими двумя шагами?

  • Во-первых, нам нужно зарегистрировать bean-компоненты, которые имеют дело с AOP, в IOC-контейнере и передать его Spring для управления. -->@EnableAspectJAutoProxy

  • Затем через IOC-контейнерgetBean()метод создания экземпляраAnnotationAwareAspectJAutoProxyCreator. -->обновить()

  • Наконец, поскольку экземпляр косвенно реализуетBeanPostProcessors,а такжеBeanPostProcessorsДля работы необходимо позвонитьbeanFactory.addBeanPostProcessor()метод зарегистрирован в контейнере. -->обновить()

В следующей статье мы проанализируемAnnotationAwareAspectJAutoProxyCreatorКак проходят занятия.