Spring 源码学习——加载 Bean

pix4d安装步骤 pix4d三维模型软件的安装步骤 阅读详情

继上次注册 bean 之后好久没更新,这两天有空查了查资料也自己看了看 spring BeanFactory 的 getBean(beanName); 这个方法。因时间有限不能像之前那样复制代码并一行一行写上注释,这次只是将代码流程中的一些方法复制出来进行注释。

Spring 的版本是 5.1.3.RELEASE

首先是 getBean(String beanName);

Person person = (Person) context.getBean("person");
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
    // 获取 beanName 参数 name 有可能是别名也有可能是 FactoryBean 带 "&" 前缀
	final String beanName = transformedBeanName(name);
	Object bean;
	// 获取缓存中的 bean
	// Eagerly check singleton cache for manually registered singletons.
	Object sharedInstance = getSingleton(beanName);
	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 + "'");
			}
		}
		// 获取 bean 实例
		bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
	}

	else {
	    // 如果 bean 的范围是非单例的则会报错,只有单例才会去尝试解决循环依赖
		// Fail if we're already creating this bean instance:
		// We're assumably within a circular reference.
		if (isPrototypeCurrentlyInCreation(beanName)) {
			throw new BeanCurrentlyInCreationException(beanName);
		}

		// 获取 parentBeanFactory 在当前例子中 parentBeanFactory 为 null
		// 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 if (requiredType != null) {
				// No args -> delegate to standard getBean method.
				return parentBeanFactory.getBean(nameToLookup, requiredType);
			}
			else {
				return (T) parentBeanFactory.getBean(nameToLookup);
			}
		}

		// typeCheckOnly: 是否获取实例用于类型检查而不是实际使用
           // !typeCheckOnly 如果不只是做类型检查而需要实际创建使用
		if (!typeCheckOnly) {
		    // 调用 alreadyCreated.add 将 beanName 加入到缓存标记
			markBeanAsCreated(beanName);
		}

		try {
		    // 将之前注册好的 BeanDefinition 转成 RootBeanDefinition 如果存在 Parent 就将属性合并
			final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
			checkMergedBeanDefinition(mbd, beanName, args);

			// 如果存在依赖则需要递归实例化依赖的 bean
			// 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
						getBean(dep);
					}
					catch (NoSuchBeanDefinitionException ex) {

					}
				}
			}

			// 如果 RootBeanDefinition 实例时单例的范围
			// Create bean instance.
			if (mbd.isSingleton()) {
			    // 则调用 getSingleton() 方法来获取到 bean 实例
				sharedInstance = getSingleton(beanName, () -> {
					try {
						// 核心创建 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.
						destroySingleton(beanName);
						throw ex;
					}
				});
				bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
			}
			// 省略其他代码
		}
		catch (BeansException ex) {
			// 省略其他代码
		}
	}
	return (T) bean;
}

