Spring IOC源码:invokeBeanFactoryPostProcessors 后置处理器详解

news2024/11/24 1:38:11

前言

前面篇幅介绍了Bean配置的解析过程,包括注解、xml配置文件的解析。下面进入refresh方法中另一个重要的节点,即BeanFactoryPostProcessor的注册及其执行过程。

正文

进入refresh,前面篇幅已经介绍了obtainFreshBeanFactory(),接下来进入prepareBeanFactory(beanFactory);

public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			// 容器刷新前准备工作
			prepareRefresh();

			// Tell the subclass to refresh the internal bean factory.
			//创建Bean工厂,解析配置
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// bean工厂准备工作
			prepareBeanFactory(beanFactory);

			try {
				//拓展接口,留给子类进行实现拓展
				postProcessBeanFactory(beanFactory);

				// 注册执行,BeanFactoryPostProcessor
				invokeBeanFactoryPostProcessors(beanFactory);

				// 注册创建BeanPostProcessor
				registerBeanPostProcessors(beanFactory);

				// 这个方法主要作用就是使用国际化,定制不同的消息文本,比如定义了一个Person的Bean,它有name属性,我们需要在不同的国家展示对应国家所在语言名称,这时候就可以使用国际化了。
				initMessageSource();

				// Initialize event multicaster for this context.
				//初始化应用事件广播器
				initApplicationEventMulticaster();

				// Initialize other special beans in specific context subclasses.
				//拓展接口,留给子类进行实现拓展,springboot就对该方法进行了处理
				onRefresh();

				// Check for listener beans and register them.
				//将内部的、以及我们自定义的监听器添加到缓存中,为后续逻辑处理做准备。还有添加事件源到缓存中。
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				//实例化剩下非懒加载的Bean
				finishBeanFactoryInitialization(beanFactory);

				// Last step: publish corresponding event.
				//使用应用事件广播器推送上下文刷新完毕事件(ContextRefreshedEvent )到相应的监听器。
				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.
				//执行相关销毁方法
				destroyBeans();

				// Reset 'active' flag.
				//重置上下文刷新状态
				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...
				resetCommonCaches();
			}
		}
	}

prepareBeanFactory(beanFactory),见方法1详解

postProcessBeanFactory(beanFactory),见方法2详解

invokeBeanFactoryPostProcessors(beanFactory),见方法3详解

方法1:prepareBeanFactory

	protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		// 为当前Bean工厂设置类加载器
		beanFactory.setBeanClassLoader(getClassLoader());
		beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		//添加BeanPostProcessor后置处理器
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
		//跳过以下6个属性的自动注入
		//因为在ApplicationContextAwareProcessor后置处理器中通过setter注入
		beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
		beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
		beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
		beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

	  /**
		 * 在Spring自动装配的时候如果一个接口有多个实现类,并且都已经放到IOC中去了,
		 * 那么自动装配的时候就会出异常,因为spring不知道把哪个实现类注入进去,
		 * 但是如果我们自定义一个类,然后实现BeanFactoryPostProcessor接口
		 * 在该阶段调用这个方法,如果哪个地方要自动注入这个类型的对象的话,那么就注入进去我们指定的对象
	  */

		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
		beanFactory.registerResolvableDependency(ResourceLoader.class, this);
		beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
		beanFactory.registerResolvableDependency(ApplicationContext.class, this);

		// Register early post-processor for detecting inner beans as ApplicationListeners.
		注册事件监听器
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

		//如果当前BeanFactory包含loadTimeWeaver Bean,说明存在类加载期织入AspectJ,则把当前BeanFactory交给类加载期BeanPostProcessor实现类LoadTimeWeaverAwareProcessor来处理,从而实现类加载期织入AspectJ的目的。

		if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			// Set a temporary ClassLoader for type matching.
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}

		// 将以下Bean添加到一级缓存中
		if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
		}
	}

方法2:postProcessBeanFactory

	protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	}

这个方法没有实现内容,为拓展接口,留给子类实现。我们可以看到这个方法的参数为bean工厂对象,意味着我们可以往该工厂中添加后置处理器或者添加忽略类,在后续注入中跳过。也可以往三级缓存中添加信息。

例如:

	protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		if (this.servletContext != null) {
			beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext));
			beanFactory.ignoreDependencyInterface(ServletContextAware.class);
		}
		WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
		WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext);
	}

