点击事件为什么会失效_Spring事务原理?事务在方法间如何传播?为什么会失效?...

推荐学习

  • 疯狂膜拜!阿里出品Spring Security王者晋级文档
  • 肝了十天半月,献上纯手绘“Spring/Cloud/Boot/MVC”全家桶脑图
009dad5a8eda6f734bf6ecb5755fd7a8.png

前言

事务我们都知道是什么,而Spring事务就是在数据库之上利用AOP提供声明式事务编程式事务帮助我们简化开发,解耦业务逻辑和系统逻辑。但是Spring事务原理是怎样?事务在方法间是如何传播的?为什么有时候事务会失效?接下来咱就一一解答~重点分析Spring事务源码,让我们彻底搞懂Spring事务的原理。

正文

XML标签的解析

配置过事务的应该都不陌生,上面这个配置就是Spring开启事务注解(@Transactional)支持的配置,而看过我之前文章的应该知道,这个带前缀的标签叫自定义标签,我在之前的文章也分析过自定义标签的解析过程,所以这里我直接找到对应的handler:

public class TxNamespaceHandler extends NamespaceHandlerSupport {static final String TRANSACTION_MANAGER_ATTRIBUTE = "transaction-manager";static final String DEFAULT_TRANSACTION_MANAGER_BEAN_NAME = "transactionManager";static String getTransactionManagerName(Element element) {return (element.hasAttribute(TRANSACTION_MANAGER_ATTRIBUTE) ?element.getAttribute(TRANSACTION_MANAGER_ATTRIBUTE) : DEFAULT_TRANSACTION_MANAGER_BEAN_NAME);}@Overridepublic void init() {registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());}}

可以看到对应的注解解析器就是AnnotationDrivenBeanDefinitionParser类,在该类中一定会有一个parse方法:

