spring(五)----------invokeBeanFactoryPostProcessors方法

虽然我们前面的文章提到,第三方框架mybatis对于spring的集成使用的是

FactoryBean+ImportBeanDefifinitionRegistrar+@Import对mapper进行注入的方案。

但对于动态注册/修改BeanDefinition的方式仍然存在两种方式:

1)、BeanFactoryPostProcess

可以修改BeanDefinition、注册不完整的BeanDefinition(这里后面会提到为什么是不完整的)

2)、BeanDefinitionRegistryPostProcessor

可以注册修改BeanDefinition。(功能和ImportBeanDefifinitionRegistrar类似)(BeanFactoryPostProcess的子接口)

而spring中对于我们自己注入的对象,在invokeBeanFactoryPostProcessors方法中会去处理这两种动态注入BeanDefinition的方式(当然这个方法不止这个功能)。我们要解决之前几篇文章遗留下来的问题,需要先看看invokeBeanFactoryPostProcessors方法是如何运行的。

1、探究两个接口实现方法的执行顺序

我们从几个因素出发,探究父接口BeanFactoryPostProcess和子接口BeanDefinitionRegistryPostProcessor对应的方法的执行时机:

1)、对象注入方式:调用容器api、使用注解、动态注册BeanDefinition

2)、是否实现PriorityOrdered接口

为此我们准备了几个类用来测试

A类:

@Component
public class A implements BeanFactoryPostProcessor {
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
//		BeanDefinitionBuilder k = BeanDefinitionBuilder.genericBeanDefinition(K.class);
//
//		DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) beanFactory;
//		defaultListableBeanFactory.registerBeanDefinition("k",k.getBeanDefinition());

		/*BeanDefinitionBuilder x = BeanDefinitionBuilder.genericBeanDefinition(X.class);
		DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) beanFactory;
		defaultListableBeanFactory.registerBeanDefinition("x",x.getBeanDefinition());*/
		System.out.println("A --impl BeanFactoryPostProcessor--- by @Component ---- Override postProcessBeanFactory");
	}
}

B类:

public class B implements BeanFactoryPostProcessor {
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

		System.out.println("B--impl BeanFactoryPostProcessor---By api----Override postProcessBeanFactory");
	}
}

C类:

public class C implements BeanDefinitionRegistryPostProcessor {
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		System.out.println("C--impl BeanDefinitionRegistryPostProcessor---by api ----Override postProcessBeanFactory");

		//log.debug("c-s api parent postProcessBeanFactory");
	}

	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		System.out.println("C --impl BeanDefinitionRegistryPostProcessor---by api ----Override postProcessBeanDefinitionRegistry");

		//log.debug("c-s api subclass postProcessBeanDefinitionRegistry");
//		BeanDefinitionBuilder x= BeanDefinitionBuilder.genericBeanDefinition(X.class);
//		registry.registerBeanDefinition("x",x.getBeanDefinition());
	}
}

D类:


@Component
public class D implements BeanDefinitionRegistryPostProcessor {
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		System.out.println("D -- impl BeanDefinitionRegistryPostProcessor--- by @Component ---- Override postProcessBeanFactory");

		//log.debug("d-s scan parent postProcessBeanFactory");
	}

	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {

		System.out.println("D -- impl BeanDefinitionRegistryPostProcessor--- by @Component ---- Override postProcessBeanDefinitionRegistry");
		//log.debug("d-s scan subclass postProcessBeanDefinitionRegistry register E F");
		BeanDefinitionBuilder e = BeanDefinitionBuilder.genericBeanDefinition(E.class);
		BeanDefinitionBuilder f= BeanDefinitionBuilder.genericBeanDefinition(F.class);


//		AbstractBeanDefinition j = (AbstractBeanDefinition) registry.getBeanDefinition("j");
//		j.setBeanClass(L.class);

		registry.registerBeanDefinition("e",e.getBeanDefinition());
		registry.registerBeanDefinition("f",f.getBeanDefinition());

	}
}

E类:

public class E implements BeanFactoryPostProcessor {
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

		System.out.println("E -- impl BeanFactoryPostProcessor--- by BeanDefinition ---- Override postProcessBeanFactory");

		//log.debug("e-p bd parent postProcessBeanFactory");
	}
}

F类:


public class F implements BeanDefinitionRegistryPostProcessor {
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		System.out.println("F-- impl BeanDefinitionRegistryPostProcessor---by BeanDefinition ---- Override postProcessBeanFactory");

		//log.debug("f-s bd parent postProcessBeanFactory");
	}

	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		System.out.println("F -- impl BeanDefinitionRegistryPostProcessor--- by BeanDefinition----Override postProcessBeanDefinitionRegistry");

		//log.debug("f-s bd subclass postProcessBeanDefinitionRegistry");
	}
}

H类:


@Component
public class H implements BeanFactoryPostProcessor, PriorityOrdered {
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		System.out.println("H -- impl BeanFactoryPostProcessor + PriorityOrdered--- by @Component----Override postProcessBeanFactory");

