攀爬Spring珠穆拉玛峰:Spring的启动流程

话外音

  • 真是受益良多啊,开始是想做个系统的整理与复习,然后思考了一下某个地方是如何实现,以及自己该怎么讲述这些东西;
  • 于是开始代码 debug,不知道不觉就陷入了大山,越走越深,不清楚的越来越多,又一个接一个了解清楚,然后,开始循环了……
  • 几个小时后,猛然抬头,啊这…… 好像和我 debug 的初衷有点儿对不上啊……
  • 每每念及于此,只能再次对 Spring 这座大山……膜拜啊……

环境准备

废话少说,开始吧!下载Spring5.x源码,导入Idea并构建,创建包扫描类。

@Configuration
@ComponentScan("com.slc")
public class AppConfig {

}

class StartApplication {
	public static void main(String[] args) {
		ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        //Person类在另外一个文件里面,简单用@Component标注即可,此处不展示
		Person bean = context.getBean(Person.class);
	}
}

启动项目,成功打印 Person 类的相关信息

整体流程简图

在这里插入图片描述

AnnotationConfigApplicationContext

Spring启动过程中,在通过 new AnnotationConfigApplicationContext 这一步骤已经完成了所有bean的扫描和管理。作为整个程序的入口,我们先来简单分析一下 AnnotationConfigApplicationContext

首先分析一下继承图:在这里插入图片描述
提一下几个重要的接口和类:

  1. BeanFactory:访问Spring Bean的根接口,此接口和实现类实现依赖注入,在获取 Bean 实例 的时候如果当前容器找不到,会从父容器里面找
  2. BeanDefinitionRegistry:用于保存 Bean 定义 (BeanDefinition) 的接口,定义了保存、查看、移除相关的接口
  3. DefaultListableBeanFactory: Spring容器管理的核心类,具备成熟的容器管理能力,并且继承了 DefaultSingletonBeanRegistry 定义的 Spring 三级缓存 (详情点击)
  4. AnnotationConfigRegistry:注册配置注册表,定义注册和扫描配置类的方法
  5. ApplicationContext:定义基本功能方法(通过继承各种接口),包括访问 Bean 工厂,国际化,事件监听,加载文件资源等方法定义
  6. AbstractApplicationContext: 抽象上下文,主要完成 registerBeanPostProcessors 即BeanPostProcessors的注册功能
  7. GenericApplicationContext:继承 AbstractApplicationContext ,以模板方法定义部分功能,需要各种子类的实现,并且 持有DefaultListableBeanFactory引用

总的来说 AnnotationConfigApplicationContext 实现了以下功能:

  • 完成了组件类输入,包含 @Configuration@Component 和JSR-330兼容的类 eg:@Resource
  • 并且可以注册和进行类路径扫描,是一个独立的应用程序上下文,
  • 类似的类还有 ClassPathXmlApplicationContext,属于不同的功能实现。

点击 AnnotationConfigApplicationContext的构造方法,开始解读:

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
    //1.初始化读取器和扫描器,
    //2.指定bean factory实现类(DefaultListableBeanFactory),
    //3.获取相关的环境餐撒胡配置,如系统变量参数和进程启动参数
    //4.添加默认的6个内部处理器的BeanDefinition到factory的map中,其中jpa的处理器需要判断环境中是否导入相关包
    this();
    //注册一个或多个AppConfig,即包扫描类到BeanDefinitionMap中,包括@Condition,@Primary等属性值的读取,
    register(componentClasses);
    //初始化各种类
    refresh();
}

父类初始化 DefaultListableBeanFactory

在调用构造器内的方法前,由于java的类加载机制,需要先进行父类的静态代码块和构造器的初始化

AnnotationConfigApplicationContext的父类 GenericApplicationContext 进行了 DefaultListableBeanFactory 的初始化操作。

public GenericApplicationContext() {
   this.beanFactory = new DefaultListableBeanFactory();
}

1、this()

点进 this 方法,初始化了一个读取器和扫描器。核心内容在里面,先跟进Reader的初始化操作。

public AnnotationConfigApplicationContext() {
	//读取器
	this.reader = new AnnotatedBeanDefinitionReader(this);
	//扫描器
	this.scanner = new ClassPathBeanDefinitionScanner(this);
}