1.public Object getBean(String name);
1.1.doGetBean(name, null, null, false);
1.1.1.final String beanName = transformedBeanName(name); 先获取到对应的 beanName
1.1.2.Object sharedInstance = getSingleton(beanName); 在缓存中检查是否已经存在创建好的 bean 里面涉及到几个 map
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); Key: beanName value: bean 实例
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); Key: beanName value: bean 实例 与 singletonObjects 区别是用于存放 ObjectFactory.getObject(); 返回的 bean 实例
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); Key: beanName value: ObjectFactory 缓存的是单例工厂
1.1.3.if (isPrototypeCurrentlyInCreation(beanName)); 如果当前的 bean 正在创建则直接抛出异常 throw new BeanCurrentlyInCreationException(beanName);
1.1.4.BeanFactory parentBeanFactory = getParentBeanFactory(); 获取当前 bean 定义是否存在父容器 parentBeanFactory 比如 spring springmvc 父子容器
1.1.5.markBeanAsCreated(beanName); 标记当前 bean 正在创建打上标识
private final Set alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256)); 存储的是已经创建过的 beanName
private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256); Key: beanName value: beanDefinition 存储是是已经创建过的 beanName 和 bean 定义
1.1.6.final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); 获取到 beanName 对应的 beanDefinition 从 mergedBeanDefinitions 获取,第一次是返回一个新的 RootBeanDefinition
1.1.7.checkMergedBeanDefinition(mbd, beanName, args); 检查如果该 bean 是一个抽象类抛出异常 throw new BeanIsAbstractException(beanName);
1.1.8.String[] dependsOn = mbd.getDependsOn(); 获取是否需要处理依赖 bean 如果需要则遍历 dependsOn 的元素调用 getBean(dep);
1.1.9.if (mbd.isSingleton()) 如果该 bean 是单例的话直接创建
1.2.0.getSingleton(String beanName, ObjectFactory<?> singletonFactory); 调用 getSingleton 方法创建 bean,主要核心在第二个参数的 createBean(beanName, mbd, args); 方法

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory);

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
	Assert.notNull(beanName, "Bean name must not be null");
	synchronized (this.singletonObjects) {
	    // 首先还是先从一级缓存获取最终的 bean 实例
		Object singletonObject = this.singletonObjects.get(beanName);
		// 如果获取不到
		if (singletonObject == null) {
			if (this.singletonsCurrentlyInDestruction) {
				throw new BeanCreationNotAllowedException();
			}
			if (logger.isDebugEnabled()) {
				logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
			}
			// 将 beanName 放入 singletonsCurrentlyInCreation 缓存标记正在创建中
			beforeSingletonCreation(beanName);
			boolean newSingleton = false;
			boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
			if (recordSuppressedExceptions) {
				this.suppressedExceptions = new LinkedHashSet<>();
			}
			try {
			    // 调用参数 lambda 表达式传递的行为也就是 ObjectFactory 类型的匿名内部类
				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;
				}
                   // 将 beanName 从 singletonsCurrentlyInCreation 缓存标记从删除
				afterSingletonCreation(beanName);
			}
			if (newSingleton) {
			    // 加入一级缓存删除二三级缓存
				addSingleton(beanName, singletonObject);
			}
		}
		return singletonObject;
	}
}

2.public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory);
2.1.Object singletonObject = this.singletonObjects.get(beanName); 尝试从缓存中获取如果获取不到并且该 bean 在销毁中则抛出异常 throw new BeanCreationNotAllowedException(beanName, message);
private boolean singletonsCurrentlyInDestruction = false; 销毁标识
2.2.beforeSingletonCreation(beanName); 将该 bean 加入创建单例 bean 的缓存中
2.3.singletonObject = singletonFactory.getObject(); 重点来了直接调用 ObjectFactory.createBean(beanName, mbd, args); 方法创建 bean
2.4.addSingleton(beanName, singletonObject); 最后将创建好的 bean 依次放入缓存
private final Set registeredSingletons = new LinkedHashSet<>(256); 存储的是创建好的 beanName

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args);

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

	if (logger.isTraceEnabled()) {
		logger.trace("Creating instance of bean '" + beanName + "'");
	}
	RootBeanDefinition mbdToUse = mbd;

	// 首先获取到 beanName 的 Class 对象
	// 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 {
	    // 给 BeanPostProcessors 一个返回代理而不是目标 bean 实例的机会
		// 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 {
	    // 创建 bean
		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		if (logger.isTraceEnabled()) {
			logger.trace("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);
	}
}