		//log.debug("h-p scan parent postProcessBeanFactory PriorityOrdered");
	}

	@Override
	public int getOrder() {
		return 0;
	}
}

I类:

@Component
public class I implements BeanDefinitionRegistryPostProcessor, PriorityOrdered {
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		System.out.println("I --impl BeanDefinitionRegistryPostProcessor + PriorityOrdered--- by @Component ---- Override postProcessBeanFactory");

		//log.debug("i-s scan parent postProcessBeanFactory PriorityOrdered");
	}

	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		System.out.println("I -- impl BeanDefinitionRegistryPostProcessor + PriorityOrdered---by @Component ----Override postProcessBeanDefinitionRegistry");

		//log.debug("i-s scan subclass postProcessBeanDefinitionRegistry PriorityOrdered");
//		AbstractBeanDefinition j = (AbstractBeanDefinition) registry.getBeanDefinition("j");
//		j.setBeanClass(L.class);

//		BeanDefinitionBuilder x= BeanDefinitionBuilder.genericBeanDefinition(X.class);
//		registry.registerBeanDefinition("x",x.getBeanDefinition());
	}

	@Override
	public int getOrder() {
		return 0;
	}
}

ApplicationContextTest类
注意:B、C是通过Api方式注入的,是加入一个BeanFactoryPostProcessor,而非注册BeanDefinition,所以这两个类不会转为BeanDefinition put到BeanDefinitionMap,也不会实例化为Bean放进单例池,但是这两个类会去执行其父子实现类

public class ApplicationContextTest {


    public static void main(String[] args) {


        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
		//api方式注入B
		context.addBeanFactoryPostProcessor(new B());
		context.addBeanFactoryPostProcessor(new C());
		//手动api注入时,需要自己调用AnnotationConfigApplicationContext的无参构造,并register方法传入配置类
		context.register(ContextConfig.class);
		context.refresh();
	}
}

ContextConfig类

@Component
@ComponentScan("com.spring.demo.invokeBeanFactoryPostProcessors")
public class ContextConfig {
}

启动,先直接看结果:

从结果可以推断出:

1)、子接口实现方法>>父接口方法

2)、api方式>>实现了PriorityOrdered接口>>通过注解注入>>动态注册BeanDefinition

3)、实现子接口比实现父接口更快执行

注意:其中还有spring内置类的执行,只是这里没有去打印出来。

此时我们直接进来源码

调用链:

refresh()-----》invokeBeanFactoryPostProcessors-------》
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors

源码:


	/**
	 * 功能:执行实现了BeanFactoryPostProcessor/其子接口BeanDefinitionRegistryPostProcessor的方法
	 *
	 * */
	public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

		/**
		 * 用来存放已经处理完的BeanFactoryPostProcessor以及其子类BeanDefinitionRegistryPostProcessor
		 * 防止重复执行
		 * 前提:这些类不是使用api进行注册的  留个疑问,为什么呢????(因为这些类不会出现重复执行的情况)
		 * */
		// Invoke BeanDefinitionRegistryPostProcessors first, if any.
		Set<String> processedBeans = new HashSet<>();

		//beanFactory---DefaultListableBeanFactory实现BeanDefinitionRegistry,所以会进入
		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			//存储实现了BeanFactoryPostProcessor的对象
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
			//存储实现了BeanDefinitionRegistryPostProcessor的对象
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

			//1、处理通过api注册的beanFactoryPostProcessors对象的子类方法
			// beanFactoryPostProcessors:传入通过api注册的beanFactoryPostProcessors对象
			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				//如果实现的是子接口
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					//执行子接口的实现方法
					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.
			//存放当前需要执行的BeanDefinitionRegistryPostProcessor
			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();


			//2、执行spring内置注册的几个BeanDefinition中实现了BeanDefinitionRegistryPostProcessors且implement PriorityOrdered的对象
			// 即执行ConfigurationClassPostProcessor类的子类方法(实现了BeanDefinitionRegistryPostProcessor子接口)
			// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
			//根据BeanDefinitionRegistryPostProcessor类型去BeanDefinitionMap中查询,存在则返回名字
			//此时会去找到spring内置注册的几个BeanDefinition,
			// 最后会返回一个名为org.springframework.context.annotation.internalConfigurationAnnotationProcessor(类型为ConfigurationClassPostProcessor)
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);

			for (String ppName : postProcessorNames) {
				//ConfigurationClassPostProcessor有实现PriorityOrdered接口,为true
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					//加入到processedBeans(已处理集合)、currentRegistryProcessors(当前处理集合)
					//调用getBean方法去实例化这个ConfigurationClassPostProcessor,并存到单例池中
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			//对currentRegistryProcessors集合里面的对象进行排序
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			//将当前处理currentRegistryProcessors集合加入到存放父接口对象集合registryProcessors中(合并)
			//为什么要放到registryProcessors??(因为下面这行代码invokeBeanDefinitionRegistryPostProcessors(),只会执行其子接口方法,不会执行父接口方法)
			registryProcessors.addAll(currentRegistryProcessors);
			//遍历执行当前处理集合对象的子接口实现方法(注意由于这里只有ConfigurationClassPostProcessor,则执行了其子类方法)
			//而ConfigurationClassPostProcessor的子类方法完成了对注入的对象扫描(@Component、@Bean)+@Import等注解的扫描,并加入BeanDefinitionMap中((此时未实例化为bean)
			//所以执行完该方法BeanDefinitionMap中会出现我们注解注入的对象
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			//执行完当前处理的集合后进行清除
			currentRegistryProcessors.clear();


			//3、执行spring内置注册的几个BeanDefinition+我们自己使用注解注入的BeanDefinition
			// 其中实现了BeanDefinitionRegistryPostProcessor且implement Ordered的对象
			//和上面的处理过程类似
			// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			//执行其子接口实现方法
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();

			//4、上面几种特殊情况的实现子接口的对象都处理完了,这里开始执行剩下通过注解注入bean的实现子接口的对象(处理@Compnent、@bean、@Import等注解注入的)
			// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
			//这里reiterate进行循环是为了防止注入的bean中实现BeanDefinitionRegistryPostProcessors子接口的实现方法再次进行动态注入BeanDefinition
			boolean reiterate = true;
			while (reiterate) {
				reiterate = false;
				postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
				for (String ppName : postProcessorNames) {
					if (!processedBeans.contains(ppName)) { //查看已处理集合是否存在,防止重复执行
						//不存在,则进行实例化为bean,存进单例池。然后放进已处理集合
						currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
						processedBeans.add(ppName);
						reiterate = true;
					}
				}
				sortPostProcessors(currentRegistryProcessors, beanFactory);
				registryProcessors.addAll(currentRegistryProcessors);
				//执行子类方法
				invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
				currentRegistryProcessors.clear();
			}

			// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
			//执行1+2+3+4情况中(实现了子接口的)集合中的父类方法
			//上面的1、2、3、4都是在处理实现了子接口BeanDefinitionRegistryPostProcessor的子类方法,到这里才统一执行其父类方法
			invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
			//执行符合情况1+实现了父接口BeanFactoryPostProcessor的集合的父类方法
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
		}

		else {
			// Invoke factory processors registered with the context instance.
			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!
		//5、处理除1、2、3、4情况外的所有实现了BeanFactoryPostProcessor
		//获取所有实现父接口(排除1,因为情况1在上面已经执行了父类方法了)
		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

		
		// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.
		List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		List<String> orderedPostProcessorNames = new ArrayList<>();
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		for (String ppName : postProcessorNames) {
			if (processedBeans.contains(ppName)) {
				// skip - already processed in first phase above
			}
			else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				//实现了PriorityOrdered接口则实例化为bean,并存进单例池
				//然后放进实现了PriorityOrdered的集合
				priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
			}
			//实现了Ordered+剩下的都不实例化为bean,直接加入集合
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		//排序并执行priorityOrderedPostProcessors集合的父类方法
		// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

		//实例化orderedPostProcessorNames对应对象为bean,并进行排序+执行父类方法
		// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
		List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String postProcessorName : orderedPostProcessorNames) {
			orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

		//实例化剩下的对象为bean,并执行父类方法
		// Finally, invoke all other BeanFactoryPostProcessors.
		List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		for (String postProcessorName : nonOrderedPostProcessorNames) {
			nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		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();
	}

可以通过调试看看各个情况下实例化情况、调用实现方法情况:

未执行情况1之前:

控制台也未打印任何信息 

情况1执行完后:

控制台打印:

C --impl BeanDefinitionRegistryPostProcessor---by api ----Override postProcessBeanDefinitionRegistry

 此时则表示C对象未被实例化为bean,但是已经执行了子类方法。

执行完情况2:

此时控制台打印信息:

C --impl BeanDefinitionRegistryPostProcessor---by api ----Override postProcessBeanDefinitionRegistry

此时使用了注解注入的a、d、h、i都被扫描到并实例化为bean,但是还没有去调用其实现方法。

注意:这里之所以能扫描到这些注解注入的对象,是内置的ConfigurationClassPostProcessor执行了其子类方法(扫描注解注入的对象,并将其实例化为bean,放入单例池中)

执行完情况3:

 控制台:

C --impl BeanDefinitionRegistryPostProcessor---by api ----Override postProcessBeanDefinitionRegistry
I -- impl BeanDefinitionRegistryPostProcessor + PriorityOrdered---by @Component ----Override postProcessBeanDefinitionRegistry

执行完情况4:

控制台:

C --impl BeanDefinitionRegistryPostProcessor---by api ----Override postProcessBeanDefinitionRegistry
I -- impl BeanDefinitionRegistryPostProcessor + PriorityOrdered---by @Component ----Override postProcessBeanDefinitionRegistry
D -- impl BeanDefinitionRegistryPostProcessor--- by @Component ---- Override postProcessBeanDefinitionRegistry
F -- impl BeanDefinitionRegistryPostProcessor--- by BeanDefinition----Override postProcessBeanDefinitionRegistry
C--impl BeanDefinitionRegistryPostProcessor---by api ----Override postProcessBeanFactory
I --impl BeanDefinitionRegistryPostProcessor + PriorityOrdered--- by @Component ---- Override postProcessBeanFactory
D -- impl BeanDefinitionRegistryPostProcessor--- by @Component ---- Override postProcessBeanFactory
F-- impl BeanDefinitionRegistryPostProcessor---by BeanDefinition ---- Override postProcessBeanFactory
B--impl BeanFactoryPostProcessor---By api----Override postProcessBeanFactory

 可以看到实现子类方法的对象都被实例化,并执行了子类方法+父类方法。还有通过api注入的都会在这个时候执行完。

执行完情况5:

 控制台:

C --impl BeanDefinitionRegistryPostProcessor---by api ----Override postProcessBeanDefinitionRegistry
I -- impl BeanDefinitionRegistryPostProcessor + PriorityOrdered---by @Component ----Override postProcessBeanDefinitionRegistry
D -- impl BeanDefinitionRegistryPostProcessor--- by @Component ---- Override postProcessBeanDefinitionRegistry
F -- impl BeanDefinitionRegistryPostProcessor--- by BeanDefinition----Override postProcessBeanDefinitionRegistry
C--impl BeanDefinitionRegistryPostProcessor---by api ----Override postProcessBeanFactory
I --impl BeanDefinitionRegistryPostProcessor + PriorityOrdered--- by @Component ---- Override postProcessBeanFactory
D -- impl BeanDefinitionRegistryPostProcessor--- by @Component ---- Override postProcessBeanFactory
F-- impl BeanDefinitionRegistryPostProcessor---by BeanDefinition ---- Override postProcessBeanFactory
B--impl BeanFactoryPostProcessor---By api----Override postProcessBeanFactory
H -- impl BeanFactoryPostProcessor + PriorityOrdered--- by @Component----Override postProcessBeanFactory
A --impl BeanFactoryPostProcessor--- by @Component ---- Override postProcessBeanFactory
E -- impl BeanFactoryPostProcessor--- by BeanDefinition ---- Override postProcessBeanFactory

此时所有测试类的方法都会被调用了。

到这里我们通过debug验证了我们源码中注释的流程。所以我们可以粗略的得到一个结论,spring在处理实现了BeanFactoryPostProcessor/其子接口BeanDefinitionRegistryPostProcessor时,存在下面的执行实现方法的顺序

1)、子接口实现方法>>父接口方法