AnnotatedBeanDefinitionReader初始化

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
	this(registry, getOrCreateEnvironment(registry));
}

public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
	Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
	Assert.notNull(environment, "Environment must not be null");
	this.registry = registry;
	this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
    //注册注解配置处理器 
	AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

跳过方法重写部分,有两个入参:BeanDefinitionRegistryEnvironment

  • AnnotationConfigApplicationContext本就实现了BeanDefinitionRegistry接口,调用时通过this将自身作为入参传了进来。此时向上转型为BeanDefinitionRegistry(明确职责),可以理解为现在需要使用BeanDefinitionRegistry定义的方法,而该接口负责BeanDefinition注册的相关内容。
  • Environment通过getOrCreateEnvironment获得,如果没有手动设置过的话,最终得到一个 StandardEnvironment对象,其实就是用来获取 java 启动时的参数和系统变量。

重点在于AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)这一行代码。

AnnotationConfigUtils.registerAnnotationConfigProcessors

主动调用 AnnotationConfigUtils,先加载静态代码块,这里先判断环境中是否存在jpa和@Resource,为之后添加Spring的内置处理器作出准备。

static {
    ClassLoader classLoader = AnnotationConfigUtils.class.getClassLoader();
    jsr250Present = ClassUtils.isPresent("javax.annotation.Resource", classLoader);
    jpaPresent = ClassUtils.isPresent("javax.persistence.EntityManagerFactory", classLoader) &&
            ClassUtils.isPresent(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, classLoader);
}

点进registerAnnotationConfigProcessors,是个重写方法,跳过

//方法重写,跳过
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
	registerAnnotationConfigProcessors(registry, null);
}

进入具体的方法内部,逐行分析

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
		BeanDefinitionRegistry registry, @Nullable Object source) {

	DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
	if (beanFactory != null) {
        //为BeanFactory提供@Ordered和Priority支持
		if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
			beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
		}
        //为BeanFactory提供对@Lazy和限定符解析的支持
		if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
			beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
		}
	}

	Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
	//根据判断,为BeanDefinitionMap中添加默认的spring处理器
	if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
	}
	if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
	}

	// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
	if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
	}

	// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
	if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition();
		try {
			def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
					AnnotationConfigUtils.class.getClassLoader()));
		}
		catch (ClassNotFoundException ex) {
			throw new IllegalStateException(
					"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
		}
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
	}

	if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
	}

	if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
		RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
		def.setSource(source);
		beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
	}

	return beanDefs;
}
/**
 * 注册到BeanDefinitionMap中,并放回BeanDefinitionHolder
 * @param registry 工厂
 * @param definition definition
 * @param beanName bean的名称
 * @return 持有BeanDefinition的类
 */
private static BeanDefinitionHolder registerPostProcessor(
		BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {

	definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
	registry.registerBeanDefinition(beanName, definition);
	return new BeanDefinitionHolder(definition, beanName);
}
  • 首先是为工厂设置一些默认的支持:@Ordered@Priority支持,为 Bean Factory提供对@Lazy和限定符解析的支持
  • 判断当前BeanDefinitionMap中是否存在某些内容,没有的话就添加对应的内容。

正如方法名registerAnnotationConfigProcessors(注册注解配置处理器)所描述的一样,这个方法的主要功能是在BeanDefinitionMap中添加Spring内部提供的各种处理器,其中包含以下6个处理器:

  • ConfigurationClassPostProcessor:用于对@Configuration的解析支持,是所有处理器中第一个添加的,很重要
  • AutowiredAnnotationBeanPostProcessor:用于支持自动装配;
  • CommonAnnotationBeanPostProcessor:用于支持JSR-250约束,包括@Resource@PostConstruct@PreDestroy的注解解析;
  • PersistenceAnnotationBeanPostProcessor:用户支持JPA持久层解析,会判断当前是否有持久层对应的jar包,不一定会加载;
  • EventListenerMethodProcessor:对@EventListener注解的支持,
  • DefaultEventListenerFactory:同样是对Spring Event的支持,和EventListenerMethodProcessor共同作用
总结

AnnotatedBeanDefinitionReader的初始化,大概完成了以下几件事情:

  • Bean Factory设置属性,主要是对@Ordered@Priority@Lazy的解析支持;
  • 注册5~6个spring内部使用的解析处理器,用于后面各种解析的支持;

ps:这里需要明确一个概念,目前仅仅只是在BeanDefinitionMap中添加了内部处理器,并没有加载

ClassPathBeanDefinitionScanner初始化

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
	this(registry, true);
}

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
	this(registry, useDefaultFilters, getOrCreateEnvironment(registry));
}

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment) {
	this(registry, useDefaultFilters, environment, (registry instanceof ResourceLoader ? (ResourceLoader) registry : null));
}

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
									  Environment environment, @Nullable ResourceLoader resourceLoader) {

	Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
	this.registry = registry;

	if (useDefaultFilters) {
	 //为@Component注册默认过滤器,隐式注册@Repository、@Service和@Controller等注释        
	 //并且支持JAVAEE6 提供的@ManagedBean和JSR-330的@Named     
		registerDefaultFilters();
	}
	setEnvironment(environment);
	setResourceLoader(resourceLoader);
}

