揭秘SpringIOC初始化过程

2024-03-02 10:59

本文主要是介绍揭秘SpringIOC初始化过程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

作者:小毛毛

cnblogs.com/zgwjava/p/10839732.html

1. SpringBoot 整合篇

2. 手写一套迷你版HTTP服务器

3. 记住:永远不要在MySQL中使用UTF-8

4. Springboot启动原理解析

相信大家都知道Spring,我们经常来用他一些特性,比如说他的AOP,IOC,那今天就带大家解析下SpringIOC的加载过程。

我们来看一个例子

    AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(JobService.class);for (String beanname:context.getBeanDefinitionNames()){System.out.println("--------"+beanname);}System.out.println("context.getBean(JobService.class) = " + context.getBean(JobService.class));

这点代码很简单 初始化bean,然后再来拿bean,我们点进AnnotationConfigApplicationContext来看

揭秘SpringIOC初始化过程

进⼊之后 会调用 this()默认无参构造方法

揭秘SpringIOC初始化过程

调⽤这个⽆参构造⽅法的同时 他会调用⽗类的构造方法,在调用父类构造⽅方法时 他new了一个对象

揭秘SpringIOC初始化过程

也就是 DefaultListableBeanFactory,当然 这个就是所谓我们平常所说的 bean工厂,其父类就是 BeanFactory,BeanFactory有很多子类,DefaultListableBeanFactory就是其中一个⼦类。

那么 bean的⽣命周期是围绕那个⽅法呢,就是refresh()⽅法。也就是bean的整个生命周期是围绕refresh() 来进行的

在refresh()我们可以看到

public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// 准备好刷新上下文.prepareRefresh();// 返回一个Factory 为什么需要返回一个工厂  因为要对工厂进行初始化ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// 准备bean工厂,以便在此上下文中使用。prepareBeanFactory(beanFactory);try {// 允许在上下文子类中对bean工厂进行后处理。 在spring5  并未对此接口进行实现postProcessBeanFactory(beanFactory);// 在spring的环境中去执行已经被注册的 Factory processors//设置执行自定义的postProcessBeanFactory和spring内部自己定义的invokeBeanFactoryPostProcessors(beanFactory);// 注册postProcessorregisterBeanPostProcessors(beanFactory);// 初始化此上下文的消息源。initMessageSource();// 初始化此上下文的事件多播程序。initApplicationEventMulticaster();// 在特定上下文子类中初始化其他特殊bean。onRefresh();//检查侦听器bean并注册它们。registerListeners();// 实例化所有剩余的(非懒加载)单例。//new 单例对象finishBeanFactoryInitialization(beanFactory);// 最后一步:发布相应的事件finishRefresh();}catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);}// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset 'active' flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;}finally {// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore...resetCommonCaches();}}
}

那么这里面最重要就是finishBeanFactoryInitialization(beanFactory);这个方法就是描述 spring的一个bean如何初始化

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {// Initialize conversion service for this context.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 bean post-processor// (such as a PropertyPlaceholderConfigurer 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();// 实例化所有单例对象beanFactory.preInstantiateSingletons();
}

可以看到前面是一些判断 最重要的就是最后一个方法 beanFactory.preInstantiateSingletons();我们看下preInstantiateSingletons()方法,它是ConfigurableListableBeanFactory这个接口的一个方法 我们直接来看这个接口的实现 是由DefaultListableBeanFactory这个类 来实现