3.1.Class<?> resolvedClass = resolveBeanClass(mbd, beanName); 获取该 bean 对应的 class
3.2.mbdToUse.prepareMethodOverrides(); 设置该 bean 是否有重写方法
3.3.Object bean = resolveBeforeInstantiation(beanName, mbdToUse); 在该 bean 实例化之前,检查是否需要返回 proxy 代理对象。
3.4.Object beanInstance = doCreateBean(beanName, mbdToUse, args); 进行实例化 bean

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args);

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {
       // BeanWrapper 是 Spring 提供的对 bean 操作的封装
	// Instantiate the bean.
	BeanWrapper instanceWrapper = null;
	if (mbd.isSingleton()) {
	    // 如果是单例模式就从 factoryBeanInstanceCache 缓存中删除
		instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
	}
	// 如果不存在缓存中
	if (instanceWrapper == null) {
	    // 创建 bean
		instanceWrapper = createBeanInstance(beanName, mbd, args);
	}
	final Object bean = instanceWrapper.getWrappedInstance();
	Class<?> beanType = instanceWrapper.getWrappedClass();
	if (beanType != NullBean.class) {
		mbd.resolvedTargetType = beanType;
	}

	// Allow post-processors to modify the merged bean definition.
	synchronized (mbd.postProcessingLock) {
		if (!mbd.postProcessed) {
			try {
			    // 遍历所有 MergedBeanDefinitionPostProcessor 执行 postProcessMergedBeanDefinition 方法
				applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
			}
			catch (Throwable ex) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Post-processing of merged bean definition failed", ex);
			}
			mbd.postProcessed = true;
		}
	}
       // 如果当前 bean 是一个单例的并且自动尝试解析 bean 之间的循环引用,并且正在创建中则加入三级缓存
	// Eagerly cache singletons to be able to resolve circular references
	// even when triggered by lifecycle interfaces like BeanFactoryAware.
	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));
	}

	// Initialize the bean instance.
	Object exposedObject = bean;
	try {
	    // 填充属性
		populateBean(beanName, mbd, instanceWrapper);
		// 执行 init 方法和 init-method 配置方法
		exposedObject = initializeBean(beanName, exposedObject, mbd);
	}
	catch (Throwable ex) {
		if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
			throw (BeanCreationException) ex;
		}
		else {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
		}
	}
	// 省略代码
	// Register bean as disposable.
	try {
		registerDisposableBeanIfNecessary(beanName, bean, mbd);
	}
	catch (BeanDefinitionValidationException ex) {
		throw new BeanCreationException(
				mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
	}

	return exposedObject;
}

4.1.instanceWrapper = createBeanInstance(beanName, mbd, args); 创建 bean 里面就是调用反射使用构造器创建实例 bean
4.2.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName); 获取所有的 BeanPostProcessor 判断里面元素是不是 MergedBeanDefinitionPostProcessor,再调用 MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition(mbd, beanType, beanName);
4.3.populateBean(beanName, mbd, instanceWrapper); 到了初始化 bean 数据的函数
4.4.initializeBean(beanName, exposedObject, mbd); 执行一些 bean 后置处理(BeanNameAware、BeanClassLoaderAware、BeanFactoryAware、BeanPostProcessor);
4.5.registerDisposableBeanIfNecessary(beanName, bean, mbd); 注册销毁 bean 的回调

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw);

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
	// 如果 bw bean 实例为 null 并且 beanDefinition 中描述 bean 的属性不为空则抛出异常
    if (bw == null) {
		if (mbd.hasPropertyValues()) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
		}
		else {
			// 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.
	boolean continueWithPropertyPopulation = true;

    // 如果注册了 InstantiationAwareBeanPostProcessor 则遍历调用 postProcessAfterInstantiation 方法
	if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
					continueWithPropertyPopulation = false;
					break;
				}
			}
		}
	}

	if (!continueWithPropertyPopulation) {
		return;
	}

	// spring 会根据注入类型来判断调用哪个方法一般默认是 AUTOWIRE_NO
	PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

	if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME || mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
		MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
		// Add property values based on autowire by name if applicable.
		if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_NAME) {
		    // 根据 name 注入
			autowireByName(beanName, mbd, bw, newPvs);
		}
		// Add property values based on autowire by type if applicable.
		if (mbd.getResolvedAutowireMode() == AUTOWIRE_BY_TYPE) {
		    // 根据 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();
		}
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
				if (pvsToUse == null) {
					if (filteredPds == null) {
						filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
					}
					pvsToUse = ibp.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) {
		applyPropertyValues(beanName, mbd, bw, pvs);
	}
}