跳过一层层的方法调用,查看重点:registerDefaultFilters

registerDefaultFilters
@SuppressWarnings("unchecked")
protected void registerDefaultFilters() {
	//在过滤器中添加@Component扫描支持
	this.includeFilters.add(new AnnotationTypeFilter(Component.class));
	ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
	try {
		// 在过滤器中添加@ManagedBean扫描支持
		this.includeFilters.add(new AnnotationTypeFilter(
				((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
		logger.trace("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
	}
	catch (ClassNotFoundException ex) {
		// 如果不支持JSR-250,Java EE 6,直接跳过 
	}
	try {
	   // 在过滤器中添加@Named扫描支持    
		this.includeFilters.add(new AnnotationTypeFilter(
				((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
		logger.trace("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
	}
	catch (ClassNotFoundException ex) {
		// 如果不支持JSR-330 直接跳过  
	}
}
总结

ClassPathBeanDefinitionScanner主要功能如下:

  • BeanFactory添加扫描过滤器:添加@Component和可能存在的JSR-250+JSR330注解;
  • 提供该类的scan方法,为后面包扫描提供支持;
疑问:如何扫描@Service、@Controller等注解

这里有一个注意点:只添加了@Component的拦截支持,如何扫描到@Service@Controller等等注解的呢?

参看registerDefaultFilters的Spring源码注释:

	/**
	 * Register the default filter for {@link Component @Component}.
	 * <p>This will implicitly register all annotations that have the
	 * {@link Component @Component} meta-annotation including the
	 * {@link Repository @Repository}, {@link Service @Service}, and
	 * {@link Controller @Controller} stereotype annotations.
	 * <p>Also supports Java EE 6's {@link javax.annotation.ManagedBean} and
	 * JSR-330's {@link javax.inject.Named} annotations, if available.
	 *
	 */
protected void registerDefaultFilters() {   
//...
}

翻译一下:

  • 为@Component注册默认过滤器。
  • 这将隐式注册所有具有@Component元注释的注释,包括@Repository 、 @Service和@Controller型注释。
  • 还支持 Java EE 6 的javax.annotation.ManagedBean和 JSR-330 的javax.inject.Named注释(如果可用)。

并没有提到如何隐式注册@Repository 、 @Service的。

简单提一下如何实现的:

查看这几个高级注解,可以发现他们的注解定义上均有@Component修饰

首先要明确一个概念:

  • 注解是不能继承的。如果A注解修饰B注解,然后B注解注释某个类,是不能通过类直接获取到A注解的。
  • 我们常说的注解的继承指的是,子类获取父类的注解。这并不是注解的继承,出发点在于类。

但是可以间接达到目的,Spring通过获取注解的元注解,然后递归扫描,判断类是否是Spring Bean

(判断方式Spring在5.x进行了优化,暂时不多做研究,但大概的思路就是这样的)

this方法总结

  • 初始化读取器和扫描器;
  • 间接添加了5到6个BeanPostProcessor,为之后的操作提供支持;
  • 添加各个注解的过滤器,为之后的包扫描提供支持;

2、register(componentClasses)

进入三大方法的第二个:register

@Override
public void register(Class<?>... componentClasses) {
	Assert.notEmpty(componentClasses, "At least one component class must be specified");
	this.reader.register(componentClasses);
}

public void register(Class<?>... componentClasses) {
	for (Class<?> componentClass : componentClasses) {
		registerBean(componentClass);
	}
}

public void registerBean(Class<?> beanClass) {
	doRegisterBean(beanClass, null, null, null, null);
}

主要是循环处理componentClasses(包扫描类可以传入多个),切入重点:doRegisterBean

private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
		@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
		@Nullable BeanDefinitionCustomizer[] customizers) {
	//为注册类创建一个AnnotatedGenericBeanDefinition,主要是获取注解信息的方法支持
	AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
   //结合 @Condition 来判断是否跳过,本次调用作用不大
	if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
		return;
	}

	abd.setInstanceSupplier(supplier);
	//@Scope属性判断
	ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
	abd.setScope(scopeMetadata.getScopeName());
	// 调用beanNameGenerator生成名称,用于BeanDefinitionMap的key
	String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
	// 为注册类需要注册的BeanDefinition添加各种属性值:lazy,primary,dependsOn,role,description
	AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
	if (qualifiers != null) {
		for (Class<? extends Annotation> qualifier : qualifiers) {
			if (Primary.class == qualifier) {
				abd.setPrimary(true);
			}
			else if (Lazy.class == qualifier) {
				abd.setLazyInit(true);
			}
			else {
				abd.addQualifier(new AutowireCandidateQualifier(qualifier));
			}
		}
	}
	// Spring新提供的方法,自定义注册一个 bean,本次调用没用到
	if (customizers != null) {
		for (BeanDefinitionCustomizer customizer : customizers) {
			customizer.customize(abd);
		}
	}
	// 分装BeanDefinitionHolder,BeanDefinitionHolder持有BeanDefition
	BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
	// 读取@Scop的proxyMethod属性值,确定代理方式
	definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
	// 注册Bean(添加到BeanDefinitionMap中)
	BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

那么register(componentClasses)的作用就很明显了:用来注册 AppConfig的Bean定义

基本的注释在代码都有提及。
需要注意的是:doRegisterBean是一个注册Bean的通用方法,里面包含其他componentClasses的判断。

3、refresh

终于到这个部分了,spring启动流程的精华就在这个方法内部,我们切入主题。

@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        //刷新前的准备工作,主要是一些容器状态还有环境的设置
        prepareRefresh();

        //获取DefaultListableBeanFactory (register中初始化的factory)
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        //做一些准备工作,初始化容器的一些标准特性
        prepareBeanFactory(beanFactory);

        try {
            //此处AbstractApplicationContext没有实现该方法,留给子类实现,
            postProcessBeanFactory(beanFactory);
            /**
				 * 执行实现 BeanFactoryPostProcessors接口的类(并且@Component标注),因为原理是通过getBean(name,class)获取后执行
				 *
				 * 1.委托给PostProcessorRegistrationDelegate来进行“调用”这一动作,内部处理存在特殊处理(如:优先级判断决定执行的先后顺序),
				 * 2.最原始的先后顺序上,先执行为 BeanDefinitionRegistryPostProcessor 的子类,再执行 BeanFactoryPostProcessor 的子类
				 * --- BeanFactoryPostProcessor
				 * --- BeanDefinitionRegistryPostProcessor  为前者的子类
				 *
				 * 查看spring最开始就加载的配置类之一:ConfigurationClassPostProcessor,该类为spring
				 * ConfigurationClassPostProcessor
				 *
				 */
            invokeBeanFactoryPostProcessors(beanFactory);

            //同样委托给PostProcessorRegistrationDelegate 注册需要执行的BeanPostProcessors
            registerBeanPostProcessors(beanFactory);

            //国际化的一些初始化操作
            initMessageSource();

            //初始化 ApplicationEventMulticaster到 单例池中,用于管理 ApplicationListener ,默认为 SimpleApplicationEventMulticaster。
            initApplicationEventMulticaster();

            //模板方法,用于其他Context子类 实例化一些特殊的Bean
            onRefresh();

            //往 applicationEventMulticaster 添加实现ApplicationListener接口的类
            registerListeners();

            //初始化所有非 Lazy 的单例 Bean
            finishBeanFactoryInitialization(beanFactory);

            //完成上下文刷新,会调用LifecycleProcessor的onRefresh()方法并发布ContextRefreshedEvent 。
            finishRefresh();
        } catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
            }

            //Spring original comment----------------- Destroy already created singletons to avoid dangling resources.
            destroyBeans();

            //Spring original comment----------------- Reset 'active' flag.
            cancelRefresh(ex);

            //Spring original comment----------------- Propagate exception to caller.
            throw ex;
        } finally {
            //Spring original comment----------------- Reset common introspection caches in Spring's core, since we
            //Spring original comment----------------- might not ever need metadata for singleton beans anymore...
            resetCommonCaches();
        }
    }
}

一行一行来吧:

prepareRefresh

刷新前的准备工作,包括spring状态的设置,一些验证和事件的初始化设置

protected void prepareRefresh() {
    //设置为开启状态
    this.startupDate = System.currentTimeMillis();
    this.closed.set(false);
    this.active.set(true);

    if (logger.isDebugEnabled()) {
        if (logger.isTraceEnabled()) {
            logger.trace("Refreshing " + this);
        } else {
            logger.debug("Refreshing " + getDisplayName());
        }
    }

    //初始化占位符属性源,留给子类实现,在AnnotationConfigApplicationContext没有实现,其他需要的子类应当实现
    initPropertySources();

    //验证setRequiredProperties指定的每个属性是否存在并解析为非null值。
    getEnvironment().validateRequiredProperties();

    //存储早期事件监听
    if (this.earlyApplicationListeners == null) {
        this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
    } else {
        this.applicationListeners.clear();
        this.applicationListeners.addAll(this.earlyApplicationListeners);
    }

	//用来存储早期的事件,在广播器可用后发布
    this.earlyApplicationEvents = new LinkedHashSet<>();
}

obtainFreshBeanFactory

获取BeanFactory,另外CAS设置状态,避免一个Bean Factory多次刷新。

	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        //refresh校验
		refreshBeanFactory();
		return getBeanFactory();
	}
	
	@Override
	protected final void refreshBeanFactory() throws IllegalStateException {
		if (!this.refreshed.compareAndSet(false, true)) {
			throw new IllegalStateException(
					"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
		}
		this.beanFactory.setSerializationId(getId());
	}

prepareBeanFactory(beanFactory)

做一些准备工作,初始化一些标准特性,比较重要的部分如下:

  • 提供了BeanFactoryProcessor的支持,在Spring大法属于很重要的环节;
  • 注册了ApplicationListener相关的处理器;
  • registerResolvableDependency为解决 ”无法找到同接口多实现类“ 提供了一种解决方法,可以在日常中考虑使用(@Qualifier也不错)
  • 提供LoadTimeWeaver支持
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    //上下文类加载器
    beanFactory.setBeanClassLoader(getClassLoader());
    //设置Bean表达式解析器,在属性填充(populateBean)的时候会用到里面的方法
    beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    //提供属性编辑器,可以自定义,通过实现PropertyEditorSupport接口
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    //添加 BeanFactoryProcessor 支持的重要环节
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    //忽略给定的自动装配依赖接口,在addBeanPostProcessor 已经初始化了
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

    //为避免自动装配时,找不到对应的实现类,给特定的接口添加默认的实现类,
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);

    //注册早期的 ApplicationListene 处理器
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    //果存在的话,提供 LoadTimeWeaver 支持
    if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        //为类型匹配设置一个临时的 ClassLoader。
        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());
    }
}

postProcessBeanFactory

该方法在父类 AbstractApplicationContext中定义,在AnnotationConfigApplicationContext中并没有实现它。

子类可以通过重写这个方法,在BeanFactory准备好后进行额外操作。

  • GenericWebApplicationContext作为另外的子类,就实现了该方法:添加了ServletContextAwareProcessor处理器。(有兴趣的可以看看)
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
}