public BeanDefinition parse(Element element, ParserContext parserContext) {registerTransactionalEventListenerFactory(parserContext);String mode = element.getAttribute("mode");if ("aspectj".equals(mode)) {// mode="aspectj"registerTransactionAspect(element, parserContext);if (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader())) {registerJtaTransactionAspect(element, parserContext);}}else {// mode="proxy"AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);}return null;}

首先拿到mode属性的值判断是使用AspectJ生成代理还是JDK生成代理,这里我们主要看proxy模式,进入configureAutoProxyCreator方法:

public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {// 注册AOP的入口类AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {Object eleSource = parserContext.extractSource(element);// Create the TransactionAttributeSource definition.// @Transactional注解的属性封装RootBeanDefinition sourceDef = new RootBeanDefinition("org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");sourceDef.setSource(eleSource);sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);// Create the TransactionInterceptor definition.// AOP执行链RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);interceptorDef.setSource(eleSource);interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);// 拿到transaction-manager属性的值registerTransactionManager(element, interceptorDef);interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);// Create the TransactionAttributeSourceAdvisor definition.RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);advisorDef.setSource(eleSource);advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);if (element.hasAttribute("order")) {advisorDef.getPropertyValues().add("order", element.getAttribute("order"));}parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));parserContext.registerComponent(compositeDef);}}

这里的流程比较长,但逻辑很简单。首先来看注册事务AOP入口类是哪个:

public static void registerAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {// 将优先级更高的AOP入口类放入到IOC容器中BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(parserContext.getRegistry(), parserContext.extractSource(sourceElement));// 设置代理生成的方式以及是否缓存代理类到当前线程useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);registerComponentIfNecessary(beanDefinition, parserContext);}

主要看registerAutoProxyCreatorIfNecessary方法:

public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, @Nullable Object source) {return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);}private static BeanDefinition registerOrEscalateApcAsRequired(Class> cls, BeanDefinitionRegistry registry, @Nullable Object source) {Assert.notNull(registry, "BeanDefinitionRegistry must not be null");// 判断传进来的类和ICO中当前存在的类哪个优先级更高,将更高的放入IOC中if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);if (!cls.getName().equals(apcDefinition.getBeanClassName())) {int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());int requiredPriority = findPriorityForClass(cls);if (currentPriority < requiredPriority) {apcDefinition.setBeanClassName(cls.getName());}}return null;}//把AOP入口类封装成beanDefinition对象,要实例化RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);beanDefinition.setSource(source);beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);//注解aop入口类的beanName名称 AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAMEregistry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);return beanDefinition;}

首先判断容器中是否已经存在AOP入口类,如果不存在则直接创建InfrastructureAdvisorAutoProxyCreator的BeanDefinition对象注册到容器中,这个类也是我之前分析的AOP入口类AbstractAutoProxyCreator的子类,再来看看其继承关系:

76bae540282a5ab47445f2c5f83f8a42.png

你会不会疑惑,这么多子类,到底会使用哪一个呢?回到刚刚的代码中,可以看到如果已经存在一个入口类了,就会通过findPriorityForClass获取两个类的优先级,最终就会使用优先级更大的那个,那么它们的优先级顺序是怎样的呢?

private static final List> APC_PRIORITY_LIST = new ArrayList<>(3);static {// Set up the escalation list...APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);}private static int findPriorityForClass(@Nullable String className) {// 索引即是优先级,越大优先级越高,IOC中只会存在一个事务AOP入口类for (int i = 0; i < APC_PRIORITY_LIST.size(); i++) {Class> clazz = APC_PRIORITY_LIST.get(i);if (clazz.getName().equals(className)) {return i;}}throw new IllegalArgumentException("Class name [" + className + "] is not a known auto-proxy creator class");}

可以看到,InfrastructureAdvisorAutoProxyCreator是优先级最低的,基本上不会起作用;AspectJAwareAdvisorAutoProxyCreator是当我们配置了标签时会注册,也就是xml配置的AOP的入口类;而AnnotationAwareAspectJAutoProxyCreator是当我们配置了或使用@EnableAspectJAutoProxy注解时注册,因此大部分情况下都是使用的AnnotationAwareAspectJAutoProxyCreator
注册完AOP的入口类后,回到configureAutoProxyCreator方法:

RootBeanDefinition sourceDef = new RootBeanDefinition("org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");sourceDef.setSource(eleSource);sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);String sourceName =parserContext.getReaderContext().registerWithGeneratedName(sourceDef);

AnnotationTransactionAttributeSource类的作用就是封装事务注解@Transactional的属性,这里需要记住其继承体系以及熟悉该类和其父类的属性和方法,对后面分析事物切面执行原理有帮助:

96a01f1ff7f930d8a590c41b5613a64e.png

紧接着就是创建了TransactionInterceptor对象,专门的事务拦截器,并且该类是MethodInterceptor的子类,看到这个应该不陌生了,我们知道AOP调用链在执行过程中主要就是调用该类的invoke的方法,因此它是事务切面执行的入口。既然有了Interceptor,那么必不可少的还应该有Advisor,而Advisor又是由AdvicePoincut组成的,这样才能构成一个完整的切面,所以该方法后面就是创建这两个对象。以上就是xml配置AOP注解支持的原理,很简单,下面再来看看零配置又是如何实现的。

AOP零配置原理

使用过SpringBoot的都知道,如果需要开启事务注解的支持,只需要一个注解就能搞定:@EnableTransactionManagement,不用再配置xml文件,这个又是怎么做到的呢?不多说,我们直接来看其源码:

@Import(TransactionManagementConfigurationSelector.class)public @interface EnableTransactionManagement {boolean proxyTargetClass() default false;AdviceMode mode() default AdviceMode.PROXY;int order() default Ordered.LOWEST_PRECEDENCE;}

在该注解下使用@Import导入了一个类TransactionManagementConfigurationSelector,首先该注解的作用就是导入一个类的实例到IOC容器中,你可能会说不是在类上加@Component注解就行了么,但是有些类它并不在你扫描的路径下,而该注解依然可以将其导入进来,所以我们主要看TransactionManagementConfigurationSelector类中做了些啥:

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector {@Overrideprotected String[] selectImports(AdviceMode adviceMode) {switch (adviceMode) {case PROXY:return new String[] {AutoProxyRegistrar.class.getName(),ProxyTransactionManagementConfiguration.class.getName()};case ASPECTJ:return new String[] {determineTransactionAspectClass()};default:return null;}}private String determineTransactionAspectClass() {return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);}}

可以看到在selectImports方法中返回了AutoProxyRegistrarProxyTransactionManagementConfiguration类,返回后会被封装为BeanDefinition对象,那这个方法是在哪里调用的呢?这个在之前的文章中也分析过,ConfigurationClassPostProcessor类中会调用ConfigurationClassParser类的parse方法解析@Configuration、@Import、@ImportSource等注解,具体过程这里就不再赘述了。我们继续来分别看看AutoProxyRegistrarProxyTransactionManagementConfiguration类:

public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {private final Log logger = LogFactory.getLog(getClass());@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {boolean candidateFound = false;Set annoTypes = importingClassMetadata.getAnnotationTypes();for (String annoType : annoTypes) {AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);if (candidate == null) {continue;}Object mode = candidate.get("mode");Object proxyTargetClass = candidate.get("proxyTargetClass");if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&Boolean.class == proxyTargetClass.getClass()) {candidateFound = true;if (mode == AdviceMode.PROXY) {//注册事务AOP的入口类InfrastructureAdvisorAutoProxyCreator,实际上这个AOP入口类起不了作用AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);if ((Boolean) proxyTargetClass) {AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);return;}}}}}}public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {/** 明显是创建事务切面实例* BeanFactoryTransactionAttributeSourceAdvisor** */@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();advisor.setTransactionAttributeSource(transactionAttributeSource());//设置通知类advisor.setAdvice(transactionInterceptor());if (this.enableTx != null) {advisor.setOrder(this.enableTx.getNumber("order"));}return advisor;}@Bean@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public TransactionAttributeSource transactionAttributeSource() {return new AnnotationTransactionAttributeSource();}/** 创建事务advice* TransactionInterceptor* */@Bean@Role(BeanDefinition.ROLE_INFRASTRUCTURE)public TransactionInterceptor transactionInterceptor() {TransactionInterceptor interceptor = new TransactionInterceptor();interceptor.setTransactionAttributeSource(transactionAttributeSource());//事务管理器要跟数据源挂钩,所以需要自己定义if (this.txManager != null) {interceptor.setTransactionManager(this.txManager);}return interceptor;}}

看到这就很清楚了,前者是注册AOP的入口类(这里注册的入口类依然是InfrastructureAdvisorAutoProxyCreator),后者则是创建事务AOP的组件的实例到IOC中,到这里相信不仅仅是对于事务的零配置,而是整个SpringBoot的零配置实现原理都心中有数了。

总结

本篇结合之前所学分析了事务配置解析的原理,也带出了SpringBoot零配置实现的原理。我们需要在脑海将加载、解析和调用串联起来,从微观到宏观整体把握Spring,才能真正的理解Spring。

作者:夜勿语

原文链接:https://blog.csdn.net/l6108003/article/details/106650023

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

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

相关文章

wcdma系统随机接入过程的流程图_招聘电信协优初中级优化工程师、联通系统高级...

点击上方“通信人才网” 订阅&#xff01;招聘岗位招聘职位&#xff1a; 电信协优初中级优化工程师岗位类型&#xff1a;5G无线网络优化,4G-LTE无线网络优化,无线网优项目负责人,DT/CQT测试与分析,2G/3G无线网络优化工作地点&#xff1a; 西宁市,果洛藏族自治州,海南藏族自治州…

基于wincc的虚拟电梯设计_一文带你了解西门子整个虚拟调试与仿真软硬件体系...

写在面前大家好&#xff0c;我是小智&#xff0c;智能制造之家号主~经常有朋友关注到PLCSIM、SIMIT、Amesim、NX MCD、 Process Simulate、Plant Simulation等&#xff0c;但都不知道它们到底做啥的~因此今天对西门子仿真与虚拟调试进行整体介绍&#xff0c;力求让小白也能熟悉…

三星ml1660拆机图解_炫龙DD2拆机,高性能的背后是怎样的面容?

双内存插槽 如标题所说&#xff0c;今天为大家带来炫龙DD2的图解拆机&#xff0c;废话少说&#xff0c;直接进入主题吧&#xff01;笔者对炫龙毁灭者DD2进行了简单拆解&#xff0c;拆解方式为打开D壳&#xff0c;查看散热模组和各部分硬件。炫龙毁灭者DD2延续了品牌一贯传统&am…

目录页码错误未定义书签怎么解决_目录页码对不齐应该怎么办?这2种方法,工作效率大增...

在制作文档目录时&#xff0c;你有没有遇到下图情况&#xff1a;右侧页码不对齐或者左侧文本不对齐&#xff0c;你一般是如何处理的&#xff0c;与大家分享相关的2种解决办法。工作效率大增&#xff01;1、目录页码不对齐该怎么办&#xff1f;遇到这种情况&#xff0c;一般是制…

权限丢失_不要让任何“账户权限”问题困扰你!

在Win10系统使用中时不时被“账户权限”问题困扰&#xff1f;别怕&#xff0c;有我呢~关闭更改系统相关设置时的通知不愿被安装软件、更改Windows设置时弹出的通知所打扰时&#xff0c;可以搜索【UAC】&#xff08;若没有搜索框&#xff0c;请使用【Win】【Q】快捷键调出&#…

卡方分布分位数_卡方检验和精确概率法及两两比较

看过许多统计教程&#xff0c;这篇是我最推荐的介 绍数值变量如果服从正态分布&#xff0c;采用均数标准差进行统计描述&#xff0c;采用方差分析进行组间比较&#xff0c;如果组间差异有统计学意义&#xff0c;进一步采用LSD法(也可以是其它方法)进行两两比较。如果不服从正…

arcgis渔网分割提取栅格图_【操作】ArcGIS中字段的合并、分割、提取

由于种种原因&#xff0c;可能涉及到要对ArcGIS属性字段进行合并、分割、提取等操作&#xff0c;我们可以在Excel中进行运算&#xff0c;然后连接到ArcGIS中&#xff0c;这里主要介绍下通过属性表字段计算器的操作方法。目标① 合并“名称”、“代码”字段内容到新建字段“用地…

ds排序--希尔排序_图解直接插入排序和希尔排序

前言这次我们介绍插入类排序中的 直接插入排序 和 希尔排序 。对于直接插入排序&#xff0c;虽然它的时间复杂度也是 O(n^2) &#xff0c;但是在元素 有序或近乎有序 的情况下&#xff0c;时间复杂度可以降为 O(n) &#xff0c;效率比 O(nlogn) 的算法还要高。然而对于大规模的…

jsf 配置_JSF Tomcat配置示例

jsf 配置JavaServer Faces (JSF)是一个Web应用程序框架&#xff0c;旨在简化基于Web的用户界面的开发集成。 它用于开发和构建服务器端用户界面组件&#xff0c;并在Web应用程序中使用它们。 JSF技术基于Model-View-Controller (MVC)架构&#xff0c;并且通过在页面中使用可重用…

无法加载可扩展计数器_多核可扩展计数器

无法加载可扩展计数器到处都需要计数器&#xff0c;例如&#xff0c;查找应用程序的关键KPI&#xff0c;应用程序的负载&#xff0c;服务的请求总数&#xff0c;用于查找应用程序吞吐量的一些KPI等。 由于所有这些需求&#xff0c;并发复杂性也增加了&#xff0c;这使这个问题…

linux忘记mysql密码_linux下忘记mysql root密码解决办法 | 系统运维

引言&#xff1a;在linux系统中&#xff0c;如果忘记了MySQL的root密码&#xff0c;有没有办法重新设置新密码呢&#xff1f;答案是肯定的&#xff0c;下面教大家一个比较简单的重置MySQL root密码的办法&#xff1a;1、编辑MySQL配置文件my.cnf系统运维www.osyunwei.com温馨提…

mysql中cast函数_mysql中cast函数的使用 用于强制类型转换 (转载)

例子&#xff1a;SELECTstr_to_date(concat(year(a.tb_time),date_format(a.tb_time,%m),01),%Y%m%d) tb_time,cast(a.category_id as char) category_id,a.category_name,sum(a.tendered_sum)/sum(a.winbid) tendered_sum,sum(a.winbid_sum)/sum(a.winbid) winbid_avgfrom( SE…

dht11温湿度传感器_Arduino不调用库实现DHT11数据读取

DHT11概述DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器&#xff0c;它应用专用的数字模块采集技术和温湿度传感技术&#xff0c;确保产品具有极高的可靠性和卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC测温元件&#xff0c;并与一个高性…

rete_RIP RETE时间来获得PHREAKY

rete我刚刚完成了有关新规则算法PHREAK的高级文档&#xff0c;PHREAK是混合推理中的一个文字游戏。 它仍然有点粗糙和高水平&#xff0c;但希望仍然很有趣。 它建立在ReteOO之上&#xff0c;非常好阅读。 ReteOO算法 ReteOO是在3、4和5系列发行版中开发的。 它采用了RETE算法并…

java如果把字符串转成对象_Java中的重复对象:不仅仅是字符串

当Java应用程序消耗大量内存时&#xff0c;它本身就会出现问题&#xff0c;并可能导致GC压力增加和GC暂停时间过长。在我之前的一篇文章中&#xff0c;我讨论了Java中常见的内存浪费源&#xff1a;重复字符串。两个 java.lang.String 对象&#xff0c; a 并 b 在重复时 a ! b &…

批处理 设置电脑最佳性能_批处理最佳做法

批处理 设置电脑最佳性能大多数应用程序至少具有一个批处理任务&#xff0c;在后台执行特定的逻辑。 编写批处理作业并不复杂&#xff0c;但是您需要了解一些基本规则&#xff0c;我将列举一些我发现最重要的规则。 从输入类型的角度来看&#xff0c;处理项目可以通过轮询处理…

JVM体系结构:JVM类加载器和运行时数据区

各位读者好&#xff01; 在JVM系列的上一篇文章中&#xff0c;开发人员了解了Java虚拟机&#xff08;JVM&#xff09;及其体系结构。 本教程将帮助开发人员正确回答以下主题的问题&#xff1a; ClassLoader子系统 运行时数据区 1.简介 在继续之前&#xff0c;让我们看一下Ja…

mysql5.6特性_MySQL5.6新版本特性

MySQL已发布新的系列版本5.6.x&#xff0c;如果打算升级的朋友可以尝试&#xff0c;虽然目前没有收到新版本的使用反馈&#xff0c;但凭借MySQL占据市场份额来看&#xff0c;新版本的确值得期待。五大特性&#xff1a;优化器的改进MySQL Optimizer 团队做了大量的工作为了不断的…

java计算整数出现的次数_[剑指offer题解][Java]1到n整数中1出现的次数

前言众所周知&#xff0c;《剑指offer》是一本“好书”。如果你是个算法菜鸡&#xff08;和我一样&#xff09;&#xff0c;那么最推荐的是先把剑指offer的题目搞明白。对于剑指offer题解这个系列&#xff0c;我的写作思路是&#xff0c;对于看过文章的读者&#xff0c;能够做到…

mysql 更改root密码及 主机_设置更改root密码(远程,本地)、连接mysql、mysql常用命令...

设置更改root密码1、将mysql加入环境变量中[rootcentos7 ~]# grep mysql /etc/profileexport PATH/usr/local/mysql/bin/:$PATH2、直接登录&#xff0c;无密码[rootcentos7 ~]# mysql -uroot3、方式一&#xff1a;设置密码[rootcentos7 ~]# mysqladmin -uroot password 123456W…