Spring实例化源码解析之Bean的实例化(十二)

news2025/2/25 12:39:39

前言

本章开始分析finishBeanFactoryInitialization(beanFactory)方法,直译过来就是完成Bean工厂的初始化,这中间就是非lazy单例Bean的实例化流程。ConversionService在第十章已经提前分析了。重点就是最后一句,我们的bean实例化分析就从这里开始。

本章主要是实例化流程的分析,不会太深入到细节

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		// Initialize conversion service for this context.
		// ConversionService(转换服务)在spring框架中用于处理类型转换的任务。它提供了一种统一的方式来执行各种类型之间的转换操作,
		// 包括字符串到其他类型的转换、日期和时间的转换、数字类型的转换等。
		if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
				beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
			beanFactory.setConversionService(
					beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
		}

		// Register a default embedded value resolver if no BeanFactoryPostProcessor
		// (such as a PropertySourcesPlaceholderConfigurer bean) registered any before:
		// at this point, primarily for resolution in annotation attribute values.
		if (!beanFactory.hasEmbeddedValueResolver()) {
			beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
		}

		// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
		for (String weaverAwareName : weaverAwareNames) {
			getBean(weaverAwareName);
		}

		// Stop using the temporary ClassLoader for type matching.
		beanFactory.setTempClassLoader(null);

		// Allow for caching all bean definition metadata, not expecting further changes.
		beanFactory.freezeConfiguration();

		// Instantiate all remaining (non-lazy-init) singletons.
		beanFactory.preInstantiateSingletons();
	}

预处理单例bean

preInstantiateSingletons() 是 Spring 容器的一个方法,它用于预实例化所有的单例(Singleton)Bean。

@Override
	public void preInstantiateSingletons() throws BeansException {
		if (logger.isTraceEnabled()) {
			logger.trace("Pre-instantiating singletons in " + this);
		}

		// Iterate over a copy to allow for init methods which in turn register new bean definitions.
		// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {
			// 通过bean的名称去获取bean的定义信息
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			// 不是抽象类&&是单例的&&不是懒加载
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				if (isFactoryBean(beanName)) {
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged(
									(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
							getBean(beanName);
						}
					}
				}
				else {
					getBean(beanName);
				}
			}
		}

		// Trigger post-initialization callback for all applicable beans...
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
						.tag("beanName", beanName);
				SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
				smartInitialize.end();
			}
		}
	}

这个预处理单例bean的实例化其实非常简单,我们简要分析一下整体流程:

  • 获取到当前所有的beanDefinitionNames,用于迭代。
  • 循环所有的beanDefinitionNames,也就是beanNamess
  • 获取beanName的定义信息,用于后续判断
  • 如果是抽象类,或者不是单例或者是懒加载bean就不处理。
  • 其他情况下会进入getBean逻辑,这个方法我们经常用来从 BeanFactory 中获取一个 Bean,而初始化的过程也封装到了这个方法里。

getBean/doGetBean

Spring源码中很多时候真正做事的是do开头的,个人经验。

@Override
	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}

transformedBeanName

获取beanName,如果是FactoryBean是会以&开头,也就是说这里返回的就是单纯的beanName

String beanName = transformedBeanName(name);

	public static String transformedBeanName(String name) {
		Assert.notNull(name, "'name' must not be null");
		if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
			return name;
		}
		return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
			do {
				beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
			}
			while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
			return beanName;
		});
	}

getSingleton

这里就是常说的三级缓存。在实例化的时候先要去三级缓存中查看是否存在了,需不需要走后续的实例化流程。

Object sharedInstance = getSingleton(beanName);

@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// Quick check for existing instance without full singleton lock
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			singletonObject = this.earlySingletonObjects.get(beanName);
			if (singletonObject == null && allowEarlyReference) {
				synchronized (this.singletonObjects) {
					// Consistent creation of early reference within full singleton lock
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						singletonObject = this.earlySingletonObjects.get(beanName);
						if (singletonObject == null) {
							ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
							if (singletonFactory != null) {
								singletonObject = singletonFactory.getObject();
								this.earlySingletonObjects.put(beanName, singletonObject);
								this.singletonFactories.remove(beanName);
							}
						}
					}
				}
			}
		}
		return singletonObject;
	}

从上述代码中,我们知道有三个Map对象,也就是我们常说的三级缓存,实际上就是以下这三个Map。

