spring源码解读之getBean方法(一)

article/2025/10/26 3:34:15

前言

大家使用spring,最常接触到的就是bean,大家也知道spring中用一句getBean就能取出一个实例化好的bean,这个bean是属于IOC容器管理的,那么大家有没有看过getBean方法的源码呢,知不知道spring容器到底是怎么得到一个实例化好的bean的呢,这一次,我和大家一起来研究getBean方法的源码

开始

首先我来一段非常简单的代码

//我是用注解方式配置的applicationContext,Appconfig就是配置类,用来扫描bean的
AnnotationConfigApplicationContext annotationConfigApplicationContext= new AnnotationConfigApplicationContext(Appconfig.class);
annotationConfigApplicationContext.getBean(IndexService.class)

接着我们点到getBean方法里面,可以看到一开始进到了org.springframework.context.support.AbstractApplicationContext#getBean(java.lang.Class<T>)

@Override
public <T> T getBean(Class<T> requiredType) throws BeansException {//assertBeanFactoryActive();return getBeanFactory().getBean(requiredType);
}

然后我们看这里的这个getBean,实际上是调用了org.springframework.beans.factory.support.DefaultListableBeanFactory#getBean(java.lang.Class<T>)这个getBean方法

@Override
public <T> T getBean(Class<T> requiredType) throws BeansException {/***  getBean 是一个空壳方法,所有的逻辑都封装在 doGetBean 方法中,等一下会看到*/return getBean(requiredType, (Object[]) null);
}

这个DefaultListableBeanFactory很重要,我们知道spring IOC的顶层接口实际上是BeanFactory,而真正能作为独立的ioc容器使用的还是DefaultListableBeanFactory,我们来看下整体类图

可以看到DefaultListableBeanFactory继承了ConfigureableListableBeanFactory接口,BeanDefinitionRegistry接口(bean定义的注册接口),并继承AutowireCapableBeanFactory,实现全部类管理的功能。DefaultListableBeanFactory其实要实现的功能就是以list集合的方式操作bean,最典型的应用是:在访问bean前,先注册所有的definition(可能从bean definition配置文件中)。使用预先建立的bean定义元数据对象,从本地的bean definition表中查询bean definition因而将不会花费太多成本。今天我们的重点不在DefaultListableBeanFactory这个类上,所以就不展开研究这个类了,我们接下去看