2)、api方式>>实现了PriorityOrdered接口>>通过注解注入>>动态注册BeanDefinition

(如果加上内置的,排序应该为api方式>>spring内置的实现了子接口的ConfigurationClassPostProcessor(完成扫描)>>实现了PriorityOrdered接口>>通过注解注入>>动态注册BeanDefinition)

3)、实现子接口比实现父接口更快执行

且可以推断出,spring实例化对象为bean的顺序为 :  

-----------------------------------------------------------------------------------------------

此时我们就可以根据这个结论来解释前面的疑问,前面几篇文章存在下面的疑问:

1)、为什么 BeanFactoryPostProcessor接口(只能修改BeanDefinition,不能注册)(同14问)

2)、为什么不推荐BeanDefifinitionRegistryPostProcessor进行动态注册,而改使用ImportBeanDefifinitionRegistrar(同10问)

3)、为什么ImportBeanDefifinitionRegistrar要配合@Import注解使用,和@Compnent则不会调用其实现方法?

4)、ImportBeanDefifinitionRegistrar是在什么时机被调用的,怎么被回调的,为什么不能搭配@Compnent一起使用?

5)、mybatis是如何扩展spring的扫描器的?(扫描自定义注解或某个包下的类),而spring本身又是如何扫描的?

6)、FeactoryBean的工作原理是什么?

7)、BeanFactoryPostProcess的工作原理?怎么回调的?回调时机?本身是如何注入到spring中的?其子类的原理和作用?可以获取修改beandefinition,为什么不能注册?为什么有List<BeanFactoryPostProcess>这个集合?

8)、什么是单例池、BeanDefinitionMap、@import是如何工作的?

再通过上面的源码分析,我们会出现以下问题

9)、这些执行实现方法的顺序能不能变?

10)、BeanDefifinitionRegistryPostProcessor和ImportBeanDefifinitionRegistrar的区别(类似于第2)问)

11)、实现了PriorityOrderedPostProcessors的类为什么会先被实例化?

13)、BeanDefifinitionRegistryPostProcessor对beanDefinition的修改如何保证正确性?

14)、BeanFactoryPostProcessor为什么不开发注册BeanDefinition(实际可以实现,不过注入的不是个完整的Bean)?

15)、三个接口的作用、使用场景

16)、新版本的mybatis-spring怎么做集成的,和旧版本的使用ImportBeanDefifinitionRegistrar+@import+ FactoryBean??


----------------------------------------------------

9):从上面知道执行顺序api方式>>spring内置的实现了子接口的ConfigurationClassPostProcessor(完成扫描)>>实现了PriorityOrdered接口>>通过注解注入>>动态注册BeanDefinition,为什么api提供的要比spring内置的提前执行?

为了提高api方式的实现方法的执行优先级。