/** Cache of singleton objects: bean name to bean instance. */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** Cache of singleton factories: bean name to ObjectFactory. */
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

	/** Cache of early singleton objects: bean name to bean instance. */
	private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
  • 一级缓存:singletonObjects缓存的是单例对象,key是beanName value是bean的实例。
  • 二级缓存:earlySingletonObjects缓存的是早期的单例对象,key是beanName value是bean的实例。
  • 三级缓存:singletonFactories缓存的是ObjectFactory,key是beanName value是ObjectFactory。

回到getSingleton方法,首先spring尝试通过beanName从一级缓存中获取,如果一级缓存中不存在,并且当前bean并不是正在创建中的话直接返回null。只有当bean正在创建中的时候才回去从二级缓存中获取,如果二级缓存中获取不到再从三级缓存中去获取。此处我们先大概有这么一个概念,后续会在循环依赖章节详细描述。

如果当前获取到的sharedInstance不为空且不是FacotyBean的话就直接返回回去了。如果为空继续走后续的逻辑。

dependsOn

根据BeanDefinition获取是否有依赖的bean,如果有的话先把其他bean实例化完成。@DependsOn的注解的作用就在这里可以体现。

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);
						}
					}
				}

singletonsCurrentlyInCreation

如果是单例的,就会调用 getSingleton(String beanName, ObjectFactory<?> singletonFactory)方法。

  • 第一个参数就是beanName
  • 第二个参数是一个FunctionalInterface
if (mbd.isSingleton()) {
					// 先执行getSingleton方法,然后在代码中会调用createBean方法
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							destroySingleton(beanName);
							throw ex;
						}
					});
					beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}

执行getSingleton方法,代码如下

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(beanName, "Bean name must not be null");
		synchronized (this.singletonObjects) {
			Object singletonObject = this.singletonObjects.get(beanName);
			if (singletonObject == null) {
				if (this.singletonsCurrentlyInDestruction) {
					throw new BeanCreationNotAllowedException(beanName,
							"Singleton bean creation not allowed while singletons of this factory are in destruction " +
							"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
				}
				if (logger.isDebugEnabled()) {
					logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
				}
				// 对象是否正在创建中 singletonsCurrentlyInCreation,避免循环依赖的一种操作
				beforeSingletonCreation(beanName);
				boolean newSingleton = false;
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
					// 在这里调用外出的createBean返回的就是springbean,然后后续执行缓存的相关操作
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}
				catch (IllegalStateException ex) {
					// Has the singleton object implicitly appeared in the meantime ->
					// if yes, proceed with it since the exception indicates that state.
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						throw ex;
					}
				}
                catch (BeanCreationException ex) {
					if (recordSuppressedExceptions) {
						for (Exception suppressedException : this.suppressedExceptions) {
							ex.addRelatedCause(suppressedException);
						}
					}
					throw ex;
				}
				finally {
					if (recordSuppressedExceptions) {
						this.suppressedExceptions = null;
					}
					afterSingletonCreation(beanName);
				}
				if (newSingleton) {
					addSingleton(beanName, singletonObject);
				}
			}
			return singletonObject;
		}
	}

首先这个放回加了一个synchronized的锁,锁的是一级缓存对象,也就是说对象的实例化是线程安全的,不让其在实例化的时候出现重复创建。获取锁之后会再从缓存中去获取当前beanName是否存在实例,如果没有的话会执行beforeSingletonCreation(beanName)。

protected void beforeSingletonCreation(String beanName) {
		if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}
	}

此处的核心就是singletonsCurrentlyInCreation集合的add方法,就是提前曝光的地方。

private final Set<String> singletonsCurrentlyInCreation =
			Collections.newSetFromMap(new ConcurrentHashMap<>(16));

直接就是会调用传入的FunctionalInterface,也就是执行createBean方法。

		try {
					// 在这里调用外出的createBean返回的就是springbean,然后后续执行缓存的相关操作
					singletonObject = singletonFactory.getObject();
					newSingleton = true;
				}

createBean/doCreateBean

在执行doCreateBean的时候会调用构造方法

if (instanceWrapper == null) {
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}

然后判断beanDefinition信息是单例的,并且是允许循环依赖的(默认为允许)并且当前的bean是正在创建中就会进入if的逻辑。

addSingletonFactory,从名字开发猜测是否和我们的三级缓存有关联。

boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

addSingletonFactory方法的参数如下:

  • beanName,bean的名称
  • ObjectFactory,函数式接口,之前看getSingleton(name)方法的时候也知道,会调用这个getObject方法来获取对象放入二级缓存中。

一级缓存中不存在就将这个ObjectFactory放入三级缓存,同时清理掉二级缓存和加入已注册的有序集合中。

protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(singletonFactory, "Singleton factory must not be null");
		synchronized (this.singletonObjects) {
			if (!this.singletonObjects.containsKey(beanName)) {
				
				this.singletonFactories.put(beanName, singletonFactory);
				
				this.earlySingletonObjects.remove(beanName);
				
				this.registeredSingletons.add(beanName);
			}
		}
	}

populateBean

填充bean,也就是属性注入。这里会去解析bean的依赖,从而继续去走getBean的逻辑来让当前bean实例化完整。

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
		if (bw == null) {
			if (mbd.hasPropertyValues()) {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
			}
			else {
				// property mean 属性
				// Skip property population phase for null instance.
				return;
			}
		}

		// Give any InstantiationAwareBeanPostProcessors the opportunity to modify the
		// state of the bean before properties are set. This can be used, for example,
		// to support styles of field injection.
		// 在属性填充之前给任意InstantiationAwareBeanPostProcessors一个机会去修改bean的状态
		// 后置处理器可以被使用在例如:支持字段注入的样式.
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
				if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
					return;
				}
			}
		}


     	PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

		int resolvedAutowireMode = mbd.getResolvedAutowireMode();
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			// Add property values based on autowire by name if applicable.
			if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
				autowireByName(beanName, mbd, bw, newPvs);
			}
			// Add property values based on autowire by type if applicable.
			if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
				autowireByType(beanName, mbd, bw, newPvs);
			}
			pvs = newPvs;
		}

		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

		PropertyDescriptor[] filteredPds = null;
		if (hasInstAwareBpps) {
			if (pvs == null) {
				pvs = mbd.getPropertyValues();
			}
			// 实例化感知的BeanPostProcessor
			for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
				// 默认的情况下resolvedAutowireMode是为0的,所以默认是AutoWiredAnnotationBeanPostProcessor进行自动装配
  				PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
				if (pvsToUse == null) {
					if (filteredPds == null) {
						filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
					}
					// 在这里面回去校验属性的版本信息(BeanNotOfRequiredTypeException)
					/**
					 *Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException:
					 * Error creating bean with name 'b': Unsatisfied dependency expressed through field 'a';
					 * nested exception is org.springframework.beans.factory.BeanNotOfRequiredTypeException:
					 * Bean named 'a' is expected to be of type 'com.qhyu.cloud.circlarRefrence.A' but was actually of type 'com.sun.proxy.$Proxy34'
					 */
					pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) {
						return;
					}
				}
				pvs = pvsToUse;
			}
		}
		if (needsDepCheck) {
			if (filteredPds == null) {
				filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			}
			checkDependencies(beanName, mbd, filteredPds, pvs);
		}

		if (pvs != null) {
			// 属性填充的最后回对spel进行解析
			applyPropertyValues(beanName, mbd, bw, pvs);
		}
	}

initializeBean

如果 bean 实现了 BeanNameAware、BeanClassLoaderAware 或 BeanFactoryAware 接口,回调invokeAwareMethods(beanName, bean)