@Overridepublic <T> T getBean(Class<T> requiredType, @Nullable Object... args) throws BeansException {//NamedBeanHolder 可以理解为一个数据结构和map差不多,里面就是存了bean的名字和bean的实例//A simple holder for a given bean name plus bean instance//一个简单的bean和名字的容器//通过resolveNamedBean方法得到这个holderNamedBeanHolder<T> namedBean = resolveNamedBean(requiredType, args);if (namedBean != null) {//获取有名字的Bean的实例return namedBean.getBeanInstance();}//上层Bean工厂BeanFactory parent = getParentBeanFactory();if (parent != null) {return (args != null ? parent.getBean(requiredType, args) : parent.getBean(requiredType));}throw new NoSuchBeanDefinitionException(requiredType);}

我们看一下NamedBeanHolder这个类是怎么定义的

/*** A simple holder for a given bean name plus bean instance.** @author Juergen Hoeller* @since 4.3.3* @see AutowireCapableBeanFactory#resolveNamedBean(Class)*/
public class NamedBeanHolder<T> implements NamedBean {private final String beanName;private final T beanInstance;/*** Create a new holder for the given bean name plus instance.* @param beanName the name of the bean* @param beanInstance the corresponding bean instance*/public NamedBeanHolder(String beanName, T beanInstance) {Assert.notNull(beanName, "Bean name must not be null");this.beanName = beanName;this.beanInstance = beanInstance;}/*** Return the name of the bean.*/@Overridepublic String getBeanName() {return this.beanName;}/*** Return the corresponding bean instance.*/public T getBeanInstance() {return this.beanInstance;}}

这里的getBean的关键代码在于resolveNamedBean(requiredType, args),这段代码获得了这个holder,其实也就是获得了bean的名字和bean的实例,那么这里就要具体看一下是怎么获得的bean名字和bean实例了。废话不多上代码

@SuppressWarnings("unchecked")@Nullableprivate <T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType, @Nullable Object... args) throws BeansException {Assert.notNull(requiredType, "Required type must not be null");//得到可能的bean名字数组String[] candidateNames = getBeanNamesForType(requiredType);/*** 得到对象的名字,因为对象可能有别名所以需要处理别名*/if (candidateNames.length > 1) {List<String> autowireCandidates = new ArrayList<>(candidateNames.length);for (String beanName : candidateNames) {if (!containsBeanDefinition(beanName) || getBeanDefinition(beanName).isAutowireCandidate()) {autowireCandidates.add(beanName);}}if (!autowireCandidates.isEmpty()) {candidateNames = StringUtils.toStringArray(autowireCandidates);}}if (candidateNames.length == 1) {String beanName = candidateNames[0];//这的getBean才是真正获取对象的方法return new NamedBeanHolder<>(beanName, getBean(beanName, requiredType, args));}else if (candidateNames.length > 1) {Map<String, Object> candidates = new LinkedHashMap<>(candidateNames.length);for (String beanName : candidateNames) {if (containsSingleton(beanName) && args == null) {Object beanInstance = getBean(beanName);candidates.put(beanName, (beanInstance instanceof NullBean ? null : beanInstance));}else {candidates.put(beanName, getType(beanName));}}String candidateName = determinePrimaryCandidate(candidates, requiredType);if (candidateName == null) {candidateName = determineHighestPriorityCandidate(candidates, requiredType);}if (candidateName != null) {Object beanInstance = candidates.get(candidateName);if (beanInstance == null || beanInstance instanceof Class) {beanInstance = getBean(candidateName, requiredType, args);}return new NamedBeanHolder<>(candidateName, (T) beanInstance);}throw new NoUniqueBeanDefinitionException(requiredType, candidates.keySet());}return null;}

在这一段代码中,我们首先要看String[] candidateNames = getBeanNamesForType(requiredType);这句代码,这个方法进去之后其实会调用很多层

@Overridepublic String[] getBeanNamesForType(@Nullable Class<?> type) {return getBeanNamesForType(type, true, true);}@Overridepublic String[] getBeanNamesForType(@Nullable Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {if (!isConfigurationFrozen() || type == null || !allowEagerInit) {//这句代码才是真正通过类型获取名字的代码return doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, allowEagerInit);}Map<Class<?>, String[]> cache =(includeNonSingletons ? this.allBeanNamesByType : this.singletonBeanNamesByType);String[] resolvedBeanNames = cache.get(type);if (resolvedBeanNames != null) {return resolvedBeanNames;}resolvedBeanNames = doGetBeanNamesForType(ResolvableType.forRawClass(type), includeNonSingletons, true);if (ClassUtils.isCacheSafe(type, getBeanClassLoader())) {cache.put(type, resolvedBeanNames);}return resolvedBeanNames;}//根据类型去factory中获取对应类的名字//比如在工厂初始化的时候可以根据BeanFactory去获取所有的BeanFactoryProcessorprivate String[] doGetBeanNamesForType(ResolvableType type, boolean includeNonSingletons, boolean allowEagerInit) {List<String> result = new ArrayList<>();// Check all bean definitions.for (String beanName : this.beanDefinitionNames) {// Only consider bean as eligible if the bean name// is not defined as alias for some other bean.if (!isAlias(beanName)) {try {RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);// Only check bean definition if it is complete.if (!mbd.isAbstract() && (allowEagerInit ||(mbd.hasBeanClass() || !mbd.isLazyInit() || isAllowEagerClassLoading()) &&!requiresEagerInitForType(mbd.getFactoryBeanName()))) {// In case of FactoryBean, match object created by FactoryBean.boolean isFactoryBean = isFactoryBean(beanName, mbd);BeanDefinitionHolder dbd = mbd.getDecoratedDefinition();boolean matchFound =(allowEagerInit || !isFactoryBean ||(dbd != null && !mbd.isLazyInit()) || containsSingleton(beanName)) &&(includeNonSingletons ||(dbd != null ? mbd.isSingleton() : isSingleton(beanName))) &&isTypeMatch(beanName, type);if (!matchFound && isFactoryBean) {// In case of FactoryBean, try to match FactoryBean instance itself next.beanName = FACTORY_BEAN_PREFIX + beanName;matchFound = (includeNonSingletons || mbd.isSingleton()) && isTypeMatch(beanName, type);}if (matchFound) {result.add(beanName);}}}catch (CannotLoadBeanClassException ex) {if (allowEagerInit) {throw ex;}// Probably a class name with a placeholder: let's ignore it for type matching purposes.if (logger.isDebugEnabled()) {logger.debug("Ignoring bean class loading failure for bean '" + beanName + "'", ex);}onSuppressedException(ex);}catch (BeanDefinitionStoreException ex) {if (allowEagerInit) {throw ex;}// Probably some metadata with a placeholder: let's ignore it for type matching purposes.if (logger.isDebugEnabled()) {logger.debug("Ignoring unresolvable metadata in bean definition '" + beanName + "'", ex);}onSuppressedException(ex);}}}// Check manually registered singletons too.for (String beanName : this.manualSingletonNames) {try {// In case of FactoryBean, match object created by FactoryBean.if (isFactoryBean(beanName)) {if ((includeNonSingletons || isSingleton(beanName)) && isTypeMatch(beanName, type)) {result.add(beanName);// Match found for this bean: do not match FactoryBean itself anymore.continue;}// In case of FactoryBean, try to match FactoryBean itself next.beanName = FACTORY_BEAN_PREFIX + beanName;}// Match raw bean instance (might be raw FactoryBean).if (isTypeMatch(beanName, type)) {result.add(beanName);}}catch (NoSuchBeanDefinitionException ex) {// Shouldn't happen - probably a result of circular reference resolution...if (logger.isDebugEnabled()) {logger.debug("Failed to check manually registered singleton with name '" + beanName + "'", ex);}}}return StringUtils.toStringArray(result);}

可能看到这里有的人已经有疑问了,名字一样为什么要调用3次getBeanNamesForType这个方法?其实仔细看就会发现这三个方法的签名不同 ,spring这么做我理解可能是为了更方便传递参数,因为每一次调用都会传递更多的参数进去,其实spring有很多类都是这样的重载方法,然后嵌套多层调用。

然后最最关键的就是这句代码了return new NamedBeanHolder<>(beanName, getBean(beanName, requiredType, args));这句代码中的getBean,才是真正去拿Bean的方法。我们看到先进入了org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String, java.lang.Class<T>, java.lang.Object...)这个方法

public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args)throws BeansException {/*** 这里又是一个空方法*/return doGetBean(name, requiredType, args, false);}

下面这个doGetBean方法的代码比较长,还请大家耐心的看下去

@SuppressWarnings("unchecked")protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {/*** 通过 name 获取 beanName。这里不使用 name 直接作为 beanName 有两个原因* 1、name 可能会以 & 字符开头,表明调用者想获取 FactoryBean 本身,而非 FactoryBean*   实现类所创建的 bean。在 BeanFactory 中,FactoryBean 的实现类和其他的 bean 存储*   方式是一致的,即 <beanName, bean>,beanName 中是没有 & 这个字符的。所以我们需要*   将 name 的首字符 & 移除,这样才能从缓存里取到 FactoryBean 实例。* 2、还是别名的问题,转换需要* &beanName*/final String beanName = transformedBeanName(name);Object bean;// Eagerly check singleton cache for manually registered singletons./*** 这个方法在初始化的时候会调用,在getBean的时候也会调用* 为什么需要这么做呢?* 也就是说spring在初始化的时候先获取这个对象* 判断这个对象是否被实例化好了(普通情况下绝对为空====有一种情况可能不为空)* 从spring的bean容器中获取一个bean,由于spring中bean容器是一个map(singletonObjects)* 所以你可以理解getSingleton(beanName)等于beanMap.get(beanName)* 需要说明的是在初始化时候调用一般都是返回null*/// 先从缓存中获取,因为在容器初始化的时候或者其他地方调用过getBean,已经完成了初始化Object sharedInstance = getSingleton(beanName);// 如果已经初始化过,直接从缓存中获取if (sharedInstance != null && args == null) {//这里的代码是对于日志的记录,方便我们以后阅读应该注释,不影响spring功能
//			if (logger.isDebugEnabled()) {
//				if (isSingletonCurrentlyInCreation(beanName)) {
//					logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
//							"' that is not fully initialized yet - a consequence of a circular reference");
//				}
//				else {
//					logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
//				}
//			}/*** 如果 sharedInstance 是普通的单例 bean,下面的方法会直接返回。但如果* sharedInstance 是 FactoryBean 类型的,则需调用 getObject 工厂方法获取真正的* bean 实例。如果用户想获取 FactoryBean 本身,这里也不会做特别的处理,直接返回* 即可。毕竟 FactoryBean 的实现类本身也是一种 bean,只不过具有一点特殊的功能而已。*/bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);}else {// Fail if we're already creating this bean instance:// We're assumably within a circular reference./*** 原型* 如果是原型不应该在初始化的时候创建,在这里直接抛出异常*/if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}// Check if bean definition exists in this factory.BeanFactory parentBeanFactory = getParentBeanFactory();if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {// Not found -> check parent.String nameToLookup = originalBeanName(name);if (parentBeanFactory instanceof AbstractBeanFactory) {return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);}else if (args != null) {// Delegation to parent with explicit args.return (T) parentBeanFactory.getBean(nameToLookup, args);}else {// No args -> delegate to standard getBean method.return parentBeanFactory.getBean(nameToLookup, requiredType);}}if (!typeCheckOnly) {//添加到alreadyCreated set集合当中,表示他已经创建过一次markBeanAsCreated(beanName);}try {final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);checkMergedBeanDefinition(mbd, beanName, args);//检查是否有depends on// Guarantee initialization of beans that the current bean depends on.String[] dependsOn = mbd.getDependsOn();if (dependsOn != null) {for (String dep : dependsOn) {if (isDependent(beanName, dep)) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");}registerDependentBean(dep, beanName);try {getBean(dep);}catch (NoSuchBeanDefinitionException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"'" + beanName + "' depends on missing bean '" + dep + "'", ex);}}}//创建bean实例// Create bean instance.if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, () -> {try {return createBean(beanName, mbd, args);}catch (BeansException ex) {// Explicitly remove instance from singleton cache: It might have been put there// eagerly by the creation process, to allow for circular reference resolution.// Also remove any beans that received a temporary reference to the bean.destroySingleton(beanName);throw ex;}});bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}else if (mbd.isPrototype()) {// It's a prototype -> create a new instance.Object prototypeInstance = null;try {beforePrototypeCreation(beanName);prototypeInstance = createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}else {String scopeName = mbd.getScope();final Scope scope = this.scopes.get(scopeName);if (scope == null) {throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");}try {Object scopedInstance = scope.get(beanName, () -> {beforePrototypeCreation(beanName);try {return createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}});bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);}catch (IllegalStateException ex) {throw new BeanCreationException(beanName,"Scope '" + scopeName + "' is not active for the current thread; consider " +"defining a scoped proxy for this bean if you intend to refer to it from a singleton",ex);}}}catch (BeansException ex) {cleanupAfterBeanCreationFailure(beanName);throw ex;}}// Check if required type matches the type of the actual bean instance.if (requiredType != null && !requiredType.isInstance(bean)) {try {T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);if (convertedBean == null) {throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}return convertedBean;}catch (TypeMismatchException ex) {if (logger.isDebugEnabled()) {logger.debug("Failed to convert bean '" + name + "' to required type '" +ClassUtils.getQualifiedName(requiredType) + "'", ex);}throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());}}return (T) bean;}

从这个方法开始,就要进入拿bean的过程了,首先是从缓存中拿,因为doGetBean有很多地方会调用,可能当前调用的时候缓存里已经有bean存在了。缓存中拿bean的真正方法是org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)

@Nullableprotected Object getSingleton(String beanName, boolean allowEarlyReference) {//从map中获取bean如果不为空直接返回,不再进行初始化工作//一个程序员提供的对象这里一般都是为空的Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {synchronized (this.singletonObjects) {singletonObject = this.earlySingletonObjects.get(beanName);if (singletonObject == null && allowEarlyReference) {ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);if (singletonFactory != null) {singletonObject = singletonFactory.getObject();this.earlySingletonObjects.put(beanName, singletonObject);this.singletonFactories.remove(beanName);}}}}return singletonObject;}

总结

为了控制文章的篇幅,下面的代码我会放到第二部分去讲,谢谢大家关注


http://chatgpt.dhexx.cn/article/PkN48hPZ.shtml

相关文章

Spring源码之getBean(获取 bean)方法(一)解读

目录 测试类一个简单的测试类对于 ApplicationContext 和 ClassPathXmlApplicationContext 类图如下getBean() 源码解读查看 AbstractApplicationContext 中的 getBean 方法查看 AbstractBeanFactory 的 doGetBean 方法看 doGetBean 方法的流程图分析doGetBean 方法的主要流程 …

JavaBean(set和get方法)

JavaBean的规范 类中所有的成员属性都是私有&#xff0c;也就是 private 来修饰 提供一个公共无参数的构造方法 为所有私有的属性提供公共的 set 和 get 方法。 set方法 set 方法是有参数无返回值的&#xff0c;目的是通过 set 方法给 javabean 中的私有属性赋值&#xff0c;…

getBean方法源码

一、 三个API // 根据name获取bean Override public Object getBean(String name) throws BeansException {return doGetBean(name, null, null, false); }// 根据name获取bean&#xff0c;如果获取到的bean和指定类型不匹配&#xff0c;则抛出异常 Override public <T>…

详解Spring中getBean()方法

我们日常会经常使用getBean()方法从spring容器中获取我们需要的bean。那么&#xff0c;getBean()方法是怎么一步步完成从spring容器中获取bean的呢&#xff1f; 下面我们就通过源码分析一下。 一、主要代码分析 基于&#xff1a;spring5.1 入口&#xff1a;AbstractBeanFactory…

getBean方法(一)

我们先看看这个方法的轮廓流程 这个getbean的轮廓方法很长. 先分两种情况: 一种是在缓存实例中能拿到bean, (主要是factroyBean的处理, 执行所有已注册的 BeanPostProcessor 的 postProcessAfterInitialization 方法) 前边是校验 (如果name以“&”为前缀&#xff0c;但是b…

Spring源码分析之getBean主流程分析

当我们通过向Spring容器获取某个bean的时候&#xff0c;总是调用Spring中重载的各种getBean方法。那么&#xff0c;getBean中的流程是什么样的&#xff1f; 通过本文&#xff0c;你将对getBean方法的主流程有一个详细的认识。 入口当然是getBean方法&#xff1a; public Obje…

getBean( )流程

getBean() 方法是顶层接口 BeanFactory 提供的&#xff0c;一共五个原型。AbstractBeanFactory作为抽象实现&#xff0c;复写了其中3个方法&#xff0c; Overridepublic Object getBean(String name) throws BeansException {return doGetBean(name, null, null, false);}Overr…

Prometheus监控MongoDB数据库

监控环境&#xff1a;Prometheus 数据库&#xff1a;MongoDB 3.4.6 集群&#xff0c;3个节点 监控工具&#xff1a;mongodb_exporter 我这个模板是自己二次开发的。使用mongodb_exporter 监控 阿里云的MongoDB数据库 各位根据自己的需求进行使用 1、创建Mongodb监控可读账…

DBeaver 数据库管理工具

DBeaver 数据库管理工具 DBeaver 是一个基于 Java 开发&#xff0c;免费开源的通用数据库管理和开发工具&#xff0c;使用非常友好&#xff0c;且遵循ASL 协议。由于 DBeaver 基于 Java 开发&#xff0c;可以运行在各种操作系统上&#xff0c;比如Windows、Linux、macOS 等操作…

mysql数据库监控

MySQL是一个关系型数据库管理系统&#xff0c;由瑞典MySQL AB 公司开发&#xff0c;属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一&#xff0c;在 WEB 应用方面&#xff0c;MySQL是最好的 RDBMS (Relational Database Management System&#xff0c;关系数据…

一些数据库监控,优化,管理工具

http://www.itpub.net/viewthread.php?tid1057814&extra&page1 一些数据库监控,优化,管理工具 ******************************************************************* 这两天网盘连不上了&#xff0c;导致国内用户暂时无法下载。大家下载时需要用代理。这里提供一个比…

oracle实时监控工具

oracle实时监控工具市面上不多&#xff0c;但是兼具数据维护管理及性能实时监控的工具可以说更少&#xff0c;而实时监控又是项目运维管理&#xff0c;测试&#xff0c;开发但环节不可少的功能&#xff0c;目前有一款JAVA开发的&#xff0c;基于WEB的&#xff1a;TreeSoft数据库…

数据库的可用监控

监控 数据库是否连接和读写以及数据库的连接数 1、确认数据库是否可以通过网络连接 造成连接不成功的原因&#xff1a;防火墙 TCP/IP连接被占满 监控的方式&#xff1a; 1、mysqladmin -u 监控用户 -p 密码 -h 监控的服务器地址 ping 首先我们在MySQL下要建立一个mysql 的用户…

数据库实时监控,实时监控数据库数据

为了满足大多数用户对数据库的监控和运维需求&#xff0c;系统实时采集了监控数据库的主要指标&#xff0c;并提供完整的报警、性能容量分析和报告功能。  系统以数字形式收集现场设备发送的数据&#xff0c;通过实时数据操作实现监控功能&#xff0c;并提供有利于监控生产过…

数据库监控工具SQL Monitor:可同时实现云和本地的SQL Server数据库监视

SQL Monitor提供了一个基于Web的监视&#xff0c;在桌面计算机和移动设备上实时地监控服务器的性能。使用SQL Monitor时&#xff0c;只要一出现问题&#xff0c;你将会通过邮件和用户界面接收到警告&#xff0c;SQL Monitor会快速地做全局检查&#xff0c;检查单机&#xff0c;…

mysql实时监控工具

mysql实时监控工具市面上有许多了&#xff0c;但是兼具数据维护管理及性能实时监控的工具不多&#xff0c;可以说很少&#xff0c;而实时监控又是项目运维管理&#xff0c;测试&#xff0c;开发但环节不可少的功能&#xff0c;目前有一款JAVA开发的&#xff0c;基于WEB的&#…

数据库监控

数据库监控 一、数据库监控介绍 1、对什么进行监控 (1) 对数据库服务可用性进行监控 数据库进程或是端口存在并不意味着数据库就是可用的&#xff1b; 通过网络连接到数据库并且确定数据库是可以对外提供服务的。 (2) 对数据库性能进行监控 QPS和TPS&#xff1b; 并发线程数量…

MySQL - 数据库的监控方式

对于当前数据库的监控方式有很多&#xff0c;分为数据库自带、商用、开源三大类&#xff0c;每一种都有各自的特色&#xff1b; 而对于 mysql 数据库由于其有很高的社区活跃度&#xff0c;监控方式更是多种多样&#xff0c;不管哪种监控方式最核心的就是监控数据&#xff0c;获…

现在的SQLSERVER数据库监控软件有哪些?

现在的SQLSERVER数据库监控软件有哪些&#xff1f; 收集了一下当前SQLSERVER数据库监控软件&#xff0c;发现开源免费的真的是“没有” Questsoftware Quests spotlight&#xff08;收费&#xff09; http://www.quest.com/search/search-results.aspx?qspotlight Ideras S…

2019年最好用的6款数据库监控工具

为了让数据发挥最大的价值&#xff0c;通常我们都会采用数据库监控工具&#xff0c;本文将为大家介绍 6 款最好用的数据库监控工具。 "数据就是一切&#xff01;"我们都曾听过这种大胆的说法&#xff0c;但其实事实真是这样&#xff0c;而且数据还无处不在。如今&…