@Override
public void preInstantiateSingletons() throws BeansException {if (logger.isDebugEnabled()) {logger.debug("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.//所有bean的名字List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);// Trigger initialization of all non-lazy singleton beans...for (String beanName : beanNames) {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) {final 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);}}}

我们可以看到用

List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

来保存bean的名字,那this.beanDefinitionNames是一个什么东西

/** List of bean definition names, in registration order */
private volatile List<String> beanDefinitionNames = new ArrayList<>(256);

可以看到是beanDefinition的一个名字,那beanDefinition是个什么呢?它是spring当中非常重要的一个概念,在这里简单的提一嘴 我们传统用纯java的方式怎么new对象 是 Student stu=new Student();的方式来实例化对象,但是要交给spring的话,

先通过springScan的方式扫描到类,当他扫描到的时候 他会去new一个beanDefinition对象 他有很多子类 比如说 GenericBeanDefinition generic=new GenericBeanDefinition();然后他会把扫描到的类的各种信息给拿出来,比如说Student的名字是什么:

揭秘SpringIOC初始化过程

等等很多很多,然后把这个对象放到哪里呢? 在DefaultListableBeanFactory中有一个Map,叫做

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

就放到这个Map当中 也就是

beanDefinitionMap.put("studentService",generic)这样放进去之后,spring会看你有没有调用拓展接口,拓展接口我们到后面再说 如果没有拓展接口,就会继续调用我们刚刚接着继续的 preInstantiateSingletons()方法,这个方法来完成bean的实例化 总的一句话 BeanDefinition就是用来描述bean的,当然BeanDefinition的知识不仅仅是这些,今天只是简单提一嘴

那么我们现在继续 beanDefinitionNames也就是刚刚那个Map中Key的集合,然后开始循环

//触发所有非延迟加载单例beans的初始化,只要步骤调用getBean
//根据List名字从Map当中把BeanDefinition依次拿出来开始new对象
for (String beanName : beanNames) {//合并父BeanDefinition//通过Map的名字拿BeanDefinitionRootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);//判断当前类是否抽象 是否为单例  是否为懒加载  如果条件都成立 则继续if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {//判断该类是否为FactoryBean FactoryBean这里不进行讲解 不懂得朋友可以去了解下//如果不是FactoryBeanif (isFactoryBean(beanName)) {Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);if (bean instanceof FactoryBean) {final 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 {//则直接调用getBeangetBean(beanName);}}
}

 

揭秘SpringIOC初始化过程

 

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {/***通过name获取beanName。这里不使用name直接做beanName* name可能会以&字符开头,表用调用者想获取FactoryBean本身,而非FactoryBean*实现类所创建的bean。在BeanFactory中,FactoryBean的实现类和其他的bean存储方式是一致的即* <beanName, bean> ,beanName中没有&字符的。所以我们需要将name的首字母&移除,这样才能取到*FactoryBean实例*/final String beanName = transformedBeanName(name);Object bean;// Eagerly check singleton cache for manually registered singletons.Object sharedInstance = getSingleton(beanName);if (sharedInstance != null && args == null) {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 + "'");}}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) {markBeanAsCreated(beanName);}try {final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);checkMergedBeanDefinition(mbd, beanName, args);// 一个注解叫@DependsOn:A类创建 必须B类创建出来再创建A类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);}}}// 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;
}

Object sharedInstance = getSingleton(beanName);重点为这行代码,我们点进去getSingleton(beanName)这个方法来看

揭秘SpringIOC初始化过程

正在要new一个对象的时候 他会调用getSingleton方法,那么在这个方法中

Object singletonObject = this.singletonObjects.get(beanName);

这行代码是本质,那他是什么东西 我们点进来看

/** Cache of singleton objects: bean name --> bean instance */
//用于存放完全初始化好的bean从该缓存中取出bean可以直接使用
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

很明显 他就是个Map ConcurrentHashMap线程安全的Map,什么意思 这个Map也就是我们常常说说的Spring的容器 如果从微观角度来讲 没错spring容器就是这个Map,如果从宏观上讲,他就不能称之为map 我希望大家能理解什么意思,因为spring环境包含很多组件,各种组件包含在一起以及singletonObjects以及一些后置处理器配合完成一些工作我们称之为Spring容器。

singletonObjects 是什么?没错他就是单例池 他什么要在单例池拿?为什么要调用他?

因为他要解决Spring当中的循环依赖问题,相信大家既然有看源码的能力,相信大家也明白什么是循环依赖这里不再细说

在这个类里也有介绍

/** Cache of early singleton objects: bean name --> bean instance */
//存放原始的bean对象用于解决循环依赖,注意:存到里面的对象还没被填充到属性
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

什么意思 一个bean放到singletonObjects之后,把一个对象new出来之后,如果这个对象要循环引用那spring就会先把他放到earlySingletonObjects这个当中.get是因为怕对象已经放到early当中所以先去get一遍,这里也只是简单题一嘴

那我们继续看

if (sharedInstance != null && args == null) {//如果条件成立的话bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);//直接返回调//如果条件不成立直接elseif (isPrototypeCurrentlyInCreation(beanName)) //判断这个类是否正在创建,什么意思 因为spring正在创建一类的时候他会进行标识这个类我正在创建中,然后获取bean工厂BeanFactory parentBeanFactory = getParentBeanFactory();//这里不重要

我们继续来看

sharedInstance = getSingleton(beanName, () -> { try { return createBean(beanName, mbd, args); } 到这一步的时候,才开始真正创建对象,这里又一个getSingleton这个方法跟上面那个不是同一个方法,这个地方用到lambdas表达式,我们点进去看这个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 + "'");}beforeSingletonCreation(beanName);boolean newSingleton = false;boolean recordSuppressedExceptions = (this.suppressedExceptions == null);if (recordSuppressedExceptions) {this.suppressedExceptions = new LinkedHashSet<>();}try {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;}
}

Object singletonObject = this.singletonObjects.get(beanName);

这里关键:

第一个getSingleton:单例池拿,拿不到到缓存池拿,拿不到返回null 第二个:也是先从单例池拿 如果为null, if (this.singletonsCurrentlyInDestruction)判断对象有没有开始创建,

然后 beforeSingletonCreation(beanName);我们点进去来看

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

singletonsCurrentlyInCreation是什么意思

/** Names of beans that are currently in creation */
private final Set<String> singletonsCurrentlyInCreation =Collections.newSetFromMap(new ConcurrentHashMap<>(16));

也是一个Lsit,什么意思 把它放到这个List当中表示正在创建

紧接着调用createBean(beanName, mbd, args);开始创建对象

我们来看createBean

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {if (logger.isDebugEnabled()) {logger.debug("Creating instance of bean '" + beanName + "'");}RootBeanDefinition mbdToUse = mbd;// Make sure bean class is actually resolved at this point, and// clone the bean definition in case of a dynamically resolved Class// which cannot be stored in the shared merged bean definition.Class<?> resolvedClass = resolveBeanClass(mbd, beanName);if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {mbdToUse = new RootBeanDefinition(mbd);mbdToUse.setBeanClass(resolvedClass);}// Prepare method overrides.try {mbdToUse.prepareMethodOverrides();}catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),beanName, "Validation of method overrides failed", ex);}try {// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.Object bean = resolveBeforeInstantiation(beanName, mbdToUse);if (bean != null) {return bean;}}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,"BeanPostProcessor before instantiation of bean failed", ex);}try {Object beanInstance = doCreateBean(beanName, mbdToUse, args);if (logger.isDebugEnabled()) {logger.debug("Finished creating instance of bean '" + beanName + "'");}return beanInstance;}catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {// A previously detected exception with proper bean creation context already,// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.throw ex;}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);}
}

到这里 不要以为完了,其实还没完最重要的部分

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);

这个是第一次调用spring的后置处理器,spring的生命周期一共围绕了9个后置处理器,这个是第一个

我们先不管这些后置处理器是干嘛的 先把他找出来我们点进resolveBeforeInstantiation

@Nullable
protected Object  resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {Object bean = null;if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {// Make sure bean class is actually resolved at this point.if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {Class<?> targetType = determineTargetType(beanName, mbd);if (targetType != null) {bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);if (bean != null) {bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);}}}mbd.beforeInstantiationResolved = (bean != null);}return bean;
}

bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);点进来看

@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);if (result != null) {return result;}}}return null;
}

