Spring源码分析(三) IOC 之 getBean()和doGetBean()

2023-09-14 14:39:24

b、在中篇会正式经历一套生命周期流程

getBean() -> doGetBean() -> createBean() -> doCreateBean() -> createBeanInstance() -> populateBean() -> initializeBean() 流程

在这里插入图片描述

1、AbstractBeanFactory#getBean()

此处开始进行对象的获取也就是核心步骤

@Override
	public Object getBean(String name) throws BeansException {
		// 此方法是实际获取bean的方法,也是触发依赖注入的方法
		return doGetBean(name, null, null, false);
	}

2、AbstractBeanFactory#doGetBean()

doGetBean方法中得执行流程,如下图所示;

在这里插入图片描述

protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {

		/**
		 * 提取对应的beanName,有人可能会认为此处直接使用即可,为什么还要进行转换呢,原因在于当bean对象实现FactoryBean接口之后就会变成&beanName,同时如果存在别名,也需要把别名进行转换*/
		String beanName = transformedBeanName(name);
		Object bean;

		// Eagerly check singleton cache for manually registered singletons.
		/**提前检查单例缓存中是否有手动注册的单例对象,跟循环依赖有关联*/
		Object sharedInstance = getSingleton(beanName);
		// 如果bean的单例对象找到了,且没有创建bean实例时要使用的参数
		if (sharedInstance != null && args == null) {
			if (logger.isTraceEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			// 返回对象的实例,这句话的重点在于当你实现了FactoryBean接口的对象,需要获取具体的对象的时候就需要此方法来进行获取了
			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.
			// 如果bean定义不存在,就检查父工厂是否有
			BeanFactory parentBeanFactory = getParentBeanFactory();
			// 如果beanDefinitionMap中也就是在所有已经加载的类中不包含beanName,那么就尝试从父容器中获取
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				// Not found -> check parent.
				// 获取name对应的规范名称【全类名】,如果name前面有'&',则会返回'&'+规范名称【全类名】
				String nameToLookup = originalBeanName(name);
				// 如果父工厂是AbstractBeanFactory的实例
				if (parentBeanFactory instanceof AbstractBeanFactory) {
					// 调用父工厂的doGetBean方法,就是该方法。【递归】
					return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
							nameToLookup, requiredType, args, typeCheckOnly);
				}
				else if (args != null) {
					// Delegation to parent with explicit args.
					// 如果有创建bean实例时要使用的参数
					// Delegation to parent with explicit args. 使用显示参数委派给父工厂
					// 使用父工厂获取该bean对象,通bean全类名和创建bean实例时要使用的参数
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else if (requiredType != null) {
					// No args -> delegate to standard getBean method.
					// 没有创建bean实例时要使用的参数 -> 委托给标准的getBean方法。
					// 使用父工厂获取该bean对象,通bean全类名和所需的bean类型
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
				else {
					// 使用父工厂获取bean,通过bean全类名
					return (T) parentBeanFactory.getBean(nameToLookup);
				}
			}
			// 如果不是做类型检查,那么表示要创建bean,此处在集合中做一个记录
			if (!typeCheckOnly) {
				// 为beanName标记为已经创建(或将要创建)
				markBeanAsCreated(beanName);
			}

			try {
				// 此处做了BeanDefinition对象的转换,当我们从xml文件中加载beandefinition对象的时候,封装的对象是GenericBeanDefinition,
				// 此处要做类型转换,如果是子类bean的话,会合并父类的相关属性
				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				// 检查mbd的合法性,不合格会引发验证异常
				checkMergedBeanDefinition(mbd, beanName, args);

				// Guarantee initialization of beans that the current bean depends on.
				// 如果存在依赖的bean的话,那么则优先实例化依赖的bean
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					// 如果存在依赖,则需要递归实例化依赖的bean
					for (String dep : dependsOn) {
						// 如果beanName已注册依赖于dependentBeanName的关系
						if (isDependent(beanName, dep)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
						// 注册各个bean的依赖关系,方便进行销毁
						registerDependentBean(dep, beanName);
						try {
							// 递归优先实例化被依赖的Bean
							getBean(dep);
						}
						// 捕捉为找到BeanDefinition异常:'beanName'依赖于缺少的bean'dep'
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}

				// Create bean instance.
				// 创建bean的实例对象
				if (mbd.isSingleton()) {
					// 返回以beanName的(原始)单例对象,如果尚未注册,则使用singletonFactory创建并注册一个对象:
					sharedInstance = getSingleton(beanName, () -> {
						try {
							// 为给定的合并后BeanDefinition(和参数)创建一个bean实例
							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.
							// 显示地从单例缓存中删除实例:它可能是由创建过程急切地放在那里,以允许循环引用解析。还要删除
							// 接收到该Bean临时引用的任何Bean
							// 销毁给定的bean。如果找到相应的一次性Bean实例,则委托给destoryBean
							destroySingleton(beanName);
							// 重新抛出ex
							throw ex;
						}
					});
					// 从beanInstance中获取公开的Bean对象,主要处理beanInstance是FactoryBean对象的情况,如果不是
					// FactoryBean会直接返回beanInstance实例
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
				// 原型模式的bean对象创建
				else if (mbd.isPrototype()) {
					// It's a prototype -> create a new instance.
					// 它是一个原型 -> 创建一个新实例
					// 定义prototype实例
					Object prototypeInstance = null;
					try {
						// 创建Prototype对象前的准备工作,默认实现将beanName添加到prototypesCurrentlyInCreation中
						beforePrototypeCreation(beanName);
						// 为mbd(和参数)创建一个bean实例
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						// 创建完prototype实例后的回调,默认是将beanName从prototypesCurrentlyInCreation移除
						afterPrototypeCreation(beanName);
					}
					// 从beanInstance中获取公开的Bean对象,主要处理beanInstance是FactoryBean对象的情况,如果不是
					// FactoryBean会直接返回beanInstance实例
					bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}

				else {
					// 指定的scope上实例化bean
					String scopeName = mbd.getScope();
					if (!StringUtils.hasLength(scopeName)) {
						throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
					}
					// 从scopes中获取scopeName对于的Scope对象
					Scope scope = this.scopes.get(scopeName);
					// 如果scope为null
					if (scope == null) {
						// 抛出非法状态异常:没有名为'scopeName'的scope注册
						throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
					}
					try {
						// 从scope中获取beanName对应的实例对象
						Object scopedInstance = scope.get(beanName, () -> {
							// 创建Prototype对象前的准备工作,默认实现 将beanName添加到prototypesCurrentlyInCreation中
							beforePrototypeCreation(beanName);
							try {
								// 为mbd(和参数)创建一个bean实例
								return createBean(beanName, mbd, args);
							}
							finally {
								// 创建完prototype实例后的回调,默认是将beanName从prototypesCurrentlyInCreation移除
								afterPrototypeCreation(beanName);
							}
						});
						// 从beanInstance中获取公开的Bean对象,主要处理beanInstance是FactoryBean对象的情况,如果不是
						// FactoryBean会直接返回beanInstance实例
						bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
					catch (IllegalStateException ex) {
						// 捕捉非法状态异常
						// 抛出Bean创建异常:作用域 'scopeName' 对于当前线程是不活动的;如果您打算从单个实例引用它,请考虑为此
						// beanDefinition一个作用域代理
						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) {
				// 捕捉获取Bean对象抛出的Bean异常
				// 在Bean创建失败后,对缓存的元数据执行适当的清理
				cleanupAfterBeanCreationFailure(beanName);
				// 重新抛出ex
				throw ex;
			}
		}

		// Check if required type matches the type of the actual bean instance.
		// 检查requiredType是否与实际Bean实例的类型匹配
		// 如果requiredType不为null&&bean不是requiredType的实例
		if (requiredType != null && !requiredType.isInstance(bean)) {
			try {
				// 获取此BeanFactory使用的类型转换器,将bean转换为requiredType
				T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
				// 如果convertedBean为null
				if (convertedBean == null) {
					// 抛出Bean不是必要类型的异常
					throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
				}
				// 返回convertedBean
				return convertedBean;
			}
			catch (TypeMismatchException ex) {
				if (logger.isTraceEnabled()) {
					logger.trace("Failed to convert bean '" + name + "' to required type '" +
							ClassUtils.getQualifiedName(requiredType) + "'", ex);
				}
				throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
			}
		}
		// 将bean返回出去
		return (T) bean;
	}

2.1 transformedBeanName()

这一步没什么太多的内容就是,提取对应的beanName,有人可能会认为此处直接使用即可,为什么还要进行转换呢,原因在于当bean对象实现FactoryBean接口之后就会变成&beanName,同时如果存在别名,也需要把别名进行转换。

2.2 getSingleton() ***特殊地方

doGetBean方法开始会调用getsingleton()方法尝试获取bean实例,如果该bean实例为空,则继续执行下面的代码。如果bean实例不为空则调用getObjectForBeanInstance()方法获取Bean 实例。
这里的不为空是当使用applicationcontext的实现类或者是beanfactory来加载bean.xml文件(或者是application.xml文件,总之是用xml的形式将某个类加入到spring应用上下文中),有可能会采用非延迟加载的形式。而非延迟加载就意味着某个bean在applicationcontext的实现类调用getbean方法之前(applicationcontext的实现类加载bean.xml文件之后),bean就已经实例化了。

而这里的getobjectfromfactorybean存在的意义在于,从缓存中得到了bean是原始状态,并不一定是我们最终想要的bean。需要对bean进行实例化。我们需要对工厂bean进行处理,我们真正需要的是工程bean中定义的factory-method方法中返回的bean,而getObjectForBeanInstance就是完成这个工作的。getObjectForBeanInstance最终调用Factorybean中的getobject()方法。其实如果我们对xml中的bean进行实例化,可以在xml的factory-method中声明一个自定义类,然后该类需要实现factorybean中的getobject方法,所以说factorybean就是负责将spring应用上下文中的bean进行实例化的。

/**
* 返回以给定名称注册的(原始)单例对象,如果尚未注册,则创建并注册一个对象
*/
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
		// 如果beanName为null,抛出异常
		Assert.notNull(beanName, "Bean name must not be null");
		// 使用单例对象的高速缓存Map作为锁,保证线程同步
		synchronized (this.singletonObjects) {
			// 从单例对象的高速缓存Map中获取beanName对应的单例对象
			Object singletonObject = this.singletonObjects.get(beanName);
			// 如果单例对象获取不到
			if (singletonObject == null) {
				// 如果当前在destorySingletons中
				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);
				// 表示生成了新的单例对象的标记,默认为false,表示没有生成新的单例对象
				boolean newSingleton = false;
				// 有抑制异常记录标记,没有时为true,否则为false
				boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
				// 如果没有抑制异常记录
				if (recordSuppressedExceptions) {
					// 对抑制的异常列表进行实例化(LinkedHashSet)
					this.suppressedExceptions = new LinkedHashSet<>();
				}
				try {
					// 从单例工厂中获取对象
					singletonObject = singletonFactory.getObject();
					// 生成了新的单例对象的标记为true,表示生成了新的单例对象
					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.
					// 同时,单例对象是否隐式出现 -> 如果是,请继续操作,因为异常表明该状态
					// 尝试从单例对象的高速缓存Map中获取beanName的单例对象
					singletonObject = this.singletonObjects.get(beanName);
					// 如果获取失败,抛出异常
					if (singletonObject == null) {
						throw ex;
					}
				}
				// 捕捉Bean创建异常
				catch (BeanCreationException ex) {
					// 如果没有抑制异常记录
					if (recordSuppressedExceptions) {
						// 遍历抑制的异常列表
						for (Exception suppressedException : this.suppressedExceptions) {
							// 将抑制的异常对象添加到 bean创建异常 中,这样做的,就是相当于 '因XXX异常导致了Bean创建异常‘ 的说法
							ex.addRelatedCause(suppressedException);
						}
					}
					// 抛出异常
					throw ex;
				}
				finally {
					// 如果没有抑制异常记录
					if (recordSuppressedExceptions) {
						// 将抑制的异常列表置为null,因为suppressedExceptions是对应单个bean的异常记录,置为null
						// 可防止异常信息的混乱
						this.suppressedExceptions = null;
					}
					// 创建单例后的回调,默认实现将单例标记为不在创建中
					afterSingletonCreation(beanName);
				}
				// 生成了新的单例对象
				if (newSingleton) {
					// 将beanName和singletonObject的映射关系添加到该工厂的单例缓存中:
					addSingleton(beanName, singletonObject);
				}
			}
			// 返回该单例对象
			return singletonObject;
		}
	}

2.2.1 getObjectForBeanInstance()

1、 Spring首先会判断当前beanName是否是FactoryBean<?>类型的BeanName,FactoryBean<?>类型的BeanName是&拼接上原始Bean的BeanName。即一个BeanName为test的Bean实现了FactoryBean<?>接口,那么使用test就会从容器中获取到这个Bean,如果需要获取FactoryBean则需要使用&test从容器中获取。所以Spring在对于Bean的检查中第一步做的就是判断当前获取Bean的BeanName是否为FactoryBean<?>的类型的BeanName。如果获取的是FactoryBean<?>类型的BeanName则进行相关校验。如果确实是FactoryBean<?>类型并且BeanDefinition不为空,则修改该Bean的BeanDefinition中的isFactoryBean属性为true代表该Bean是一个FactoryBean<?>类型的Bean,最后直接返回当前Bean实例。节省性能开销,解析过一次后避免后面重复解析的性能开销。

2、 如果当前beanName不是FactoryBean<?>类型的BeanName,则判断当前Bean实例是否是FactoryBean<?>类型,如果不是FactoryBean<?>类型则直接返回,说明该Bean只是一个常规Bean,则不需要后续处理直接返回。 3、如果当前Bean是FactoryBean<?>类型,则说明当前获取的Bean是实现FactoryBean<?>接口的原始Bean。则需要激活FactoryBean<?>中定义的三个方法对当前Bean进行实例化处理。

protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

		// Don't let calling code try to dereference the factory if the bean isn't a factory.
		// 如果 BeanName 是 FactoryBean<?> 相关的 BeanName
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			// BeanInstance 是 NullBean
			if (beanInstance instanceof NullBean) {
				// 直接返回 beanInstance
				return beanInstance;
			}
			// 如果不是 FactoryBean<?> 类型的 Bean 实例
			if (!(beanInstance instanceof FactoryBean)) {
				// 抛出异常 : 当前 Bean 不是一个工厂
				throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
			}
			// 如果 BeanName 与 FactoryBean<?> 相关 && beanInstance 不是 NullBean
			// && beanInstance 是 FactoryBean<?> 类型 && RootBeanDefinition 不为空
			if (mbd != null) {
				// 当前 Bean 实例为 FactoryBean<?> 类型的 Bean
				mbd.isFactoryBean = true;
			}
			// 直接返回当前 Bean 实例, 这也是为什么针对于一个 FactoryBean<?> 类型的 Bean 实例而言
			// 使用 '&' + beanName 就能获取到 FactoryBean<?> 本身
			return beanInstance;
		}

		// Now we have the bean instance, which may be a normal bean or a FactoryBean.
		// If it's a FactoryBean, we use it to create a bean instance, unless the
		// caller actually wants a reference to the factory.
		// 现在拥有了一个新的 BeanInstance, 这个实例可能是常规 Bean 也有可能是 FactoryBean<?>
		// 如果是 FactoryBean<?> 则使用它创建实例, 但如果是开发者想要直接获取工厂实例而不是工厂的 getObject()
		// 方法对应的实例, 那么传入的 BeanName 应该加入前缀 '&'
		if (!(beanInstance instanceof FactoryBean)) {
			// 如果不是 FactoryBean 直接返回当前 Bean 实例
			return beanInstance;
		}

		// 如果是 FactoryBean
		Object object = null;
		if (mbd != null) {
			mbd.isFactoryBean = true;
		}
		else {
			// 从缓存中加载
			object = getCachedObjectForFactoryBean(beanName);
		}

		// 激活 FactoryBean<?> 的 getObject() 方法
		if (object == null) {
			// Return bean instance from factory.
			// 这里已经明确知道 beanInstance 一定是 FactoryBean<?> 类型
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;

			// Caches object obtained from FactoryBean if it is a singleton.
			// 如果 mbd 为空 && 从 XML 配置文件中加载的 BeanDefinition 中包含 BeanName 对应的 Bean 定义信息
			if (mbd == null && containsBeanDefinition(beanName)) {
				// 将解析 XML 配置文件的 GenericBeanDefinition 转换为 RootBeanDefinition, 如果指定的 BeanName
				// 是子 Bean 的话同时会合并父类的相关属性
				mbd = getMergedLocalBeanDefinition(beanName);
			}

			boolean synthetic = (mbd != null && mbd.isSynthetic());
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}

1、 getObjectFromFactoryBean()
  1. 如果该FactoryBean<?>实例是单例类型,那么就必须要保证Spring中单实例Bean的唯一以及使用缓存做到避免额外开销。并且Spring在获取Bean的规则中强调到,尽可能保证所有Bean初始化之后都会激活容器中注册的BeanPostProcessor中的postProcessorAfterBeanInitialization()方法。而真正获取Bean实例则是委托给了doGetObjectFromFactoryBean()方法。
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
		// 如果是单例 Bean && Bean 实例已经创建过, 没有再次创建的必要, 要保证单例 Bean 全局唯一, 直接从缓存中获取
		if (factory.isSingleton() && containsSingleton(beanName)) {
			// 进入同步代码块
			synchronized (getSingletonMutex()) {
				// 从缓存中获取
				Object object = this.factoryBeanObjectCache.get(beanName);
				// 如果缓存中没有
				if (object == null) {
					// 激活 FactoryBean<?> 中的 getObject() 方法获取开发者
					// 定制的初始化逻辑
					object = doGetObjectFromFactoryBean(factory, beanName);
					// Only post-process and store if not put there already during getObject() call above
					// (e.g. because of circular reference processing triggered by custom getBean calls)
					Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
					if (alreadyThere != null) {
						object = alreadyThere;
					}
					else {
						if (shouldPostProcess) {
							if (isSingletonCurrentlyInCreation(beanName)) {
								// Temporarily return non-post-processed object, not storing it yet..
								return object;
							}
							beforeSingletonCreation(beanName);
							try {
								object = postProcessObjectFromFactoryBean(object, beanName);
							}
							catch (Throwable ex) {
								throw new BeanCreationException(beanName,
										"Post-processing of FactoryBean's singleton object failed", ex);
							}
							finally {
								afterSingletonCreation(beanName);
							}
						}
						if (containsSingleton(beanName)) {
							this.factoryBeanObjectCache.put(beanName, object);
						}
					}
				}
				return object;
			}
		}
		else {
			// 直接获取
			Object object = doGetObjectFromFactoryBean(factory, beanName);
			if (shouldPostProcess) {
				try {
					object = postProcessObjectFromFactoryBean(object, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
				}
			}
			return object;
		}
	}

2、 doGetObjectFromFactoryBean()
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
		Object object;
		try {
			if (System.getSecurityManager() != null) {
				AccessControlContext acc = getAccessControlContext();
				try {
					object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
				// 激活 FactoryBean<?> 中的 getObject() 方法调用
				// 开发者定制化的的 Bean 注册逻辑
				object = factory.getObject();
			}
		}
		catch (FactoryBeanNotInitializedException ex) {
			throw new BeanCurrentlyInCreationException(beanName, ex.toString());
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
		}

		// Do not accept a null value for a FactoryBean that's not fully
		// initialized yet: Many FactoryBeans just return null then.
		if (object == null) {
			if (isSingletonCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(
						beanName, "FactoryBean which is currently in creation returned null from getObject");
			}
			object = new NullBean();
		}
		return object;
	}

2.3 getParentBeanFactory()

这一个方法主要是先从父容器里面查询,这个在SpringMVC中会讲到,单看spring可以不用看其实

2.4 其他方法

doGetBean中的其他方法可以看整体概览里面的注释,最后核心还是会进入到createBean()

3、开始进行bean的创建->createBean()

更多推荐

Git:Git的一些基本操作

文章目录基本认识使用方法创建本地仓库配置本地仓库工作区、暂存区、版本库的概念添加文件版本回退撤销修改删除操作基本认识首先要对Git有一个基本的认知:Git本质上是一个版本控制器,可以对一个信息的多个版本进行一些控制,而能对版本的控制的好处就是,不管需要哪个版本的内容,都可以借助Git这个工具找到所需要的信息Git是一个

API接口在电商商品数据获取中的应用

一、引言在当前的数字化时代,电子商务平台已经成为了人们购物的主要场所之一。许多电商平台都提供了API接口,以便开发者可以获取商品数据并进行创新应用。本文将深入探讨如何使用API接口获取商品数据,以及如何将这些数据应用到电商领域中。二、API接口概述1.API接口定义API(ApplicationProgrammingI

Java-List<Map>的复制 深拷贝与浅拷贝

博客背景是Java开发。讲一讲List<Map>的复制中深拷贝与浅拷贝。文章目录1、浅拷贝1.1循环遍历复制1.2使用list实现类的构造方法1.3addAll方法2、深拷贝深拷贝工具类SerializationUtils.clone1、浅拷贝Map除了基本类型是值传递,其余的都是引用地址传递。由于map的value存

MySql(随记)

一条MySql执行过程首先Mysql的架构分为两层,Server层和存储引擎层。Server层:MySql大多数核心功能,主要包括,连接器,查询缓存,解释器,预处理器,优化器,执行器等存储引擎层:负责数据的获取和存储。(innodb,MyISAM)连接器1.首先经过TCP三次握手,随后进行权限验证,若有问题则返回“Ac

UI美工设计岗位的基本职责概述(合集)

UI美工设计岗位的基本职责概述11、有良好的美术功底、设计新颖,整体配色及设计创意理念,能够独立完成整个网站页面设计及制作;2、熟练运用DIV+CSS,HTML设计制作网页;3、熟练运用Photoshop,Dreamweaver,Coreldraw(或Illustrator),Flash,Fireworks等软件。4、

两个有序链表序列的交集

已知两个非降序链表序列S1与S2,设计函数构造出S1与S2的交集新链表S3。输入格式:输入分两行,分别在每行给出由若干个正整数构成的非降序序列,用−1表示序列的结尾(−1不属于这个序列)。数字用空格间隔。输出格式:在一行中输出两个输入序列的交集序列,数字间用空格分开,结尾不能有多余空格;若新链表为空,输出NULL。输入

红黑树插入的实现

红黑树:1.概念:红黑树的性质:红黑树的插入操作:其前面的插入和二叉搜索树的一模一样,只是后面需要判断是否满足红黑树的性质:具体分为三种情况:1.uncle节点存在且为红色的:对应如图:这种情况只需要将parent和uncle节点都弄成黑色,对应的grandparent节点弄成黑色接下来又会分为三种情况:1.如果对应的

创新未来,工信部组建【AI应用工作组】助力人工智能进步

随着人工智能大模型技术的快速发展和成熟,AI应用已经从早期的概念阶段进入了千行百业的实践落地阶段,三百六十行、行行需AI。如今,AI已经成为推动各行各业创新和发展的重要引擎,对经济、社会和文化的发展产生了深远的影响。为了进一步推动人工智能应用的落地和创新,工业和信息化部工业文化发展中心于9月12日上午在北京王府井希尔顿

Go net http包

文章目录1Request2Response3client4HTTPServer服务端5自定义处理器(CustomHandlers)6将函数作为处理器7中间件Middleware8静态站点在Go中,搭建一个HTTPserver简单到令人难以置信。只需要引入net/http包,写几行代码,一个HTTP服务器就可以正常运行并

Java进化史:从Java 8到Java 17的语言特性全解析

文章目录Java8:引入Lambda表达式和StreamAPILambda表达式StreamAPIJava9:模块化系统模块Jigsaw项目Java10:局部变量类型推断Java11:引入HTTP客户端HTTP客户端Java12:引入Switch表达式Switch表达式Java13到Java16:小幅改进Java17:

MySQL:获取Auto_increment失败问题记录

项目场景:人员权限设置,定义了一张存储自增id的表sys_id_sequence(A表)/*A表定义*/SETNAMESutf8mb4;SETFOREIGN_KEY_CHECKS=0;--------------------------------Tablestructureforsys_id_sequence----

热文推荐