invokeBeanFactoryPostProcessors(beanFactory);

	protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
        //委托
		PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

		//如果检测到 LoadTimeWeaver ,则准备编织
        //例如通过 ConfigurationClassPostProcessor 注册的 @Bean 方法
		if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}
	}

这个方法的主要作用是:实例化并调用所有已注册的 BeanFactoryPostProcessor,分析一下关键代码。

首先是委托给了PostProcessorRegistrationDelegate进行调用操作。点进去查看委托的操作。 这部分有点儿意思。

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

		//如果有的话,首先调用 BeanDefinitionRegistryPostProcessors。
		Set<String> processedBeans = new HashSet<>();

		//如果factory属于BeanDefinitionRegistry,则执行以下逻辑(通过扫描获取哪些BeanFactoryPostProcessor需要执行)
		//而else里面则直接执行 beanFactoryPostProcessors 集合里面的内容
    	//(该类容一般传参的方式为工厂的成员变量 factory.getBeanFactoryPostProcessors())
		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

			//对于DefaultListableBeanFactory而言,此处为Empty -->factory.getBeanFactoryPostProcessors 为空
			for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
				if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
					BeanDefinitionRegistryPostProcessor registryProcessor =
							(BeanDefinitionRegistryPostProcessor) postProcessor;
					registryProcessor.postProcessBeanDefinitionRegistry(registry);
					registryProcessors.add(registryProcessor);
				} else {
					regularPostProcessors.add(postProcessor);
				}
			}

			//不要在此处初始化 FactoryBeans:我们需要保留所有常规 bean 未初始化以让 bean 工厂后处理器应用于它们!
			// 将实现 PriorityOrdered、Ordered 和其余部分的 BeanDefinitionRegistryPostProcessor 分开。
			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

			// 1.首先,调用实现 PriorityOrdered 的 BeanDefinitionRegistryPostProcessors。
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					//获取BeanDefinitionRegistryPostProcessor 接口定义的类,
					//spring内部定义的扫描类,优先级高于 BeanFactoryPostProcessor,为 BeanFactoryPostProcessor的子类
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();

			// 2。然后,调用实现 Ordered 的 BeanDefinitionRegistryPostProcessors
			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();

			// 3.最后,调用所有其他 BeanDefinitionRegistryPostProcessor 直到不再出现。
			boolean reiterate = true;
			while (reiterate) {
				reiterate = false;
				postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
				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 回调。
			invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
		} else {
			//调用在上下文实例中注册的工厂处理器
			invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
		}


		//不要在此处初始化 FactoryBeans:我们需要保留所有常规 bean 未初始化以让 bean 工厂后处理器应用于它们!
		String[] postProcessorNames =
				beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

		//将实现 PriorityOrdered、Ordered 和其余部分的 BeanFactoryPostProcessors 分开。
		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
				 * 已经先调用完毕了,比如ConfigurationClassPostProcessor,该类实现了 BeanDefinitionRegistryPostProcessor 接口
				 * 而BeanDefinitionRegistryPostProcessor是 BeanFactoryPostProcessor的子类,所以这个集合里面还是会得到该类的名称,
				 * 所以此处跳过(不做处理)
				 */
			} else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
			} else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			} else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// 1.首先,调用实现 PriorityOrdered 的 BeanFactoryPostProcessors。
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

		// 2。然后,调用实现 Ordered 的 BeanFactoryPostProcessors
		List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String postProcessorName : orderedPostProcessorNames) {
			orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

		// 3.最后,调用所有其他 BeanFactoryPostProcessors 
		List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		for (String postProcessorName : nonOrderedPostProcessorNames) {
			nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

		//清除缓存的 merged bean definitions,因为后处理器可能已经修改了原始元数据,例如替换值中的占位符...
		beanFactory.clearMetadataCache();
	}

这一段的代码较长,但是重复的段落较多,整体思想还是比较简单的。一层一层的来解析他。

  • 首先明确调用此方法的BeanFactory,是否是用来注册的(beanFactory instanceof BeanDefinitionRegistry),否则直接调用该工厂内定义的beanFactoryPostProcessors

本次调用的是DefaultListableBeanFactory,自然间接继承或实现了BeanDefinitionRegistry

我们进入内部复杂的初始化操作。在简单看完这里面的代码之后,我们可以发现一些很有趣的东西:

  • 该方法主要是按顺序调用了实现BeanFactoryPostProcessorBeanDefinitionRegistryPostProcessor接口的方法。
  • 这个顺序是按照所实现方法上的注解进行判断的,最优先的为@PriorityOrdered标注的实现类,其次是@Ordered,最后是什么都没有的。
重点:beanFactoryPostProcessors加载的优先级判断

其实BeanDefinitionRegistryPostProcessor是继承BeanFactoryPostProcessor的子接口

  1. 那么为什么要spring要区分对待呢?
  2. 都是beanFactoryPostProcessors处理器,按照@PriorityOrdered@Ordered什么都没有的顺序处理一次不就可以了吗?

通过断点,我们发现被扫描出来的,实现了BeanDefinitionRegistryPostProcessor接口的类为:ConfigurationClassPostProcessor

我们之前就提到过了ConfigurationClassPostProcessor:在registerAnnotationConfigProcessors中被注册,是第一个被调用的处理器。

ConfigurationClassPostProcessor负责支持@Configuration的解析,从作用上来说,应当早于所有其他的beanFactoryPostProcessors

到这里我们需要知道两点就可以了:

  1. 实现BeanDefinitionRegistryPostProcessor的方法 早于 实现beanFactoryPostProcessors的方法。
  2. invokeBeanFactoryPostProcessors中是先处理的前者。二者调用时都是@PriorityOrdered@Ordered什么都没有的优先级判断

另外在调用的同时两个接口的实现类会通过getBean()加载到DefaultListableBeanFactory持有的由父级的单例池singletonObjects里面

ConfigurationClassPostProcessor的加载

我们来查看第一个调用并添加到单例池BeanFactory处理器:ConfigurationClassPostProcessor究竟做了什么:

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    int factoryId = System.identityHashCode(beanFactory);
    if (this.factoriesPostProcessed.contains(factoryId)) {
        throw new IllegalStateException(
            "postProcessBeanFactory already called on this post-processor against " + beanFactory);
    }
    this.factoriesPostProcessed.add(factoryId);
    if (!this.registriesPostProcessed.contains(factoryId)) {
        // BeanDefinitionRegistryPostProcessor hook apparently not supported...
        // Simply call processConfigurationClasses lazily at this point then.
        processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
    }
    //对Configuration类进行增强
    enhanceConfigurationClasses(beanFactory);
    //添加一个 ImportAwareBeanPostProcessor 后置处理器,
    //其作用是为EnhanceConfiguration类的beanFactory属性赋值。
    beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}