他会先拿出来所有后置处理器 然后判断是不是属于他

我们返回刚刚

Object beanInstance = doCreateBean(beanName, mbdToUse, args);

在doCreateBean里面调用第二个后置处理器,我这里都不再一一寻找了,直接列出来吧

第一次:InstantiationAwareBeanPostProcessor --postProcessBeforeInstantiation
第二次:SmartInstantiationAwareBeanPostProcessor—determineCandidateConstructors—由后置处理器决定返回那些构造方法
第三次:MergedBeanDefinitionPostProcessor——postProcessMergedBeanDefinition------缓存的
第四次:SmartInstantiationAwareBeanPostProcessor—getEarlyBeanReference----把对象放到Early当中--处理循环引用
第五次:InstantiationAwareBeanPostProcessor—postProcessAfterInstantiation---判断要不要填充属性
第六次:InstantiationAwareBeanPostProcessor—postProcessPropertyValues—处理属性的值
第七次:BeanPostProcessor—postProcessBeforeInitialization —处理AOP
第八次:BeanPostProcessor----postProcessAfterInitialization
第九次为销毁

那么到这里一个完整的springBean的初始化。

揭秘SpringIOC初始化过程

这篇关于揭秘SpringIOC初始化过程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/765893

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

作业提交过程之HDFSMapReduce