5.1.if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) 到这步的时候 bean 实例化完成但是还没开始属性设值,取所有 InstantiationAwareBeanPostProcessor 的实现类调用 postProcessAfterInstantiation(bw.getWrappedInstance(), beanName); InstantiationAwareBeanPostProcessor 的实现类可以在这里对 bean 进行状态修改
5.2.PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null); 取出该 bean 的所有属性
5.3.autowireByName(beanName, mbd, bw, newPvs); 通过 name 找到所有属性值
5.4.autowireByType(beanName, mbd, bw, newPvs); 通过 type 找到所有属性值
5.5.for (BeanPostProcessor bp : getBeanPostProcessors()) 获取所有的 BeanPostProcessor
5.6.if (bp instanceof InstantiationAwareBeanPostProcessor) 找到所有的 InstantiationAwareBeanPostProcessor 类型
5.7.pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName); 对采用 @Autowired 注解的依赖进行设值 field.set(bean, value);
5.8.if (pvs != null) applyPropertyValues(beanName, mbd, bw, pvs); 设置该 bean 的属性值

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd);

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
	if (System.getSecurityManager() != null) {
		AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
		    // 调用实现了 XxxAware 接口的方法
			invokeAwareMethods(beanName, bean);
			return null;
		}, getAccessControlContext());
	}
	else {
           // 调用实现了 XxxAware 接口的方法
		invokeAwareMethods(beanName, bean);
	}

	Object wrappedBean = bean;
	if (mbd == null || !mbd.isSynthetic()) {
	    // 调用 BeanPostProcessor.postProcessBeforeInitialization
		wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
	}

	try {
	    // 调用 InitializingBean 接口的方法
		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.postProcessAfterInitialization
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}

	return wrappedBean;
}

protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable {

		boolean isInitializingBean = (bean instanceof InitializingBean);
		if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
			if (logger.isTraceEnabled()) {
				logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
			}
			if (System.getSecurityManager() != null) {
				try {
					AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
					    // 调用 InitializingBean.afterPropertiesSet
						((InitializingBean) bean).afterPropertiesSet();
						return null;
					}, getAccessControlContext());
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
                // 调用 InitializingBean.afterPropertiesSet
				((InitializingBean) bean).afterPropertiesSet();
			}
		}

		if (mbd != null && bean.getClass() != NullBean.class) {
            // 判断是否指定了 init-method,如果指定了则调用
			String initMethodName = mbd.getInitMethodName();
			if (StringUtils.hasLength(initMethodName) &&
					!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
					!mbd.isExternallyManagedInitMethod(initMethodName)) {
                // 利用反射机制执行
				invokeCustomInitMethod(beanName, bean, mbd);
			}
		}
	}

6.1.invokeAwareMethods(beanName, bean); 如果该 bean 实现了 Aware(BeanNameAware、BeanClassLoaderAware、BeanFactoryAware) 接口则调用对应的 set 方法进行赋值
6.2.wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName); 获取出所有的 BeanPostProcessor 调用对应的 Object current = processor.postProcessBeforeInitialization(result, beanName);
6.3.invokeInitMethods(beanName, wrappedBean, mbd); 如果该 bean 实现了 InitializingBean 接口则调用对应的 ((InitializingBean) bean).afterPropertiesSet();
6.4.invokeCustomInitMethod(beanName, bean, mbd); 调用 bean 自定义的 init-method 方法
6.5.wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); 获取出所有的 BeanPostProcessor 调用对应的 Object current = processor.postProcessAfterInitialization(result, beanName);

执行完这 6 步之后一个 spring bean 的加载就已经结束了进行逐层返回。帮助了自己巩固记忆,如果写的不足之处望指出谢谢各位观看!

注释

id 和 name

每个 bean 在配置的时候都有唯一的名字和多个别名,获取 bean 的时候可以通过 beanName 也可以通过别名

beanFactory.getBean("beanName or alias");

以下配置的结果就是:beanName 为 person,别名有 3 个,分别为 p1、p2、p3。

<bean id="person" name="p1, p2, p3" class="com.feil.springtest.ioc.test01.Person">

以下配置的结果就是:beanName 为 p1,别名有 2 个,分别为 p2、p3。

<bean name="p1, p2, p3" class="com.javadoop.example.MessageServiceImpl" />

以下配置的结果就是:beanName 为:com.feil.springtest.ioc.test01.Person#0,

<bean class="com.feil.springtest.ioc.test01.Person" />

以下配置的结果就是:beanName 为 person,没有别名。

<bean id="person" class="com.feil.springtest.ioc.test01.Person" />
profile

我们可以把不同环境的配置分别配置到单独的文件中

<beans profile="dev" ....>
	<bean ... />
	<bean ... />
	<bean ... />