处理 bean 中定义的 init-method,或者如果 bean 实现了 InitializingBean 接口,调用 afterPropertiesSet() 方法

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			// 先执行beanpostProcessor的before
			// 通过BeanPostProcessor在bean初始化之前做点事情
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			// 再执行initmethods
			// 调用bean的初始化方法进行初始化
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null || !mbd.isSynthetic()) {
			// 再执行BeanPostProcessor的After方法
			// 通过BeanPostProcessor在bean初始化之后做点事情
			// aop的切入点
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

getSingleton

如果创建没有任何问题,newSingleton = true,继续执行 addSingleton(beanName, singletonObject)方法

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(beanName, "Bean name must not be null");
    synchronized (this.singletonObjects) {
       Object singletonObject = this.singletonObjects.get(beanName);
       if (singletonObject == null) {
          if (this.singletonsCurrentlyInDestruction) {
             throw new BeanCreationNotAllowedException(beanName,
                   "Singleton bean creation not allowed while singletons of this factory are in destruction " +
                   "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
          }
          if (logger.isDebugEnabled()) {
             logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
          }
          // 对象是否正在创建中 singletonsCurrentlyInCreation,避免循环依赖的一种操作
          beforeSingletonCreation(beanName);
          boolean newSingleton = false;
          boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
          if (recordSuppressedExceptions) {
             this.suppressedExceptions = new LinkedHashSet<>();
          }
          try {
             // 在这里调用外出的createBean返回的就是springbean,然后后续执行缓存的相关操作
             singletonObject = singletonFactory.getObject();
             newSingleton = true;
          }
          catch (IllegalStateException ex) {
             // Has the singleton object implicitly appeared in the meantime ->
             // if yes, proceed with it since the exception indicates that state.
             singletonObject = this.singletonObjects.get(beanName);
             if (singletonObject == null) {
                throw ex;
             }
          }
          catch (BeanCreationException ex) {
             if (recordSuppressedExceptions) {
                for (Exception suppressedException : this.suppressedExceptions) {
                   ex.addRelatedCause(suppressedException);
                }
             }
             throw ex;
          }
          finally {
             if (recordSuppressedExceptions) {
                this.suppressedExceptions = null;
             }
             afterSingletonCreation(beanName);
          }
          if (newSingleton) {
             addSingleton(beanName, singletonObject);
          }
       }
       return singletonObject;
    }
}

将创建好的bean放入一级缓存,移除一二级缓存。

protected void addSingleton(String beanName, Object singletonObject) {
		// 线程安全的
		synchronized (this.singletonObjects) {
			// 放入一级缓存
			this.singletonObjects.put(beanName, singletonObject);
			// 移除三级缓存
			this.singletonFactories.remove(beanName);
			// 移除二级缓存
			this.earlySingletonObjects.remove(beanName);
			// 已注册的map中把新初始化的bean放入
			this.registeredSingletons.add(beanName);
		}
	}

总结

整个bean的初始化流程就如下图所示,下面的这个图是一个最简单的单例bean的实例化流程,不涉及到循环依赖问题,循环依赖和三级缓存将在下一章详细分析。本章主要了解bean实例化的整体流程,了解和熟悉spring工作模式。

在这里插入图片描述

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

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

相关文章

蓝桥每日一题(day 6: 蓝桥505.数字三角形)--线性dp--easy

题目&#xff1a; 关注&#xff1a; 本题给出了一个限制&#xff0c;“向左下走的次数与向右下走的次数相差不能超过1”。观察一下&#xff0c;发现&#xff1a;当行数为奇数的时候&#xff0c;只有最后一行的中间的f符合要求&#xff1b;当行数为偶数的时候&#xff0c;只有中…

12.4 组播鼠标批量执行

组播模式相比单播模式可以提高网络的效率和带宽利用率&#xff0c;因为组播数据包只需要发送一次&#xff0c;就可以被多个接收者接收&#xff0c;而不需要每个接收者都单独发送一份数据包。这在需要同时向多个接收者发送相同数据的场景下特别有用&#xff0c;如视频会议、在线…

解救Kubernetes混乱:Descheduler快速实现资源平衡

By default, Kubernetes doesn’t recompute and rebalance workloads. You could have a cluster with fewer overutilized nodes and others with a handful of pods How can you fix this? 关注【云原生百宝箱】公众号&#xff0c;快速掌握云原生 默认情况下&#xff0c;Ku…

RabbitMQ相关的其他知识点

RabbitMQ相关的其他知识点 一、幂等性1.1 概念1.2 消息重复消费1.3 消费端的幂等性保障 二、优先队列2.1 应用场景2.2 实现原理2.3 代码实现 三、惰性队列3.1 定义3.2 应用场景3.3 两种设置模式3.4 内存开销对比 一、幂等性 1.1 概念 用户对于同一操作发起的一次请求或者多次请…

冬天虽冷,希望你们能够坚强一点

养了好多植物&#xff0c;以前来阳台的时候看着个个都挺茂盛&#xff0c;也绿油油的&#xff0c;可天气一变冷&#xff0c;你们当中就有些扛不住了&#xff0c;多肉已经挂了&#xff0c;就剩你们啦&#xff01;希望你们能够坚强一点。

1024程序员节 | 电脑软件:SmartSystemMenu(窗口置顶工具)介绍

目录 一、软件介绍 二、软件用途 三、安装教程 四、功能介绍 五、软件设置 六、软件下载 一、软件介绍 SmartSystemMenu 是一款简单实用的 Windows 窗口增强工具&#xff0c;它可以为窗口的标题栏右键菜单新增 17 个新功能。 二、软件用途 SmartSystemMenu(窗口置顶工具)&#…

Spring实例化源码解析之循环依赖CircularReference(十三)

前言 首先什么是循环依赖&#xff0c;简单说就是互相引用。在Spring中是默认支持循环依赖的&#xff0c;至于怎么解决的循环依赖问题&#xff0c;就是本章要探讨的内容。 // 默认允许循环依赖 private boolean allowCircularReferences true;//提供set方法 public void setA…

Jmeter压测工具和Docker服务端接口压测的安装使用详细教程

安装 参考资料 版本 切换语言 使用步骤 1、新建线程组&#xff1b; 右键“测试计划”(左侧导航中的第一条) > 添加 > 线程&#xff08;用户&#xff09; > 线程组&#xff1b; 线程数&#xff1a;并发数&#xff1b; 2、添加取样器 > HTTP请求&#xff1b; 右…

菜尼奥排错之AttributeError: module ‘mmcv‘ has no attribute ‘dump‘

环境版本&#xff1a; 阿里云PAI平台创建的实例&#xff0c;linux x86-64基础配置如下&#xff1a; pytorch 1.12.0 mmengine 0.8.4 mmcv 2.0.1 mmdet 3.1.0 mmdet3d 1.2.0 报错信息&#xff1a; AttributeError: module mmcv has no attribute dump 本人是在mmcv.dum…

第18章 SpringCloud生态(三)

18.21 Nacos能存储什么样格式的数据(配置中心) 难度:★ 重点:★ 白话解析 看下面这副Nacos控制台的截图就明白了 参考答案 六种格式数据:Text、JSON、XML、Yaml、HTML和Properties格式。 18.22 Nacos是如何实现配置动态更新的(配置中心) 难度:★★ 重点:★★★ 白话…

Linux命令之网络命令ifconfig

一、ifconfig命令简介 ifconfig命令是Linux系统下的一个网络配置工具&#xff0c;用于查看和设置网络接口的配置信息。通过ifconfig命令&#xff0c;用户可以查看当前系统中所有网络接口的详细信息&#xff0c;如IP地址、子网掩码、广播地址等。同时&#xff0c;用户还可以使用…

vue判断是pc端还是手机端访问

首先编写一个util.ts工具类&#xff0c;用作判断访问进来的是pc还是手机端 //判断是否是移动端 export function _isMobile(): boolean {return navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|w…

2023年10月24日程序员节

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

源码编译安装Apache

目录 ✨apache安装步骤 &#x1f36d;挂载镜像 &#x1f36d;解压并安装 &#x1f36d;安装主程序 &#x1f36d;优化链接及服务 &#x1f36d;查看httpd模块 &#x1f36d;查看mpm配置文件 &#x1f36d;查看apache主页 &#x1f36d;使用ab命令进行压力测试 &#x1f990;博客…

【idea】win 10 / win 11:idea 、Alibaba Dragonwell 11、maven、git下载与安装

目录 一、安装 jdk&#xff1a;Alibaba Dragonwell 11 &#xff08;1&#xff09;下载&#xff1a;Alibaba Dragonwell 11 &#xff08;2&#xff09;解压&#xff1a;Alibaba Dragonwell 11 &#xff08;3&#xff09;配置系统环境变量&#xff1a;jdk &#xff08;4&a…

二、虚拟机克隆和快照

1.虚拟机克隆 如果你已经安装了一台Linux操作系统&#xff0c;你还想要更多的&#xff0c;这个时候没有必要重新装&#xff0c;只需要克隆就可以 方式1&#xff1a;直接拷贝一份安装好的虚拟机文件 方式2&#xff1a;使用vmware的克隆操作 注意&#xff0c;克隆时&#xff0c;…

“深入理解C++类默认成员函数:探索构造、析构与复制“

文章目录 类的8个默认成员函数构造函数析构函数拷贝构造移动构造赋值运算符重载移动赋值运算符重载取地址及const取地址操作符重载 强制生成默认函数的关键字default禁止生成默认函数的关键字delete 类的8个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。 空…

[黑马程序员SpringBoot2]——基础篇1

目录&#xff1a; SpringBoot入门案例&#xff08;Idea联网版&#xff09;SpringBoot入门案例&#xff08;官网创建版&#xff09;SpringBoot入门案例&#xff08;阿里云版&#xff09;SpringBoot入门案例&#xff08;手工制作版&#xff09;教你一招&#xff0c;隐藏文件或文件…

【大数据】Hadoop

文章目录 概述Hadoop组成HDFSMapReduce写MapReduce程序&#xff08;Hadoop streaming&#xff09; YARNHadoop 启动 工作方式Hadoop的主从工作方式Hadoop的守护进程 运行模式本地运行模式伪分布式运行模式完全分布式运行模式 Hadoop高可用的解决方案ZooKeeper quorumZKFC 环境搭…

k8s集群镜像下载加gradana监控加elk日志收集加devops加秒杀项目

展示 1.配套资料2.devops 3.elk日志收集 4.grafana监控 5.dashboard![在这里插入图片描述](https://img-blog.csdnimg.cn/bf294f9fd98e4c038858a6bf5c34dbdc.png 目的 学习k8s来来回回折腾很久了&#xff0c;光搭个环境就能折腾几天。这次工作需要终于静下心来好好学习了一…