方法3:invokeBeanFactoryPostProcessors

	protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		//执行BeanFactoryPostProcessors
		PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

		// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
		// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
		if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}
	}

getBeanFactoryPostProcessors(),见方法4详解
invokeBeanFactoryPostProcessors(),见方法5详解

方法4:getBeanFactoryPostProcessors()

	public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
		return this.beanFactoryPostProcessors;
	}

我们看到这里是直接返回当前上下文的beanFactoryPostProcessors集合,默认情况下这里是空的,那我们如何自定义一个后置处理器并且往该集合存放呢?我们可以自定义ClassPathXmlApplicationContext子类,重写上述介绍的方法2postProcessBeanFactory方法,并往beanFactoryPostProcessors添加自定义后置处理器;

创建工厂后置处理器

package controller.main;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		Object teacher = beanFactory.getBean("teacher");
		System.out.println(teacher);
	}
}

自定义ClassPathXmlApplicationContext子类,并添加后置处理器

package controller.main;

import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyClassPathApplicationContext extends ClassPathXmlApplicationContext {

	public MyClassPathApplicationContext(String path){
		super(path);
	}

	@Override
	protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		this.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());
	}
}



启动测试

public class PersonTest {
	public static void main(String[] args) {
		MyClassPathApplicationContext applicationContext=new MyClassPathApplicationContext("application-scan.xml");
		StudentDao zdcDomain = (StudentDao) applicationContext.getBean("studentDao");
		System.out.println(zdcDomain);
	}
}

在这里插入图片描述

方法5:invokeBeanFactoryPostProcessors