主要做了两点:

  1. Configuration类创建代理;
  2. 添加一个 ImportAwareBeanPostProcessor后置处理器,为EnhanceConfiguration类的beanFactory属性赋值

这里面牵扯到@ImportAware的实现原理,篇幅有限,暂不展开。具体内容会在其他博客中详细描述。

总结

invokeBeanFactoryPostProcessors(beanFactory)完成了以下功能:

  • 委托给PostProcessorRegistrationDelegate调用beanFactoryPostProcessors的实现类(包括BeanDefinitionRegistryPostProcessor);
  • 加载beanFactoryPostProcessors的实现类到单例池里面;
  • 调用ConfigurationClassPostProcessorpostProcessBeanFactory的方法,创建对应代理,并添加一个ImportAwareBeanPostProcessor

registerBeanPostProcessors(beanFactory);

调用并注册BeanPostProcessors,原理和invokeBeanFactoryPostProcessors如出一辙,简单分析一下:

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

BeanFactoryProcessors类似,同样是委托,此处委托给PostProcessorRegistrationDelegate进行相关操作。我们直接点进去:

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

    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.
    //注册 BeanPostProcessorChecker,它会在 BeanPostProcessor 实例化期间创建 bean 时记录信息消息,即当 bean 没有资格被所有 BeanPostProcessor 处理时。
    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    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<>();
    for (String ppName : postProcessorNames) {
        if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            priorityOrderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        } else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        } else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    // First, register the BeanPostProcessors that implement PriorityOrdered.
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

    // Next, register the BeanPostProcessors that implement Ordered.
    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
    for (String ppName : orderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        orderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, orderedPostProcessors);

    // Now, register all regular BeanPostProcessors.
    List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
    for (String ppName : nonOrderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        nonOrderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

    // Finally, re-register all internal BeanPostProcessors.
    sortPostProcessors(internalPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, internalPostProcessors);

    //重新注册处理器以将内部 bean 检测为 ApplicationListeners,将其移动到处理器链的末尾(用于获取代理等)
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

大体内容是一样的:按照@PriorityOrdered@Ordered什么都没有的优先级调用并注册BeanPostProcessor

不同的地方有以下两个地方:

  1. 添加了一个BeanPostProcessorChecker:这是用于记录某些没有被所有BeanPostProcessorBean信息。
  2. 重新注册了ApplicationListenerDetector:Spring Event的相关机制,此时吧``ApplicationListenerDetector`添加到了处理器的末尾

*ps:addBeanPostProcessor*内部操作时,会先remove,然后再新增,并且放在最后面:addLast方法

initMessageSource();

国际化的一些初始化操作

initApplicationEventMulticaster();

初始化 ApplicationEventMulticaster。如果上下文中没有定义,则使用 SimpleApplicationEventMulticaster

代码如下,没什么好说的。

protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
        this.applicationEventMulticaster =
            beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
        if (logger.isTraceEnabled()) {
            logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
        }
    } else {
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
        if (logger.isTraceEnabled()) {
            logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
                         "[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
        }
    }
}

onRefresh();

postProcessBeanFactory,使个模板方法。交给子类实现。AnnotationConfigApplicationContext并没有实现它。

例如GenericWebApplicationContext在这个时候设置了ThemeSource

ThemeSource:主题资源,web时可能需要,没用过。参考即可。

registerListeners();

往 applicationEventMulticaster 添加实现ApplicationListener接口的类

finishBeanFactoryInitialization(beanFactory);

初始化所有非 Lazy 的单例 Bean

这是 Spring启动流程的重点,这是Spring启动流程的重点,这是Spring启动流程的重点。重要的事说三遍!

循环依赖的解决及三级缓存的设计都在里面。

关于本方法会在另一篇博客里面详细描述。此处不展开

finishRefresh();

完成上下文刷新,会调用LifecycleProcessor的onRefresh()方法并发布ContextRefreshedEvent

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你遇到的问题是在使用Qt连接MySQL数据库时,出现了"undefined reference to `mysql_character_set_name@4'"的错误。这个错误通常是由于编译器没有找到MySQL的库文件所致。 解决这个问题的方法如下所示: 1. 首先,确保你已经正确安装了MySQL数据库,并且在你的系统中能够正常运行。 2. 检查你的Qt安装目录下的Mysql文件夹中的pri文件是否存在。这个文件通常位于类似"D:\Qt\5.14.2\Src\qtbase\src\plugins\sqldrivers\mysql"的路径下。如果该文件不存在,请确认你的Qt安装包中是否包含了MySQL插件源代码。 3. 如果存在pri文件,请双击打开它并进入Qt界面。检查该文件是否可以直接编译,如果不能,请确认是否缺少了必要的依赖库。 4. 将qsqlmysql.dll文件复制到你的Qt安装目录下的"plugins\sqldrivers"文件夹中。例如,对于你的Qt安装目录"D:\Qt\5.14.2\mingw73_64"和编译器目录"bin",复制的路径应为"D:\Qt\5.14.2\mingw73_64\plugins\sqldrivers"。 5. 将MySQL安装目录下的lib文件夹中的libmysql.dll文件复制到你的Qt安装目录下的"bin"文件夹中。这样可以确保编译器能够找到MySQL的依赖库。 6. 然后,重新运行和调试程序。你可以使用以下代码来测试数据库连接是否成功: ```cpp qDebug() << "available drivers:"; QStringList drivers = QSqlDatabase::drivers(); foreach(QString driver, drivers) qDebug() << driver; QSqlDatabase database = QSqlDatabase::addDatabase("QMYSQL"); database.setHostName("127.0.0.1"); //设置主机地址 database.setPort(3306); //设置端口,默认3306 database.setDatabaseName("**"); //设置数据库名称 database.setUserName("root"); //对应数据库的用户名 database.setPassword("****");//对应数据库的密码 if(!database.open()) qDebug() << database.lastError().text(); else qDebug() << "success"; ``` 请确保将代码中的主机地址、数据库名称、用户名和密码替换为正确的值。 希望以上步骤能够解决你遇到的问题。如果问题仍然存在,请提供更多的错误信息和背景,以便我们能够更好地帮助你。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [qt-5.14.2与Mysql的连接问题汇总](https://blog.csdn.net/Max_one/article/details/118788465)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值