14)、其实BeanFactoryPostProcessor可以进行注册BeanDdefinition,只是无法注入完整的bean,我们看下下面的例子:

A类修改下进行注册Bd:


@Component
public class A implements BeanFactoryPostProcessor {
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {


		//将beanFactory强转为子类对象DefaultListableBeanFactory,然后注册BeanDefinition
		BeanDefinitionBuilder k = BeanDefinitionBuilder.genericBeanDefinition(K.class);
		DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) beanFactory;
		defaultListableBeanFactory.registerBeanDefinition("k",k.getBeanDefinition());

		/*BeanDefinitionBuilder x = BeanDefinitionBuilder.genericBeanDefinition(X.class);
		DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) beanFactory;
		defaultListableBeanFactory.registerBeanDefinition("x",x.getBeanDefinition());*/
		System.out.println("A --impl BeanFactoryPostProcessor--- by @Component ---- Override postProcessBeanFactory");
	}
}
K类:
public class K implements BeanFactoryPostProcessor {
	public K(){

		System.out.println("create K BeanFactoryPostProcessor");
	}
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) beanFactory;
		System.out.println("k-p bd-A parent postProcessBeanFactory");
	}
}

此时运行,会发现,K的构造方法可以被执行,但其父类实现方法不会被执行。

所以说即使BeanFactoryPostProcessor可以硬性的进行动态注册,但是会存在某些方法、注解(如@Bean)不生效。(spring中不会对api方式的类中的父接口对应的实现方法循环执行,即spring执行了实现了父接口的A的父类方法,但不会做循环对K的父类方法做执行,所以不会生效)

 (但对于实现子类的会在情况4中进行循环执行实现方法,所以使用BeanDefifinitionRegistryPostProcessor进行注册则可以生效)

13)、BeanDefifinitionRegistryPostProcessor对beanDefinition的修改如何保证正确性?

我们先举一个例子,我们在D类中加入一个修改H的代码:

@Component
public class D implements BeanDefinitionRegistryPostProcessor {
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		System.out.println("D -- impl BeanDefinitionRegistryPostProcessor--- by @Component ---- Override postProcessBeanFactory");

		//log.debug("d-s scan parent postProcessBeanFactory");
	}

	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {

		System.out.println("D -- impl BeanDefinitionRegistryPostProcessor--- by @Component ---- Override postProcessBeanDefinitionRegistry");
		//log.debug("d-s scan subclass postProcessBeanDefinitionRegistry register E F");
		BeanDefinitionBuilder e = BeanDefinitionBuilder.genericBeanDefinition(E.class);
		BeanDefinitionBuilder f= BeanDefinitionBuilder.genericBeanDefinition(F.class);


		//动态获取到名为j的Beandefinition,然后修改其类型为L.class
		AbstractBeanDefinition j = (AbstractBeanDefinition) registry.getBeanDefinition("j");
		j.setBeanClass(L.class);

		registry.registerBeanDefinition("e",e.getBeanDefinition());
		registry.registerBeanDefinition("f",f.getBeanDefinition());

	}
}

public class L implements BeanDefinitionRegistryPostProcessor {
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

		System.out.println("l-s scan parent postProcessBeanFactory");
	}
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		System.out.println("l-s scan subclass postProcessBeanDefinitionRegistry register E F");
	}
}
@Component
public class J implements BeanDefinitionRegistryPostProcessor {
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		System.out.println("j-s scan parent postProcessBeanFactory");
	}
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		System.out.println("j-s scan subclass postProcessBeanDefinitionRegistry register E F");
	}
}

此时运行,我们预期的结果应该是j类的打印信息没有了,变成了L的打印信息。