作业提交全过程详解 (1)作业提交 第1步:Client调用job.waitForCompletion方法,向整个集群提交MapReduce作业。 第2步:Client向RM申请一个作业id。 第3步:RM给Client返回该job资源的提交路径和作业id。 第4步:Client提交jar包、切片信息和配置文件到指定的资源提交路径。 第5步:Client提交完资源后,向RM申请运行MrAp

揭秘世界上那些同时横跨两大洲的国家

我们在《世界人口过亿的一级行政区分布》盘点全球是那些人口过亿的一级行政区。 现在我们介绍五个横跨两州的国家,并整理七大洲和这些国家的KML矢量数据分析分享给大家,如果你需要这些数据,请在文末查看领取方式。 世界上横跨两大洲的国家 地球被分为七个大洲分别是亚洲、欧洲、北美洲、南美洲、非洲、大洋洲和南极洲。 七大洲示意图 其中,南极洲是无人居住的大陆,而其他六个大洲则孕育了众多国家和

三国地理揭秘:为何北伐之路如此艰难,为何诸葛亮无法攻克陇右小城?

俗话说:天时不如地利,不是随便说说,诸葛亮六出祁山,连关中陇右的几座小城都攻不下来,行军山高路险,无法携带和建造攻城器械,是最难的,所以在汉中,无论从哪一方进攻,防守方都是一夫当关,万夫莫开;再加上千里运粮,根本不需要打,司马懿只需要坚守城池拼消耗就能不战而屈人之兵。 另一边,洛阳的虎牢关,一旦突破,洛阳就无险可守,这样的进军路线,才是顺势而为的用兵之道。 读历史的时候我们常常看到某一方势

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

无线领夹麦克风什么牌子好用?揭秘领夹麦克风哪个牌子音质好!

随着短视频行业的星期,围绕着直播和视频拍摄的电子数码类产品也迎来了热销不减的高增长,其中除了数码相机外,最为重要的麦克风也得到了日益增长的高需求,尤其是无线领夹麦克风,近几年可谓是异常火爆。别看小小的一对无线麦克风,它对于视频拍摄的音质起到了极为关键的作用。 不过目前市面上的麦克风品牌种类多到让人眼花缭乱,盲目挑选的话容易踩雷,那么无线领夹麦克风什么牌子好用?今天就给大家推荐几款音质好的

负债不再是障碍?银行信贷“白名单“揭秘

谈及银行信贷产品,常闻有言称存在无需考量负债与查询记录之奇品,此等说法十有八九为中介诱人上钩之辞。轻信之下,恐将步入连环陷阱。除非个人资质出类拔萃,如就职于国央企或事业单位,工龄逾年,五险一金完备,还款能力卓越,或能偶遇线下产品对查询记录稍显宽容,然亦非全然无视。宣称全然不顾者,纯属无稽之谈。 银行非慈善机构,不轻易于困境中援手,更偏爱锦上添花之举。若无坚实资质,即便求助于银行亦难获青睐。反

c++的初始化列表与const成员

初始化列表与const成员 const成员 使用const修饰的类、结构、联合的成员变量,在类对象创建完成前一定要初始化。 不能在构造函数中初始化const成员,因为执行构造函数时,类对象已经创建完成,只有类对象创建完成才能调用成员函数,构造函数虽然特殊但也是成员函数。 在定义const成员时进行初始化,该语法只有在C11语法标准下才支持。 初始化列表 在构造函数小括号后面,主要用于给