</beans>
<beans profile="test" ....>
	<bean ... />
	<bean ... />
	<bean ... />
</beans>

当然,我们也可以在一个配置文件中使用:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="...">

    <beans profile="dev">
        ...
    </beans>

    <beans profile="test">
        ...
    </beans>
</beans>

那么 spring 是怎么识别出不同的环境呢?Spring 在启动的过程中,会去寻找 “spring.profiles.active” 的属性值,根据这个属性值来的。那怎么配置这个值呢?
Spring 会在这几个地方寻找 spring.profiles.active 的属性值:操作系统环境变量、JVM 系统变量、web.xml 中定义的参数、JNDI。
最简单的方式肯定是在程序启动的时候指定:

-Dspring.spring.profiles.active="dev"
BeanPostProcessor

BeanPostProcessor接口作用:
如果我们想在 Spring 容器中完成 bean 实例化、配置以及其他初始化方法前后要添加一些自己逻辑处理。我们需要定义一个或多个 BeanPostProcessor 接口实现类,然后注册到 Spring IoC 容器中。
BeanPostProcessor 概念在 Spring 中也是比较重要的。我们看下接口定义:

public interface BeanPostProcessor {
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

1:后置处理器的 postProcessorBeforeInitailization 方法是 bean 在初始化之前会执行 postProcessBeforeInitialization 这个方法。
2:后置处理器的 postProcessorAfterInitailization 方法是在 bean 初始化完成之后会执行 postProcessAfterInitialization 这个方法。
请看第一个方法,这个方法接受的第一个参数是 bean 实例重点在返回值将会作为新的 bean 实例,那意味着什么呢?我们很容易想到的就是,我们这里可以对一些我们想要修饰的 bean 实例做一些事情。但是对于 Spring 框架来说,它会决定是不是要在这个方法中返回 bean 实例的代理。

Java调用YOLOv26全解析:从ONNX模型部署到工业质检实战 本文分享了工业自动化领域使用Java调用YOLOv26进行零件缺陷检测的完整方案。通过YOLOv26s模型结合ONNX Runtime Java部署,误检率和漏检率显著降低(分别从12%降至2.1%,8%降至0.8%)。文章详细介绍了方案选型理由、环境配置避坑指南、ONNX模型导出步骤,以及Maven依赖配置(分CPU/GPU版本)。该方案直接在上位机Java环境中运行,避免了跨语言调用损耗,适合工业质检场景部署,提供了可复用的性能优化和多线程推理实现。 阅读详情

相关推荐

使用OpenCV进行3D重建:详细指南

3D重建是计算机视觉领域的一项关键技术,它能够从二维图像中恢复出场景的三维结构。这项技术在机器人视觉、增强现实和3D建模等多个领域都有广泛的应用。在本篇技术博客中,我们将详细介绍如何使用OpenCV这一流行的计算机视觉库来实现3D重建。我们将逐步探讨整个过程,包括相机标定、特征点提取与匹配、立体校正、深度图计算以及最终的三维重建。3D重建是一个复杂的过程,涉及多个步骤和多种算法。OpenCV提供了强大的工具来支持这一过程,从相机标定到特征点提取与匹配,再到立体校正和深度图计算,最后实现三维重建。

weixin_41544125的博客 1315

定义常量Map

我们知道在java编程中,定义常量时必须用到:static final,既是静态的,又是不可修改的; 普通类型的常量可以这么定义,但是对于集合类型的常量,我们该怎么定义才好用呢? 本文就来讲一下常量Map的定义,如有错误欢迎大家指点批评! 一、普通类型常量定义 举例如下: private staic final String SERVICE_URL=“XXXXXXXX”; 这样就完成了定义; 二、集合Map常量定义 方式一: private static final Map<String, Stri

m0_55070913的博客 885

Android音频学习(一)——音频基础

在系统的学习Android音频之前,先了解音频的基础知识。

miemie2014的博客 1482

Spring源码获取Bean

前言 前面的文章描述了,通过xml文件的解析,得到了Bean的定义,但是Bean却没有new出来。我们主要看下容器将非懒加载的单例bean是怎么创建起来的。 源码解析 通过refresh的代码,去掉关系不大的代码。 //AbstractApplicationContext类 public void refresh() throws BeansException, IllegalStateExcep...

wyq411576759的专栏 216

图片边界矢量化-地理配准

无地理和投影信息的JPG图片,通过ArcGIS进行地理配准(Georeferencing)完成数字化边界。

u012727861的博客 1902

STM32进入HardFault_Handler时,如何找到问题所在?

当STM32进入HardFault_Handler时,定位问题发生的点

m0_60831979的博客 2147

JAVA基础(七)-Map篇

一、map实现类 接口类java.util.Map有四个实现类:HashMap、Hashtable、LinkedHashMap、TreeMap HashMap:最常用,遍历时随机 Hashtable:相较HashMap:键值均不能为null(编译时不会报错);线程安全,多线程可共用一个Hashtable LinkedHashMap:键按插入顺序排序,遇到需按插入顺序遍历时可用 TreeM...

LiuYiFan_TOT的博客 404

机器视觉/将HIK海康面阵相机连接Halcon软件

本文简述了如何将海康面阵相机连接到Halcon软件中进行实时取图的过程。

Dahe.qu 4864

NoUniqueBeanDefinitionException: No qualifying bean of type ‘XXXX‘ available: expected single matchi

spring在进行注入的时候如果发现有两个bean,这时候他是不知道注入哪个bean的,就会报如下的错误: Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'XXXX' available: expected single matching bean but found 2: 这时候可以在bean的xml文件里给bean配置优先级:

只为成功找方法 不为失败找借口 1268

SAP Fiori 会话超时全解析:从 Launchpad 到 Identity Authentication 的统一策略

SAP Fiori会话超时机制解析与配置策略 本文深入探讨SAP Fiori项目中的会话超时机制,分析其对系统安全和用户体验的双重影响。文章系统拆解了SAP Fiori Launchpad与SAP Cloud Identity Services之间的会话超时工作原理,重点介绍了两种超时机制:服务器驱动的超时(通过SESSION_TIMEOUT_STOP_DATA_REFRESH参数控制)和UI驱动的超时(通过SESSION_TIMEOUT_INTERVAL_IN_MINUTES参数控制)。文中结合制造业产线

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 211

基于GA-BP遗传算法优化神经网络的多输入多输出数据预测-Python代码实现

多输入多输出的GA-BP神经网络

2301_80449389的博客 2306

反射和动态加载bean

最近我们部门有个小项目,用来管理这个公司所有项目用到的代码表,例如国家代码、行政区划代码等。这个项目的功能其实很少,就是简单的修改、查询、新增和逻辑删除。但是为每张表都写一套增删改查的页面和一套service,工作量巨大,且维护很困难。我们发现各个表的业务其实都很类似,如果能写一套通用的service代码,在web层根据表名动态调用,在通用的jsp上生成想要的数据,那就只需要写一套代码就可以完成所

king_zxy的博客 675

使用 Python 爬虫抓取 IMDb 电影信息 - 评分、评论与基本信息抓取教程

本文介绍了如何使用 Python 爬虫技术抓取 IMDb 电影评分、评论和基本信息。我们分别展示了通过IMDb API和两种方法抓取数据,并进行了数据存储、分析与可视化。在未来,我们还可以基于这些数据开发电影推荐系统、情感分析工具等,进一步丰富电影数据的应用场景。通过这些实践,您不仅学会了如何抓取和存储数据,还可以通过这些基础来构建自己的数据分析应用,获取更丰富的电影数据。

2201_76125261的博客 599

spring源码学习一: bean的加载

1 吐槽 学spring,用spring,天天围绕着这么一个框架转;Autowired,Resource,Service,Controller,Repository,各种注解都写了不下千遍,敲代码得速度可能比菜市场的老大妈算菜钱的心算速度都要快了;樱花下落的速度是五厘米每秒,我敲注解的手速是1分钟30个。。。。。 然而代码敲了很多,始终停留在应用层面,而且是很粗浅的日常使用罢了,就像老大妈只知道一斤菠菜3.2块钱,3斤菠菜就是9.6块一样,虽心算速度直逼计算机,却不知这种程度的计算在整个数学的菜单里,就是一

weixin_44137343的博客 260

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Spring源码学习四、Bean的加载

这章分析的是,从容器中获取bean Student student = (Student)xmlBeanFactory.getBean("student"); bean加载的大体思路 @Override public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); } 继续往下追踪 /** * Return an instance, whic

贵在坚持 406

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

9、Spring 源码学习 ~ Bean 的加载

Spring 源码学习

戴泽王的博客 548

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

Spring 源码学习(四) bean 的加载

既然我们 Spring 辛辛苦苦将 bean 进行了注册,当然需要拿出来进行使用,在使用之前还需要经过一个步骤,就是 bean 的加载。在第一篇笔记提到了,完成 bean...

Java极客技术 230

二、Spring源码学习之Bean的加载过程

二、Spring源码之Bean的加载过程 1.Bean的定义方式 xml配置 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework

snow_hope的博客 216

spring源码学习:bean加载过程

spring会通过AbstractApplicationContext抽象类的refresh()方法加载bean。

stayfoolishqaq的博客 489

Spring源码学习笔记-bean加载

1、总体流程 2、转换对应的beanName 由于入参name不一定就是beanName,所以需要转换一下; 主要有如下转换内容: 2.1、去除FactoryBean修饰符‘&’ 获取bean是通过FactoryBean.getObject(); name = “&nane”表示获取对应的FactoryBean本身; 而name="nane"表示获取获取nane对应的bean;即FactoryBean.getObject(); 方法的返回; 2.2、别名转为beanName 因为用户传入的n

歆夜的博客 283

spring源码学习(3):bean的加载

对于加载bean的功能,在Spring中的调用方法为: MyTestBean bean = (MyTestBean)bf.getBean("myTestBean"); 这句代码实现了什么样的功能呢? 来看看AbstractBeanFactory里咋写的 getBean public Object getBean(String name) throws BeansException { return doGetBean(name, null, null, false); } protected &

qq_35217284的博客 728

spring源码学习之bean的加载(一)

  对XML文件的解析基本上已经大致的走了一遍,虽然没有能吸收多少,但是脑子中总是有些印象的,接下来看下spring中的bean的加载,这个比xml解析复杂的多。这个加载,在我们使用的时候基本上是:BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("beanFactory.xml"));MyTestBea...

weixin_30640291的博客 162

Spring 源码学习笔记(四) bean的加载

个人学习Spring源码系列 bean的加载 一、总览 bean加载的调用方式 MyTestBean bean = (MyTestBean) bf.getBean("myTestBean") 加载过程相当复杂: (1)转换对应的beanName 去除FactoryBean的修饰符 取指定alias所表示的最终beanName (2)尝试从缓存中加载单例 如果加载不成功则再次尝试从singletonFactories中加载. 在Spring中创建bean的原则是不等bean创建完成就会将.

panjianlongWUHAN的专栏 1183

spring源码学习之bean的加载(三)

  接着二中的继续写,那个都超过1000行了,哈,需要重新写一个,要不太长了,我都看不下去了 7.4 初始化bean doCreateBean函数中有这样一行代码:这行代码中initializeBean函数就是初始化bean的逻辑exposedObject = initializeBean(beanName, exposedObject, mbd); 这个方法在org.spring...

weixin_38168590的博客 118

《Spring源码深度解析》学习笔记-bean的加载

对于bean的加载,在spring中的调用方式为: MyTestBean bean=(MyTestBean) bf.getBean("myTestBean"); 根据上图,Spring加载Bean的大致过程: 1.转换对应的beanName(其实就是获取真正的beanName),因为传入的beanName可能是别名或者FactoryBean 去除Fac...

419

spring源码初步学习-bean的加载

第二部分:bean的加载 一 bean加载流程概览 调用XmlBeanFactory.getBean(String name)方法时,最终会进入到AbstractBeanFactory的doGetBean方法 1)转换对应beanName: final String beanName = transformedBeanName(name); 因为传入的name可能是别名,也可

Mailzyw的专栏 677
上一篇: Git 学习(三)Git 创建版本库
下一篇: Rabbit MQ 基础入门
一定要细心
博客等级 码龄12年 11粉丝 58原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值