D:\MyTools\Jdk\bin\java.exe "-javaagent:D:\MyTools\Idea\soft\IntelliJ IDEA 2022.2.1\lib\idea_rt.jar=10091:D:\MyTools\Idea\soft\IntelliJ IDEA 2022.2.1\bin" -Dfile.encoding=UTF-8 -classpath E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-demo\out\production\classes;D:\MyTools\Jdk\jre\lib\charsets.jar;D:\MyTools\Jdk\jre\lib\deploy.jar;D:\MyTools\Jdk\jre\lib\ext\access-bridge-64.jar;D:\MyTools\Jdk\jre\lib\ext\cldrdata.jar;D:\MyTools\Jdk\jre\lib\ext\dnsns.jar;D:\MyTools\Jdk\jre\lib\ext\jaccess.jar;D:\MyTools\Jdk\jre\lib\ext\jfxrt.jar;D:\MyTools\Jdk\jre\lib\ext\localedata.jar;D:\MyTools\Jdk\jre\lib\ext\nashorn.jar;D:\MyTools\Jdk\jre\lib\ext\sunec.jar;D:\MyTools\Jdk\jre\lib\ext\sunjce_provider.jar;D:\MyTools\Jdk\jre\lib\ext\sunmscapi.jar;D:\MyTools\Jdk\jre\lib\ext\sunpkcs11.jar;D:\MyTools\Jdk\jre\lib\ext\zipfs.jar;D:\MyTools\Jdk\jre\lib\javaws.jar;D:\MyTools\Jdk\jre\lib\jce.jar;D:\MyTools\Jdk\jre\lib\jfr.jar;D:\MyTools\Jdk\jre\lib\jfxswt.jar;D:\MyTools\Jdk\jre\lib\jsse.jar;D:\MyTools\Jdk\jre\lib\management-agent.jar;D:\MyTools\Jdk\jre\lib\plugin.jar;D:\MyTools\Jdk\jre\lib\resources.jar;D:\MyTools\Jdk\jre\lib\rt.jar;D:\MyTools\gradle\gradle-5.6.4-bin\rep\caches\modules-2\files-2.1\org.projectlombok\lombok\1.18.22\9c08ea24c6eb714e2d6170e8122c069a0ba9aacf\lombok-1.18.22.jar;E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-core\build\libs\spring-cglib-repack-3.3.0.jar;E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-core\build\libs\spring-objenesis-repack-3.1.jar;E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-context\out\production\classes;E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-context\out\production\resources;E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-aop\out\production\classes;E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-aop\out\production\resources;E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-beans\out\production\classes;E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-beans\out\production\resources;E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-expression\out\production\classes;E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-expression\out\production\resources;E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-core\out\production\classes;E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-core\out\production\resources;E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-jcl\out\production\classes;E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-jcl\out\production\resources com.spring.demo.invokeBeanFactoryPostProcessors.ApplicationContextTest -Dfile.encoding=utf-8
C --impl BeanDefinitionRegistryPostProcessor---by api ----Override postProcessBeanDefinitionRegistry
I -- impl BeanDefinitionRegistryPostProcessor + PriorityOrdered---by @Component ----Override postProcessBeanDefinitionRegistry
D -- impl BeanDefinitionRegistryPostProcessor--- by @Component ---- Override postProcessBeanDefinitionRegistry
j-s scan subclass postProcessBeanDefinitionRegistry register E F
F -- impl BeanDefinitionRegistryPostProcessor--- by BeanDefinition----Override postProcessBeanDefinitionRegistry
C--impl BeanDefinitionRegistryPostProcessor---by api ----Override postProcessBeanFactory
I --impl BeanDefinitionRegistryPostProcessor + PriorityOrdered--- by @Component ---- Override postProcessBeanFactory
D -- impl BeanDefinitionRegistryPostProcessor--- by @Component ---- Override postProcessBeanFactory
j-s scan parent postProcessBeanFactory
F-- impl BeanDefinitionRegistryPostProcessor---by BeanDefinition ---- Override postProcessBeanFactory
B--impl BeanFactoryPostProcessor---By api----Override postProcessBeanFactory
H -- impl BeanFactoryPostProcessor + PriorityOrdered--- by @Component----Override postProcessBeanFactory
A --impl BeanFactoryPostProcessor--- by @Component ---- Override postProcessBeanFactory
E -- impl BeanFactoryPostProcessor--- by BeanDefinition ---- Override postProcessBeanFactory

Process finished with exit code 0

可打印结果却发现修改BeanDefinition的代码没有生效,原因在于D类和J的实例化为bean优先级一样,所以去D修改J时,J已经被实例化为bean了,此时修改BeanDefinition已经没用了。

我们可以从上面的代码找到一个方法,就是在情况2-3之间,会对注解方式的对象转为BeanDefiniton对象并存进BeanDefinitionMap中,此时还没有实例化为bean,所以我们可以在这个时机通过提升修改BeanDefinition的代码执行优先级,即把修改的代码放到实现了PriorityOrdered接口的I类上:

此时我们在I中对J进行修改:

@Component
public class I implements BeanDefinitionRegistryPostProcessor, PriorityOrdered {
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		System.out.println("I --impl BeanDefinitionRegistryPostProcessor + PriorityOrdered--- by @Component ---- Override postProcessBeanFactory");

		//log.debug("i-s scan parent postProcessBeanFactory PriorityOrdered");
	}

	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		System.out.println("I -- impl BeanDefinitionRegistryPostProcessor + PriorityOrdered---by @Component ----Override postProcessBeanDefinitionRegistry");

		//log.debug("i-s scan subclass postProcessBeanDefinitionRegistry PriorityOrdered");
		AbstractBeanDefinition j = (AbstractBeanDefinition) registry.getBeanDefinition("j");
		j.setBeanClass(L.class);

//		BeanDefinitionBuilder x= BeanDefinitionBuilder.genericBeanDefinition(X.class);
//		registry.registerBeanDefinition("x",x.getBeanDefinition());
	}

	@Override
	public int getOrder() {
		return 0;
	}
}

控制台:

D:\MyTools\Jdk\bin\java.exe "-javaagent:D:\MyTools\Idea\soft\IntelliJ IDEA 2022.2.1\lib\idea_rt.jar=10192:D:\MyTools\Idea\soft\IntelliJ IDEA 2022.2.1\bin" -Dfile.encoding=UTF-8 -classpath E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-demo\out\production\classes;D:\MyTools\Jdk\jre\lib\charsets.jar;D:\MyTools\Jdk\jre\lib\deploy.jar;D:\MyTools\Jdk\jre\lib\ext\access-bridge-64.jar;D:\MyTools\Jdk\jre\lib\ext\cldrdata.jar;D:\MyTools\Jdk\jre\lib\ext\dnsns.jar;D:\MyTools\Jdk\jre\lib\ext\jaccess.jar;D:\MyTools\Jdk\jre\lib\ext\jfxrt.jar;D:\MyTools\Jdk\jre\lib\ext\localedata.jar;D:\MyTools\Jdk\jre\lib\ext\nashorn.jar;D:\MyTools\Jdk\jre\lib\ext\sunec.jar;D:\MyTools\Jdk\jre\lib\ext\sunjce_provider.jar;D:\MyTools\Jdk\jre\lib\ext\sunmscapi.jar;D:\MyTools\Jdk\jre\lib\ext\sunpkcs11.jar;D:\MyTools\Jdk\jre\lib\ext\zipfs.jar;D:\MyTools\Jdk\jre\lib\javaws.jar;D:\MyTools\Jdk\jre\lib\jce.jar;D:\MyTools\Jdk\jre\lib\jfr.jar;D:\MyTools\Jdk\jre\lib\jfxswt.jar;D:\MyTools\Jdk\jre\lib\jsse.jar;D:\MyTools\Jdk\jre\lib\management-agent.jar;D:\MyTools\Jdk\jre\lib\plugin.jar;D:\MyTools\Jdk\jre\lib\resources.jar;D:\MyTools\Jdk\jre\lib\rt.jar;D:\MyTools\gradle\gradle-5.6.4-bin\rep\caches\modules-2\files-2.1\org.projectlombok\lombok\1.18.22\9c08ea24c6eb714e2d6170e8122c069a0ba9aacf\lombok-1.18.22.jar;E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-core\build\libs\spring-cglib-repack-3.3.0.jar;E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-core\build\libs\spring-objenesis-repack-3.1.jar;E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-context\out\production\classes;E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-context\out\production\resources;E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-aop\out\production\classes;E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-aop\out\production\resources;E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-beans\out\production\classes;E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-beans\out\production\resources;E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-expression\out\production\classes;E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-expression\out\production\resources;E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-core\out\production\classes;E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-core\out\production\resources;E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-jcl\out\production\classes;E:\09Project\spring\spring-framework-5.2.x\spring-framework-5.2.x\spring-jcl\out\production\resources com.spring.demo.invokeBeanFactoryPostProcessors.ApplicationContextTest -Dfile.encoding=utf-8
C --impl BeanDefinitionRegistryPostProcessor---by api ----Override postProcessBeanDefinitionRegistry
I -- impl BeanDefinitionRegistryPostProcessor + PriorityOrdered---by @Component ----Override postProcessBeanDefinitionRegistry
D -- impl BeanDefinitionRegistryPostProcessor--- by @Component ---- Override postProcessBeanDefinitionRegistry
l-s scan subclass postProcessBeanDefinitionRegistry register E F
F -- impl BeanDefinitionRegistryPostProcessor--- by BeanDefinition----Override postProcessBeanDefinitionRegistry
C--impl BeanDefinitionRegistryPostProcessor---by api ----Override postProcessBeanFactory
I --impl BeanDefinitionRegistryPostProcessor + PriorityOrdered--- by @Component ---- Override postProcessBeanFactory
D -- impl BeanDefinitionRegistryPostProcessor--- by @Component ---- Override postProcessBeanFactory
l-s scan parent postProcessBeanFactory
F-- impl BeanDefinitionRegistryPostProcessor---by BeanDefinition ---- Override postProcessBeanFactory
B--impl BeanFactoryPostProcessor---By api----Override postProcessBeanFactory
H -- impl BeanFactoryPostProcessor + PriorityOrdered--- by @Component----Override postProcessBeanFactory
A --impl BeanFactoryPostProcessor--- by @Component ---- Override postProcessBeanFactory
E -- impl BeanFactoryPostProcessor--- by BeanDefinition ---- Override postProcessBeanFactory

此时发现修改成功了。

这个问题告诉我们,可以利用实例化为bean的优先级去排查修改不生效的操作,也可以利用其优先级去实现修改的操作(实现了PriorityOrdered接口去提升优先级)。

所以在BeanDefifinitionRegistryPostProcessor中修改BeanDefinition需要注意其不生效的情况以及解决方法。

11)、实现了PriorityOrdered接口的(PriorityOrderedPostProcessors集合)为什么会先被实例化?

和上面13)问一样,为了提供一个优先级的设计。

10)、BeanDefifinitionRegistryPostProcessor和ImportBeanDefifinitionRegistrar的区别

从上面知道顺序api方式>>spring内置的实现了子接口的ConfigurationClassPostProcessor(完成扫描)>>实现了PriorityOrdered接口>>通过注解注入>>动态注册BeanDefinition。

而我们对于ImportBeanDefifinitionRegistrar实现方法的执行时机是比BeanDefifinitionRegistryPostProcessor前的(注意invokeBeanFactoryPostProcessors方法中会实例化实现了ImportBeanDefifinitionRegistrar的类,但实例化的是普通的对象,不会实例化为bean)