public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

		// 存放BeanDefinitionRegistryPostProcessor类型已经执行过其postProcessBeanDefinitionRegistry方法的beanName
		Set<String> processedBeans = new HashSet<>();

		if (beanFactory instanceof BeanDefinitionRegistry) {
			
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			//存放普通的PostProcessors,就是非BeanDefinitionRegistryPostProcessor类型的
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
			//存放BeanDefinitionRegistryPostProcessor类型的处理器
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
			//遍历上下文中的beanFactoryPostProcessors集合,也就是我们在方法4中设置进去的后置处理器集合
			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					//执行postProcessBeanDefinitionRegistry方法
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					//添加到集合中
					registryProcessors.add(registryProcessor);
				}
				else {
					//添加到普通后置处理器集合中
					regularPostProcessors.add(postProcessor);
				}
			}

			// Do not initialize FactoryBeans here: We need to leave all regular beans
			// uninitialized to let the bean factory post-processors apply to them!
			// Separate between BeanDefinitionRegistryPostProcessors that implement
			// PriorityOrdered, Ordered, and the rest.
			//存放当前节点的集合
			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

			// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
			//获取我们bean工厂中类型为BeanDefinitionRegistryPostProcessor的beanName
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				//判断是否实现了PriorityOrdered接口
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					//添加到当前节点中
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					//添加名称到集合中
					processedBeans.add(ppName);
				}
			}
			//排序
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			//将当前节点的后置处理器添加到registryProcessors集合中
			registryProcessors.addAll(currentRegistryProcessors);
			//执行postProcessBeanDefinitionRegistry方法
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			//清空当前节点集合
			currentRegistryProcessors.clear();

			// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
			//重新获取类型为BeanDefinitionRegistryPostProcessor的beanName,为什么这里要重新获取一次,
			//我理解就是上面执行了post ProcessBeanDefinitionRegistry方法,可能存在往bean工厂中添加类型为
			//BeanDefinitionRegistryPostProcessor的BeanDefinition封装对象,所以这里算是更新数据吧
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				//判断执行过的processedBeans集合中不存在,并且实现了Ordered接口
				if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
					//添加到当前节点中
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					//添加名称到已执行集合中
					processedBeans.add(ppName);
				}
			}
			//排序
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			//将当前节点的后置处理器添加到registryProcessors集合中
			registryProcessors.addAll(currentRegistryProcessors);
			//执行postProcessBeanDefinitionRegistry方法
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);		
			//清空当前节点集合
			currentRegistryProcessors.clear();

			// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
			boolean reiterate = true;
			while (reiterate) {
				reiterate = false;
				//获取类型BeanDefinitionRegistryPostProcessor的beanName
				postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
				//这里主要获取没有实现PriorityOrdered和Order类的后置处理器
				for (String ppName : postProcessorNames) {
					if (!processedBeans.contains(ppName)) {
						currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
						processedBeans.add(ppName);
						reiterate = true;
					}
				}
				sortPostProcessors(currentRegistryProcessors, beanFactory);
				registryProcessors.addAll(currentRegistryProcessors);
				invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
				currentRegistryProcessors.clear();
			}

			// 执行postProcessBeanFactory(beanFactory)方法
			invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
		}

		else {
			// Invoke factory processors registered with the context instance.
			//没有实现BeanDefinitionRegistry接口的,直接执行postProcessBeanFactory(beanFactory)方法
			invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
		}

		// Do not initialize FactoryBeans here: We need to leave all regular beans
		// uninitialized to let the bean factory post-processors apply to them!
		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

		// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.
		//存放实现了PriorityOrdered接口的后置处理器
		List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		//存放实现了Ordered接口的BeanName
		List<String> orderedPostProcessorNames = new ArrayList<>();
		//存放没有实现了PriorityOrdered和Ordered接口的BeanName
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		for (String ppName : postProcessorNames) {
			//跳过之前已经执行过的,也就是BeanDefinitionRegistryPostProcessor类型的后置处理器
			if (processedBeans.contains(ppName)) {
				// skip - already processed in first phase above
			}
			//实现PriorityOrdered,添加至集合中
			else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				//getBean方法会从三级缓存获取,取不到会提交调用实例化初始化步骤
				priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
			}
			//实现Ordered,添加至集合中
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			//添加至集合中
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
		//排序并调用postProcessBeanFactory(beanFactory)方法
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

		// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
		//遍历从bean工厂中获取实例对象,取不到进行实例化操作
		List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String postProcessorName : orderedPostProcessorNames) {
			orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		//排序并调用postProcessBeanFactory(beanFactory)方法
		sortPostProcessors(orderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

		// Finally, invoke all other BeanFactoryPostProcessors.
		遍历从bean工厂中获取实例对象,取不到进行实例化操作
		List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		for (String postProcessorName : nonOrderedPostProcessorNames) {
			nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		//排序并调用postProcessBeanFactory(beanFactory)方法
		invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

		// Clear cached merged bean definitions since the post-processors might have
		// modified the original metadata, e.g. replacing placeholders in values...
		beanFactory.clearMetadataCache();
	}

sortPostProcessors(),见方法6详解

方法6:sortPostProcessors

	private static void sortPostProcessors(List<?> postProcessors, ConfigurableListableBeanFactory beanFactory) {
		Comparator<Object> comparatorToUse = null;
		if (beanFactory instanceof DefaultListableBeanFactory) {
			comparatorToUse = ((DefaultListableBeanFactory) beanFactory).getDependencyComparator();
		}
		if (comparatorToUse == null) {
			comparatorToUse = OrderComparator.INSTANCE;
		}
		postProcessors.sort(comparatorToUse);
	}

这里我们的比较器为AnnotationAwareOrderComparator,在前面文章中《<context:component-scan>源码详解》中的方法19有设置该比较器。
在这里插入图片描述
比较器部分代码如下:

	private int doCompare(Object o1, Object o2, OrderSourceProvider sourceProvider) {
		// 判断o1是否实现了PriorityOrdered接口
		boolean p1 = (o1 instanceof PriorityOrdered);
		// 判断o2是否实现了PriorityOrdered接口
		boolean p2 = (o2 instanceof PriorityOrdered);
		// 1.如果o1实现了PriorityOrdered接口, 而o2没有, 则o1排前面
		if (p1 && !p2) {
			return -1;
		}
		// 2.如果o2实现了PriorityOrdered接口, 而o1没有, 则o2排前面
		else if (p2 && !p1) {
			return 1;
		}

		// 3.如果o1和o2都实现(都没实现)PriorityOrdered接口
		// Direct evaluation instead of Integer.compareTo to avoid unnecessary object creation.
		// 拿到o1的order值, 如果没实现Ordered接口, 值为Ordered.LOWEST_PRECEDENCE
		int i1 = getOrder(o1, sourceProvider);
		// 拿到o2的order值, 如果没实现Ordered接口, 值为Ordered.LOWEST_PRECEDENCE
		int i2 = getOrder(o2, sourceProvider);
		// 4.通过order值(order值越小, 优先级越高)排序
		return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
	}

比较器的逻辑很简单,实现 PriorityOrdered 接口的优先级最高,如果两个对象都实现(都没实现)PriorityOrdered 接口,则根据 order 值(实现 Ordered 接口时,需要实现 getOrder() 方法,返回 order 值)来进行比较,order 值越小,优先级越高。

总结

本篇文章讲解了refresh方法中的prepareBeanFactory、postProcessBeanFactory、invokeBeanFactoryPostProcessors这三个方法。prepareBeanFactory其实就是BeanFactory工厂做一些准备工作,忽略某些值不被其它类所注入,以及添加一些后置处理器等。postProcessBeanFactory方法为拓展接口,提供子类进行拓展实现,我们也讲解了案例,通过编写实现ClassPathXmlApplicationContext子类重写该方法,并往该方法中添加后置处理器。invokeBeanFactoryPostProcessors方法主要是执行后置处理,主要分为两种类型的BeanFactoryPostProcessor,实现接口BeanDefinitionRegistryPostProcessor的和直接实现BeanFactoryPostProcessor接口的,BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的接口实现类。

梳理一下invokeBeanFactoryPostProcessors方法:
1.整个 invokeBeanFactoryPostProcessors 方法围绕两个接口,BeanDefinitionRegistryPostProcessor 和 BeanFactoryPostProcessor,其中 BeanDefinitionRegistryPostProcessor 继承了 BeanFactoryPostProcessor 。BeanDefinitionRegistryPostProcessor 主要用来在常规 BeanFactoryPostProcessor 检测开始之前注册其他 Bean 定义,说的简单点,就是 BeanDefinitionRegistryPostProcessor 具有更高的优先级,执行顺序在 BeanFactoryPostProcessor 之前。

2.整个 invokeBeanFactoryPostProcessors 方法操作了 3 种 bean 对象:
入参beanFactoryPostProcessors集合:
这个我们在方法4中有讲解过,主要取的是当前上下文对象,我们可以通过自定义上下文,并往该集合中添加后置处理器。

BeanDefinitionRegistryPostProcessor 接口实现类:
实现了 BeanDefinitionRegistryPostProcessor 接口,并且注册到 Spring IoC容器中。

常规 BeanFactoryPostProcessor 接口实现类:
实现了 BeanFactoryPostProcessor 接口,并且注册到 Spring IoC容器中。

3.该方法中的排序还引用了两个重要的接口PriorityOrdered 和 Ordered,其中 PriorityOrdered 继承了 Ordered,并且 PriorityOrdered 的优先级要高于 Ordered。实现 Ordered 接口需要重写 getOrder 方法,返回一个用于排序的 order 值,order 值的范围为 Integer.MIN_VALUE ~ Integer.MAX_VALUE,order 值越小优先级越高,Integer.MIN_VALUE 拥有最高优先级,而 Integer.MAX_VALUE 则对应的拥有最低优先级。

4.BeanFactoryPostProcessor中的优先级执行顺序如下:

第一优先级:上下文beanFactoryPostProcessors集合中的 BeanDefinitionRegistryPostProcessor,会先调用其 postProcessBeanDefinitionRegistry 方法。
第二优先级:beanFactory工厂中的bean,也就是我们配置文件或者注解所配置的Bean,实现了BeanDefinitionRegistryPostProcessor 、 PriorityOrdered 接口,会调用 postProcessBeanDefinitionRegistry 方法。
第三优先级:beanFactory工厂中的bean,实现BeanDefinitionRegistryPostProcessor 、Ordered 接口,会调用 postProcessBeanDefinitionRegistry 方法。
第四优先级:没有实现PriorityOrdered 或Ordered 接口的 BeanDefinitionRegistryPostProcessor 接口实现类,调用 postProcessBeanDefinitionRegistry 方法。
第五优先级:所有 BeanDefinitionRegistryPostProcessor 接口实现类,调用 postProcessBeanFactory 方法。
第六优先级:入参 beanFactoryPostProcessors 集合中的常规 BeanFactoryPostProcessor,调用 postProcessBeanFactory 方法。
第七优先级:beanFactory工厂中的bean,常规 BeanFactoryPostProcessor 接口实现类,并且实现了 PriorityOrdered 接口,调用 postProcessBeanFactory 方法。
第八优先级:beanFactory工厂中的bean,常规 BeanFactoryPostProcessor 接口实现类,并且实现了 Ordered 接口,调用 postProcessBeanFactory 方法。
第九优先级:没有实现PriorityOrdered 或Ordered 接口的 BeanFactoryPostProcessor 接口实现类,调用 postProcessBeanFactory 方法。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/14370.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

说出你常用的20个linux命令,你还是只会说ls、cat那20个命令吗?3分钟让你发现新大陆

服务器排障常用命令 &#x1f34a; 博客主页&#xff1a;作者主页 &#x1f34a; 简介&#xff1a;云计算领域优质创作者&#x1f3c6;、在校期间参与众多计算机ICT相关的省赛、国赛&#xff0c;斩获系列荣誉。考取华为资深工程师、红帽工程师、阿里云ACP云计算工程等系列认证。…

java图书推荐协同过滤算法网站

目 录 摘 要 2 Abstract 3 1绪论 6 1.1背景和意义 6 1.2国内外发展现状 6 2系统技术分析 7 2.1技术选型 7 2.2 MVC模式 7 3功能分析 8 3.1系统角色 8 3.2系统用例图 8 3.3系统功能 8 3.3.1网站前台功能 8 3.3.2网站后台功能 13 4系…

使用Android辅助功能AccessibilityService实现微信自动聊天【外挂插件】

本文是使用Android辅助功能AccessibilityService实现微信自动聊天demo&#xff1b; 只是为了跟深入的了解Android辅助功能, 提高自身的动手能力。 请勿用于商用&#xff0c;或非法用途。 动手前&#xff0c;基本的准备要求&#xff1a; 聊天机器人app demo&#xff0c;去操作…

供应PEG试剂Azide-PEG-Acrylamide,N3-PEG-ACA,叠氮-聚乙二醇-丙烯酰胺

1、名称 英文&#xff1a;Azide-PEG-Acrylamide&#xff0c;N3-PEG-ACA 中文&#xff1a;叠氮-聚乙二醇-丙烯酰胺 2、CAS编号&#xff1a;N/A 3、所属分类&#xff1a; Acrylate/Acrylamide PEG Azide PEG 4、分子量&#xff1a;可定制&#xff0c;5k、2k、10k、20k、3.4k…

DarkNet网络结构

一、darknet53网络结构图 文字版&#xff1a;卷积(下采样卷积1残差块)(下采样卷积2残差块)(下采样卷积8残差块)(下采样卷积8残差块)(下采样卷积4*残差块) 不难看出&#xff0c;darknet53就是重复堆叠下采样卷积n*残差块(n为残差块的个数)这个结构而组成的。而更基本的结构就是…

数据库视图的基本操作(sql语句)

表视图的增删改查&#xff08;sql语句&#xff09; 概念&#xff1a;视图是一张虚拟表&#xff0c;它是从数据库的一张或多张表中导出的表&#xff0c;其内容由查询语句定义。 作用&#xff1a; 简单性、安全性、逻辑数据独立性&#xff1b;如果应用建立在视图上&#xff0c…

Node.js学习19~37(模块化)

1 模块化的基本概念 1.1 什么是模块化 模块化是指解决一个复杂问题时&#xff0c;自顶向下逐层把系统划分成若干模块的过程。对于整个系统来说&#xff0c;模块是可组合、分解和更换的单元。 编程领域中的模块化 编程领域中的模块化&#xff0c;就是遵守固定的规则&#xf…

【Pytorch with fastai】第 15 章 :深入探讨应用程序架构

&#x1f50e;大家好&#xff0c;我是Sonhhxg_柒&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f4dd;个人主页&#xff0d;Sonhhxg_柒的博客_CSDN博客 &#x1f4c3; &#x1f381;欢迎各位→点赞…

Docker概念基本介绍以及安装

目录 一、Docker概述 1.1Docker是什么 1.2Docker和虚拟机的区别 1.3使用场景 1.4 Docker 三要素&#xff08;核心组件&#xff09; 1.5六大名称空间 1.6 Docker引擎 1.7资源控制——cgroups 1.8容器特性 1.9 容器小的架构体系 二、Docker和虚拟化的区别 三、dock…

MATLAB循环类型

MATLAB 提供以下类型的循环处理循环的要求。点击链接&#xff0c;查看个循环类型的细节&#xff1a; 循环类型描述while 循环一个给定的条件为真时重复语句或语句组。测试条件才执行循环体。for 循环执行的语句序列多次缩写管理循环变量的代码。nested 循环可以使用一个或多个…

2022年深度学习最新研究成果

一、开源深度学习编译器 二、 开源深度学习加速器 三、AITemplate引擎 四、微型机器学习框架 参考文献&#xff1a;https://arxiv.org/pdf/1510.00149.pdf 五、Contrastive Learning 对比学习综述 六、Diffusion Model 扩散模型综述 Diffusion Models: A Comprehensive Surv…

【Python百日进阶-WEB开发】Day180 - Django案例:12用户登录

文章目录十、异步发送短信验证码 - 异步方案Celery10.1 生产者消费者设计模式10.2 Celery介绍10.3 Celery介绍和使用10.3.1十一、用户账号 登录11.1 用户登录11.1.1 用户登录逻辑分析11.1.2 用户登录接口设计和定义11.1.3 用户登录后端逻辑11.2 多账号登录11.2.1 自定义用户认证…

实战三:基于LGB实现车联网大数据碰撞识别 代码+数据(非常详细可作为毕设)

项目介绍&#xff1a; 使用的数据为采集车辆信号。车辆信息非常多&#xff0c;而且用户路况信息和使用偏好千人千面&#xff0c;很难找到一种准确识别碰撞的方法&#xff0c;希望参赛者通过车联网大数据识别车辆碰撞和碰撞时间。车辆标签信息如下&#xff1a; 车号LabelCollec…

SpringBoot SpringBoot 开发实用篇 4 数据层解决方案 4.5 SpringBoot 整合 Redis

SpringBoot 【黑马程序员SpringBoot2全套视频教程&#xff0c;springboot零基础到项目实战&#xff08;spring boot2完整版&#xff09;】 SpringBoot 开发实用篇 文章目录SpringBootSpringBoot 开发实用篇4 数据层解决方案4.5 SpringBoot 整合 Redis4.5.1 环境准备4.5.2 使用…

多系统-单点登录测试

单点登录 文章目录单点登录单点登录 单点登录全程Single Sign On&#xff08;SSO&#xff09;,在多个应用系统中&#xff0c;用户只需要登录一次就可以访问所有相互信任的应用系统&#xff0c;包括单点登录和单点注销两部分&#xff0c;是目前比较流行的企业业务整合的解决方案…

SpringBoot SpringBoot 开发实用篇 4 数据层解决方案 4.1 内置数据源

SpringBoot 【黑马程序员SpringBoot2全套视频教程&#xff0c;springboot零基础到项目实战&#xff08;spring boot2完整版&#xff09;】 SpringBoot 开发实用篇 文章目录SpringBootSpringBoot 开发实用篇4 数据层解决方案4.1 内置数据源4.1.1 现有数据层解决方案4.1.2 小结…

波束形成,通过matlab仿真不同参数的波束形成以及旁絆级

目录 1.算法概述 2.仿真效果预览 3.核心MATLAB代码预览 4.完整MATLAB程序 1.算法概述 波束成形技术&#xff08;Beam Forming&#xff0c;BF&#xff09;可分为自适应波束成形、固定波束和切换波束成形技术。固定波束即天线的方向图是固定的&#xff0c;把IS-95中的三个120…

同花顺_代码解析_技术指标_B

本文通过对同花顺中现成代码进行解析&#xff0c;用以了解同花顺相关策略设计的思想 目录 BBI BBIBOLL BETA BIAS BIASFS BOLL BOLLFS BTI BBI 多空指标 多空指标:(收盘价的M1日简单移动平均收盘价的M2日简单移动平均收盘价的M3日简单移动平均收盘价的M4日简单移动平均…

G蛋白偶联受体/激酶/离子通道——高通量筛选

GPCR Library &#xff08;含54,080 种化合物&#xff09;用于发现新的GPCR配体 G蛋白偶联受体 (GPCR)是新药研发人员关注的一类重要蛋白&#xff0c;三分之一FDA 批准药物靶向 GPCR。GPCR Library 涵盖了广泛的 GPCR 靶标&#xff0c;库中化合物具有新颖性和高度多样性的特…

C++不知算法系列之集结常规算法思想

1. 前言 数据结构和算法是程序的 2 大基础结构&#xff0c;如果说数据是程序的汽油&#xff0c;算法则就是程序的发动机。 什么是数据结构&#xff1f; 指数据之间的逻辑关系以及在计算机中的存储方式&#xff0c;数据的存储方式会影响到获取数据的便利性。 现实生活中&…