(1)ImportBeanDefifinitionRegistrar的实现方法的执行时机优先于BeanDefifinitionRegistryPostProcessor,较高的优先级有利于对一些BeanDefinition做修改时的正确性。

(2)实现ImportBeanDefifinitionRegistrar接口的实现方法,可以多返回一个

AnnotationMetadata参数,用于获取一些元数据(例如注解信息、注解中的扫描包路径等配置信息)

这样会比BeanDefifinitionRegistryPostProcessor更加丰富。

        这就又回到了优先级的问题上,所以在@Compnent+ImportBeanDefifinitionRegistrar的实现方法不会生效,因为spring不会去处理@Compnent+ImportBeanDefifinitionRegistrar的组合(只是当成一个普通的Bean进行注入,不会执行其实现方法),这就解释了问题3、4)。---这点尚需验证。

@Import大部分情况是可以注入bean的,但要是注入的类实现了ImportBeanDefifinitionRegistrar则注入不了。(实现ImportBeanDefifinitionRegistrar更多的是为了去调用其实现方法去动态注册BeanDefinition的功能)

所以我们可以大概知道在ImportBeanDefifinitionRegistrar方法中只对

ConfigurationClassPostProcessor等内置的+@Compnent注册的类+实现了PriorityOrdered的类+实现了子类BeanFactoryPostProcessor、父类BeanDefifinitionRegistryPostProcessor的。。。。

这里实现了ImportBeanDefifinitionRegistrar+@Import、api进来的类都没实例化为bean

15)、三个接口的作用、使用场景

BeanFactoryPostProcessor的作用和使用场景

(1)、可以用来修改BeanDefinition等容器全局配置

(2)、可以用来配置忽视自动注入(注意:只有注入模型是自动注入才能忽视生效)(后面再举例说明)?????????????????????

BeanDefinitionRegistryPostProcessor、ImportBeanDefifinitionRegistrar:

(1)、第三方集成spring中,使用ImportBeanDefifinitionRegistrar进行动态注册BeanDefinition等操作

执行时机ImportBeanDefifinitionRegistrar》》BeanDefinitionRegistryPostProcessor》》BeanFactoryPostProcessor

还有其他????

16)、新版本的mybatis-spring怎么做集成的,和旧版本的使用ImportBeanDefifinitionRegistrar+@import+ FactoryBean??

--------------------------------------------

至此我们剩下的问题应该就剩:

5)、mybatis是如何扩展spring的扫描器的?(扫描自定义注解或某个包下的类),而spring本身又是如何扫描的?

6)、FeactoryBean的工作原理是什么?

8)、什么是单例池、BeanDefinitionMap、@import是如何工作的?

16)、新版本的mybatis-spring怎么做集成的,和旧版本的使用ImportBeanDefifinitionRegistrar+@import+ FactoryBean??

对于扫描器会在下篇进行讲解,其他问题会带着继续往下讲

------------------------------------------------------

总结:该篇文章中通过对invokeBeanFactoryPostProcessors方法源码进行分析,发现通过不同方式注入的代码执行优先级存在差异,从而解释了BeanFactoryPostProcessor与子接口BeanDefinitionRegistryPostProcessor的各种差异,也解释了前面为何不推荐这两者,而去使用ImportBeanDefifinitionRegistrar进行动态注册BeanDefinition。通过前面的学习,我们也大概知道了BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor、ImportBeanDefifinitionRegistrar三个接口的大概作用和执行时机。

下面我开始进行解析spring的扫描机制:

java.lang.NoClassDefFoundError: org/springframework/aot/AotDetector at org.mybatis.spring.mapper.ClassPathMapperScanner.<init>(ClassPathMapperScanner.java:91) ~[mybatis-spring-3.0.2.jar:3.0.2] at org.mybatis.spring.mapper.MapperScannerConfigurer.postProcessBeanDefinitionRegistry(MapperScannerConfigurer.java:363) ~[mybatis-spring-3.0.2.jar:3.0.2] at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:311) ~[spring-context-5.3.27.jar:5.3.27] at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:142) ~[spring-context-5.3.27.jar:5.3.27] at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:748) ~[spring-context-5.3.27.jar:5.3.27] at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:564) ~[spring-context-5.3.27.jar:5.3.27] at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.12.jar:2.7.12] at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:731) ~[spring-boot-2.7.12.jar:2.7.12] at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) ~[spring-boot-2.7.12.jar:2.7.12] at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) ~[spring-boot-2.7.12.jar:2.7.12] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303) ~[spring-boot-2.7.12.jar:2.7.12] at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292) ~[spring-boot-2.7.12.jar:2.7.12] at com.lx.MybatisPlusApplication.main(MybatisPlusApplication.java:10) ~[classes/:na] Caused by: java.lang.ClassNotFoundException: org.springframework.aot.AotDetector at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) ~[na:na] at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) ~[na:na] at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520) ~[na:na] ... 13 common frames omitted
最新发布
07-11
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值