Spring IOC容器bean初始化源码分析

OpenWRT软件源更换保姆级教程:从国内镜像到官方源一键切换(含常见报错解决) 本文提供OpenWRT软件源更换的详细教程,涵盖从国内镜像源到官方源的切换方法,并深度解析常见报错解决方案。针对国内网络环境,指导用户如何精准定位系统信息、备份配置、选择并配置清华等国内镜像源,以及处理签名验证失败、依赖缺失、404错误等典型问题,旨在提升软件包管理效率与稳定性。 阅读详情

上一篇分析对bean定义的解析源码进行了分析,这个过程的最终结果是把xml文件中bean的定义解析成一个个的BeanDefinition对象并且注册到容器中,在Spring IOC容器启动简介篇中分析,在容器启动的最后会对容器中的所有bean进行初始化,利用之前解析出的BeanDefinition对象,创建一个个最终的bean对象,并且完成bean之间的依赖注入,本篇从源码的角度分析在容器启动时所有bean的初始化过程,bean初始化的粗略序列图如下:

初始化bean

按照作用域划分bean有如下几个作用域

singleton

prototype

自定义作用域

关于bean的初始化,几种作用域的bean基本上是相同的,所以下面主要分析singleton作用域bean初始化,可能会稍微提到其它作用域。

合并BeanDefinition

遍历所有已经注册到容器中的bean名称,因为在bean定义解析完成之后所有解析出的bean名称和bean名称和BeanDefinition之间的映射关系都已经注册到容器中,所以根据bean名称可以定位到响应的BeanDefinition,定位到BeanDefinition之后,接下来需要合并BeanDefinition,因为bean定义中可能会有parent属性表示该bean继承某个bean,所有要把父bean的一些属性拷贝到子bean中,代码在AbstractBeanDefinition中,该方法会把当前bean定义中一些属性复制到other bean定义中。

public void overrideFrom(BeanDefinition other) {
	if (StringUtils.hasLength(other.getBeanClassName())) {
		setBeanClassName(other.getBeanClassName());
	}
	if (StringUtils.hasLength(other.getFactoryBeanName())) {
		setFactoryBeanName(other.getFactoryBeanName());
	}
	if (StringUtils.hasLength(other.getFactoryMethodName())) {
		setFactoryMethodName(other.getFactoryMethodName());
	}
	if (StringUtils.hasLength(other.getScope())) {
		setScope(other.getScope());
	}
	setAbstract(other.isAbstract());
	setLazyInit(other.isLazyInit());
	setRole(other.getRole());
	getConstructorArgumentValues().addArgumentValues(other.getConstructorArgumentValues());
	getPropertyValues().addPropertyValues(other.getPropertyValues());
	setSource(other.getSource());
	copyAttributesFrom(other);

	if (other instanceof AbstractBeanDefinition) {
		AbstractBeanDefinition otherAbd = (AbstractBeanDefinition) other;
		if (otherAbd.hasBeanClass()) {
			setBeanClass(otherAbd.getBeanClass());
		}
		setAutowireCandidate(otherAbd.isAutowireCandidate());
		setAutowireMode(otherAbd.getAutowireMode());
		copyQualifiersFrom(otherAbd);
		setPrimary(otherAbd.isPrimary());
		setDependencyCheck(otherAbd.getDependencyCheck());
		setDependsOn(otherAbd.getDependsOn());
		setNonPublicAccessAllowed(otherAbd.isNonPublicAccessAllowed());
		setLenientConstructorResolution(otherAbd.isLenientConstructorResolution());
		if (StringUtils.hasLength(otherAbd.getInitMethodName())) {
			setInitMethodName(otherAbd.getInitMethodName());
			setEnforceInitMethod(otherAbd.isEnforceInitMethod());
		}
		if (StringUtils.hasLength(otherAbd.getDestroyMethodName())) {
			setDestroyMethodName(otherAbd.getDestroyMethodName());
			setEnforceDestroyMethod(otherAbd.isEnforceDestroyMethod());
		}
		getMethodOverrides().addOverrides(otherAbd.getMethodOverrides());
		setSynthetic(otherAbd.isSynthetic());
		setResource(otherAbd.getResource());
	}
	else {
		setResourceDescription(other.getResourceDescription());
	}
}
bean定义合并完成之后生成一个RootBeanDefinition对象返回给容器。如果bean没有继承其它的bean,那么把原始的BeanDefinition封装到RootBeanDefinition对象中返回给容器。

protected RootBeanDefinition getMergedBeanDefinition(
		String beanName, BeanDefinition bd, BeanDefinition containingBd)
		throws BeanDefinitionStoreException {

	synchronized (this.mergedBeanDefinitions) {
		RootBeanDefinition mbd = null;

		...

		if (mbd == null) {
			if (bd.getParentName() == null) {
				// Use copy of given root bean definition.
				if (bd instanceof RootBeanDefinition) {
					mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
				}
				else {
					mbd = new RootBeanDefinition(bd);
				}
			}
			else {
				// Child bean definition: needs to be merged with parent.
				BeanDefinition pbd;
				
				...
				
				mbd = new RootBeanDefinition(pbd);
				mbd.overrideFrom(bd);
			}
			
			...
			
		}

		return mbd;
	}
}


区分工厂bean

容器启动时会初始化所有非抽象并且非懒加载的单例bean,接下来区分bean的类型是不是FactoryBean,FactoryBean比较特殊,因为FactoryBean是用来生成其它bean的,所以如果在容器中定义了FactoryBean时,通过该FactoryBean的id或别名获取的不是FactoryBean本身而是它生产的bean,触发FactoryBean.getObject方法,并且默认情况下FactoryBean.getObject不会被提前触发必须通过应用层调用触发,容器中的处理是,如果bean是FactoryBean,通过在beanName前加上&符号让容器初始化FactoryBean的真正实例,并且判断该FactoryBean的目标bean是否需要提前初始化,默认情况下时不需要,但是可以通过SmartFactoryBean接口来进行扩展,如果需要初始化,调用bean的初始化bean实例getBean方法。如果bean是普通的bean直接调用bean的初始化getBean方法,代码在DefaultListableBeanFactory的preInstantiateSingletons方法中:

public void preInstantiateSingletons() throws BeansException {
	
	...
	
	for (String beanName : beanNames) {
		RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
		if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
			if (isFactoryBean(beanName)) {
				final FactoryBean<?> factory = (FactoryBean<?>) getBean(FACTORY_BEAN_PREFIX + beanName);
				boolean isEagerInit;
				if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
					isEagerInit = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
						public Boolean run() {
							return ((SmartFactoryBean<?>) factory).isEagerInit();
						}
					}, getAccessControlContext());
				}
				else {
					isEagerInit = (factory instanceof SmartFactoryBean &&
							((SmartFactoryBean<?>) factory).isEagerInit());
				}
				if (isEagerInit) {
					getBean(beanName);
				}
			}
			else {
				getBean(beanName);
			}
		}
	}
}


获取bean实例

无论是容器启动触发的bean初始化还是应用层触发的bean初始化,代码都是重用的,都是通过getBean方法获取bean的实例,获取bean实例时先检查bean是否已经实例化过并且注册到容器中了,包括两种情况:

  1. 所有初始化操作已经完成,所有bean的依赖关系已经注入。
  2. 提前暴露的bean,这种bean的某些依赖关系还没有注入完成,之所以出现这种情况是因为bean存在循环依赖,为了避免死循环需要提前暴露bean的实例,通过ObjectFactory.getObject创建bean实例。

如果bean已经被实例化过直接使用该bean,代码在DefaultSingletonBeanRegistry类的getSingleton方法,所有初始化完成的bean存储在singletonObjects哈希表中,提前暴露的bean存储在earlySingletonObjects哈希表中。

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
	Object singletonObject = this.singletonObjects.get(beanName);
	if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
		synchronized (this.singletonObjects) {
			singletonObject = this.earlySingletonObjects.get(beanName);
			if (singletonObject == null && allowEarlyReference) {
				ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
				if (singletonFactory != null) {
					singletonObject = singletonFactory.getObject();
					this.earlySingletonObjects.put(beanName, singletonObject);
					this.singletonFactories.remove(beanName);
				}
			}
		}
	}
	return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
如果bean没有实例化过,执行bean的实例化初始化,如果bean的作用域时prototype并且和其它bean发生了循环引用,初始化失败抛出BeanCurrentlyInCreationException异常。

因为填充bean的属性时,如果bean的属性也引用了一个bean,那么此时同样也会触发getBean方法,如果当前引用的bean在当前容器中不存在,那么把初始化该bean的动过委托给父容器,也就是从父容器中查找这个bean,比如属性的引用标签是<ref parent="xxxx">这种形式时,那么初始化xxxx这个bean的动过只能交给父容器。相关代码片段在AbstractBeanFactory的doGetBean方法中:

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

	...
	
	Object sharedInstance = getSingleton(beanName);
	if (sharedInstance != null && args == null) {
		
		...
		
	}

	else {
	
		...

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

		...
		
	}

	...
	
	return (T) bean;
}
如果bean是当前容器的bean,那么继续初始化逻辑,在初始化之前先给bean打上标记,标识当前bean已经被创建,标识信息存在alreadyCreated哈希表中。校验bean定义,是否是抽象bean,或者传了arg参数但是bean不是prototype,当需要根据动态参数实例化bean时,该bean的作用域只能是prototype。

protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, Object[] args)
		throws BeanDefinitionStoreException {

	// check if bean definition is not abstract
	if (mbd.isAbstract()) {
		throw new BeanIsAbstractException(beanName);
	}

	// Check validity of the usage of the args parameter. This can
	// only be used for prototypes constructed via a factory method.
	if (args != null && !mbd.isPrototype()) {
		throw new BeanDefinitionStoreException(
				"Can only specify arguments for the getBean method when referring to a prototype bean definition");
	}
}


检查当前bean是否有依赖的bean,也就是说bean是否定义了depends-on属性,如果有的话先初始化这些依赖bean,并且注册bean的依赖关系到容器中,包含两个结构,一个是bean的依赖列表dependentBeanMap,另一个是bean的被依赖列表dependenciesForBeanMap,存储dependentBeanMap的目的是在销毁该bean时直接遍历该哈希表把所有依赖的bean都销毁掉,dependenciesForBeanMap这个结构目前还没有发现有什么用途,相关代码片段如下:

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

	...
	
	try {
	
		...

		// Guarantee initialization of beans that the current bean depends on.
		String[] dependsOn = mbd.getDependsOn();
		if (dependsOn != null) {
			for (String dependsOnBean : dependsOn) {
				getBean(dependsOnBean);
				registerDependentBean(dependsOnBean, beanName);
			}
		}
		
		...
		
	}
	catch (BeansException ex) {
		cleanupAfterBeanCreationFailure(beanName);
		throw ex;
	}
	
    ...
	
	return (T) bean;
}


创建bean实例

检查当前是否正在销毁所有的单例bean,如果是的话报错抛出BeanCreationNotAllowedException异常,只有等销毁操作完成之后才能进行bean初始化动作。

存储标记到singletonsCurrentlyInCreation哈希表中标识bean正在被创建,这个标识将会被用来处理循环引用。接下来创建bean实例,对Class、MethodOverride做一些准备处理,然后进行实例化前处理操作,检查容器中的所有BPP(BeanPostProcessor)中是否有实现了InstantiationAwareBeanPostProcessor接口的,如果有的话触发它的postProcessBeforeInstantiation方法看看该方法是否产生了非空的bean实例,如果有的话中断BPP的遍历,继续遍历触发BPP的postProcessAfterInitialization方法,如果有BPP返回了null实例,中断遍历,代码在AbstractAutowireCapableBeanFactory类:

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.hasBeanClass() && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			bean = applyBeanPostProcessorsBeforeInstantiation(mbd.getBeanClass(), beanName);
			if (bean != null) {
				bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
			}
		}
		mbd.beforeInstantiationResolved = (bean != null);
	}
	return bean;
}

protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName)
		throws BeansException {

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

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
		throws BeansException {

	Object result = existingBean;
	for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
		result = beanProcessor.postProcessAfterInitialization(result, beanName);
		if (result == null) {
			return result;
		}
	}
	return result;
}
如果上述前处理中产生了非空的bean,实例初始化结束直接返回,这一步非常重要,AOP就是利用这个过程偷梁换柱把bean实例换成bean的代理对象。
如果没有BPP拦截bean的实例化,那么进入bean真正的实例化过程:

首先实例化bean,实例化有几种方式:

  • 工厂方法
  • 自定义构造子
  • 默认构造子

检查bean是否定义了factory-method,如果有factory-method使用该工厂方法实例化bean,存在两种方式,一种是定义factory-bean,通过指定的其它bean的非静态方法初始化该bean;另一种是定义class,通过该class的静态方法实例化该bean,此时factory-method必须是静态方法。如果工厂方法中有参数,那么会在工厂方法参数和构造子参数之间进行匹配,这种情况下目标bean的作用域必须是prototype,应用代码在调用getBean向容器请求bean实例时必须要传入相应的参数,下面是个简单的例子:

类定义:

public class ItemFactory {

	public ItemBean getItem(String name) {

		ItemBean item = new ItemBean(name);
		return item;

	}

}

public class ItemBean {

	private String name;

	public ItemBean(String name) {
		super();
		this.name = name;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}
bean定义:

<bean id="factory" class="spring.beans.factory.ItemFactory">
</bean>
<bean id="item1" factory-bean="factory" factory-method="getItem"
	scope="prototype">
	<constructor-arg value="name1"></constructor-arg>
</bean>
调用代码:
ApplicationContext ctx = new ClassPathXmlApplicationContext(
				"spring/beans/factory/factory.xml");
ItemBean item = (ItemBean) ctx.getBean("item1", "name11");


工厂方法实例化bean的逻辑在ConstructorResolver类的instantiateUsingFactoryMethod方法中,这里因为是singleton作用域的bean实例化,所以不会涉及到工厂方法的参数处理,args参数是null值。

如果bean定义为构造子注入或者装配模式是构造子,那么通过自定义构造子实例化bean并且完成构造子相关的依赖注入,如果没有定义工厂方法factory-method,检查自定义了构造子,完成构造子依赖注入的代码在ConstructorResolver类的autowireConstructor方法中,这个方法完成的功能是,解析出构造子和构造子参数,并对参数求值,如果出现了EL表达式对EL表示进行解析并且计算出结果,根据结果值的类型求对应的值,如果是引用类型那么首先实例化被引用的bean,调用BeanFactory的getBean,如果是字符类型那么根据参数的实际类型转换成对应的值,需要借助PropertyEditor,代码片段如下:

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
	
	...

	// Need to determine the constructor...
	Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
	if (ctors != null ||
			mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
			mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args))  {
		return autowireConstructor(beanName, mbd, ctors, args);
	}

	...
	
}


框架使用BeanWrapper来封装实例化的bean,在autowireConstructor方法的开始调用了initBeanWrapper方法,来看看这个方法:

protected void initBeanWrapper(BeanWrapper bw) {
	bw.setConversionService(getConversionService());
	registerCustomEditors(bw);
}

protected void registerCustomEditors(PropertyEditorRegistry registry) {
	PropertyEditorRegistrySupport registrySupport =
			(registry instanceof PropertyEditorRegistrySupport ? (PropertyEditorRegistrySupport) registry : null);
	if (registrySupport != null) {
		registrySupport.useConfigValueEditors();
	}
	if (!this.propertyEditorRegistrars.isEmpty()) {
		for (PropertyEditorRegistrar registrar : this.propertyEditorRegistrars) {
			try {
				registrar.registerCustomEditors(registry);
			}
			catch (BeanCreationException ex) {
				Throwable rootCause = ex.getMostSpecificCause();
				if (rootCause instanceof BeanCurrentlyInCreationException) {
					BeanCreationException bce = (BeanCreationException) rootCause;
					if (isCurrentlyInCreation(bce.getBeanName())) {
						if (logger.isDebugEnabled()) {
							logger.debug("PropertyEditorRegistrar [" + registrar.getClass().getName() +
									"] failed because it tried to obtain currently created bean '" +
									ex.getBeanName() + "': " + ex.getMessage());
						}
						onSuppressedException(ex);
						continue;
					}
				}
				throw ex;
			}
		}
	}
	if (!this.customEditors.isEmpty()) {
		for (Map.Entry<Class<?>, Class<? extends PropertyEditor>> entry : this.customEditors.entrySet()) {
			Class<?> requiredType = entry.getKey();
			Class<? extends PropertyEditor> editorClass = entry.getValue();
			registry.registerCustomEditor(requiredType, BeanUtils.instantiateClass(editorClass));
		}
	}
}
这个方法的功能是把容器中默认的PropertyEditor和注册到容器中的自定义PropertyEditor复制到BeanWrapper中,来辅助构造子注入时的值转换操作以及为后面其它属性的注入值转换做准备,为什么要把这些PropertyEditor复制到各个BeanWrapper中?我的理解是,PropertyEditor是有状态非线程安全的,每个BeanWrapper复制一份可以消除高并发下的状态同步开销。

上面提到的instantiateUsingFactoryMethod方法功能也类似,只不过instantiateUsingFactoryMethod是要解析工厂方法和参数,如果工厂方法是非静态的那么会多一步实例化工厂方法所在的bean。

无论是构造子还是工厂方法,在解析完之后都会把处理结果保存下来,RootBeanDefinition中有两个属性resolvedConstructorOrFactoryMethod和constructorArgumentsResolved,分别用来保存之前解析出的构造子/工厂方法和参数,下次在处理同样的bean时可以直接复用之前的解析结果,缓存代码在ArgumentsHolder类的storeCache方法中:

public void storeCache(RootBeanDefinition mbd, Object constructorOrFactoryMethod) {
	synchronized (mbd.constructorArgumentLock) {
		mbd.resolvedConstructorOrFactoryMethod = constructorOrFactoryMethod;
		mbd.constructorArgumentsResolved = true;
		if (this.resolveNecessary) {
			mbd.preparedConstructorArguments = this.preparedArguments;
		}
		else {
			mbd.resolvedConstructorArguments = this.arguments;
		}
	}
}

如果即没有工厂方法又没有自定义构造子,那么使用默认构造子实例化bean,进入AbstractAutowireCapableBeanFactory的instantiateBean方法,实例化过程时序图如下:

默认构造子初始化bean

SimpleInstantiationStrategy创建bean实例,首先检查bean是否定义了方法覆盖(lookup-method或replaced-method),如果未定义方法覆盖那么直接创建bean对应的class的实例。如果定义了方法覆盖,那么会使用CGLIB动态的生成class的一个子类,创建该子类的对象作为bean实例,下面两个内部类是lookup-method和replaced-method的CGLIB回调,从代码中可以看到当调用被lookup-mothod覆盖的方法时,会从容器中获取一个bean返回,而调用被replaced-method覆盖的方法时会调用MethodReplacer接口替换实现:

/**
 * CGLIB MethodInterceptor to override methods, replacing them with an
 * implementation that returns a bean looked up in the container.
 */
private class LookupOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor {

	public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
		// Cast is safe, as CallbackFilter filters are used selectively.
		LookupOverride lo = (LookupOverride) beanDefinition.getMethodOverrides().getOverride(method);
		return owner.getBean(lo.getBeanName());
	}
}


/**
 * CGLIB MethodInterceptor to override methods, replacing them with a call
 * to a generic MethodReplacer.
 */
private class ReplaceOverrideMethodInterceptor extends CglibIdentitySupport implements MethodInterceptor {

	public Object intercept(Object obj, Method method, Object[] args, MethodProxy mp) throws Throwable {
		ReplaceOverride ro = (ReplaceOverride) beanDefinition.getMethodOverrides().getOverride(method);
		// TODO could cache if a singleton for minor performance optimization
		MethodReplacer mr = (MethodReplacer) owner.getBean(ro.getMethodReplacerBeanName());
		return mr.reimplement(obj, method, args);
	}
}
实例创建成功之后,把创建好的实例封装到BeanWrapper中,并且调用initBeanWrapper方法把PropertyEditor都添加到BeanWrapper中为后面的属性值转换做准备。

接下来触发所有BPP的扩展MergedBeanDefinitionPostProcessor,挨个调用它们的postProcessMergedBeanDefinition方法。

检查是否发生了循环引用,如果存在循环引用提前缓存实例到容器中,代码片段在AbstractAutowireCapableBeanFactory类的doCreateBean方法中:

boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
		isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
	if (logger.isDebugEnabled()) {
		logger.debug("Eagerly caching bean '" + beanName +
				"' to allow for resolving potential circular references");
	}
	addSingletonFactory(beanName, new ObjectFactory<Object>() {
		public Object getObject() throws BeansException {
			return getEarlyBeanReference(beanName, mbd, bean);
		}
	});
}
在getEarlyBeanReference方法中会触发SmartInstantiationAwareBeanPostProcessor,可以在这一步把bean换掉,AOP就是在这里把Bean换成代理的。

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
	Object exposedObject = bean;
	if (bean != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
				SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
				exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
				if (exposedObject == null) {
					return exposedObject;
				}
			}
		}
	}
	return exposedObject;
}


注入bean属性

接下来是填充bean的属性,在属性填充之前先检查是否有自定义的InstantiationAwareBeanPostProcessor的实现的postProcessAfterInstantiation方法返回了false,如果有跳过属性填充,这个特性可以被用来实现属性注入。
如果bean设置了自动装配,则处理自动装配:

下面代码是byName模式的处理,从代码中可以看出,遍历所有属性,从容器中获取和属性名称相同的bean并且添加到PropertyValues结构中,并且调用registerDependentBean注册依赖关系:

protected void autowireByName(
		String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

	String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
	for (String propertyName : propertyNames) {
		if (containsBean(propertyName)) {
			Object bean = getBean(propertyName);
			pvs.add(propertyName, bean);
			registerDependentBean(propertyName, beanName);
			if (logger.isDebugEnabled()) {
				logger.debug("Added autowiring by name from bean name '" + beanName +
						"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
			}
		}
		else {
			if (logger.isTraceEnabled()) {
				logger.trace("Not autowiring property '" + propertyName + "' of bean '" + beanName +
						"' by name: no matching bean found");
			}
		}
	}
}

下面代码是byType模式的处理,首先通过属性名称查找出对应的set方法,然后根据set方法中的参数类型向容器获取对应的bean,获取到的bean添加到

PropertyValues结构中,并且调用registerDependentBean注册依赖关系:

protected void autowireByType(
		String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {

	TypeConverter converter = getCustomTypeConverter();
	if (converter == null) {
		converter = bw;
	}

	Set<String> autowiredBeanNames = new LinkedHashSet<String>(4);
	String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
	for (String propertyName : propertyNames) {
		try {
			PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
			// Don't try autowiring by type for type Object: never makes sense,
			// even if it technically is a unsatisfied, non-simple property.
			if (!Object.class.equals(pd.getPropertyType())) {
				MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
				// Do not allow eager init for type matching in case of a prioritized post-processor.
				boolean eager = !PriorityOrdered.class.isAssignableFrom(bw.getWrappedClass());
				DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
				Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
				if (autowiredArgument != null) {
					pvs.add(propertyName, autowiredArgument);
				}
				for (String autowiredBeanName : autowiredBeanNames) {
					registerDependentBean(autowiredBeanName, beanName);
					if (logger.isDebugEnabled()) {
						logger.debug("Autowiring by type from bean name '" + beanName + "' via property '" +
								propertyName + "' to bean named '" + autowiredBeanName + "'");
					}
				}
				autowiredBeanNames.clear();
			}
		}
		catch (BeansException ex) {
			throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
		}
	}
}
触发容器中注册的InstantiationAwareBeanPostProcessor,调用它们的postProcessPropertyValues方法,如果当有返回null值的,那么填充过程结束。

检查bean是否设置了依赖模式(dependency-check),如果设置的依赖模式非none,那么进行依赖检查,当bean定义的property属性在对应的class中既没有相应的设值方法,也没有相对应的属性名时不同的模式处理如下:

  • none:不检查
  • simple:如果该属性类型是简单类型或数组类型,抛出异常UnsatisfiedDependencyException
  • object:如果该属性类型是复杂引用类型,抛出异常UnsatisfiedDependencyException
  • all:所有类型都抛出异常UnsatisfiedDependencyException

相关代码在AbstractAutowireCapableBeanFactory类的checkDependencies方法中:

protected void checkDependencies(
		String beanName, AbstractBeanDefinition mbd, PropertyDescriptor[] pds, PropertyValues pvs)
		throws UnsatisfiedDependencyException {

	int dependencyCheck = mbd.getDependencyCheck();
	for (PropertyDescriptor pd : pds) {
		if (pd.getWriteMethod() != null && !pvs.contains(pd.getName())) {
			boolean isSimple = BeanUtils.isSimpleProperty(pd.getPropertyType());
			boolean unsatisfied = (dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_ALL) ||
					(isSimple && dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_SIMPLE) ||
					(!isSimple && dependencyCheck == RootBeanDefinition.DEPENDENCY_CHECK_OBJECTS);
			if (unsatisfied) {
				throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, pd.getName(),
						"Set this property value or disable dependency checking for this bean.");
			}
		}
	}
}
依赖检查完成之后,把bean定义中所有的property,即BeanDefinition中的PropertyValue结构这只到BeanWrapper中,调用BeanWrapper.setProperyValues,在这个过程中会查找所有属性的set方法并且处理property对应值,利用之前注册到BeanWrapper中的PropertyEditor,如果是引用类型还需要向容器请求对应的bean,在处理时还会缓存之前的处理结果到PropertyValue的resolvedDescriptor属性。

bean初始化

到这里bean的属性填充工作已经完成了,接下来调用initializeBean方法来完成一些初始化工作:

  • 激活Aware接口

private void invokeAwareMethods(final String beanName, final Object bean) {
	if (bean instanceof Aware) {
		if (bean instanceof BeanNameAware) {
			((BeanNameAware) bean).setBeanName(beanName);
		}
		if (bean instanceof BeanClassLoaderAware) {
			((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
		}
		if (bean instanceof BeanFactoryAware) {
			((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
		}
	}
}

  • 调用所有已注册的BPP的postProcessBeforeInitialization

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
		throws BeansException {

	Object result = existingBean;
	for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
		result = beanProcessor.postProcessBeforeInitialization(result, beanName);
		if (result == null) {
			return result;
		}
	}
	return result;
}

  • 如果实现了InitializingBean接口,调用afterPropertiesSet方法,如果定义了init-mothod,调用对应的方法

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

	boolean isInitializingBean = (bean instanceof InitializingBean);
	if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
		if (logger.isDebugEnabled()) {
			logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
		}
		if (System.getSecurityManager() != null) {
			try {
				AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
					public Object run() throws Exception {
						((InitializingBean) bean).afterPropertiesSet();
						return null;
					}
				}, getAccessControlContext());
			}
			catch (PrivilegedActionException pae) {
				throw pae.getException();
			}
		}
		else {
			((InitializingBean) bean).afterPropertiesSet();
		}
	}

	if (mbd != null) {
		String initMethodName = mbd.getInitMethodName();
		if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
				!mbd.isExternallyManagedInitMethod(initMethodName)) {
			invokeCustomInitMethod(beanName, bean, mbd);
		}
	}
}

  • 调用所有已注册BPP的postProcessAfterInitialization方法

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
		throws BeansException {

	Object result = existingBean;
	for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
		result = beanProcessor.postProcessAfterInitialization(result, beanName);
		if (result == null) {
			return result;
		}
	}
	return result;
}

注册析构回调

bean析构回调主要有一下几种方式:

  • DestructionAwareBeanPostProcessor的postProcessBeforeDestruction方法,注册这种特殊的BPP到容器
  • DisposableBean的destroy方法,bean实现DisposableBean接口
  • bean定义指定destroy-method

注册一个实现了DisposableBean接口的DisposableBeanAdapter类到容器中,bean销毁时会触发该类的destroy方法,在destroy方法中一次触发上面列出的析构回调:

public void destroy() {
	if (this.beanPostProcessors != null && !this.beanPostProcessors.isEmpty()) {
		for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
			processor.postProcessBeforeDestruction(this.bean, this.beanName);
		}
	}

	if (this.invokeDisposableBean) {
		if (logger.isDebugEnabled()) {
			logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'");
		}
		try {
			if (System.getSecurityManager() != null) {
				AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
					public Object run() throws Exception {
						((DisposableBean) bean).destroy();
						return null;
					}
				}, acc);
			}
			else {
				((DisposableBean) bean).destroy();
			}
		}
		catch (Throwable ex) {
			String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
			if (logger.isDebugEnabled()) {
				logger.warn(msg, ex);
			}
			else {
				logger.warn(msg + ": " + ex);
			}
		}
	}

	if (this.destroyMethod != null) {
		invokeCustomDestroyMethod(this.destroyMethod);
	}
	else if (this.destroyMethodName != null) {
		Method methodToCall = determineDestroyMethod();
		if (methodToCall != null) {
			invokeCustomDestroyMethod(methodToCall);
		}
	}
}


注册bean

bean的实例化初始化工作已经完成之后把bean注册到容器中:

  • 把bean名称从singletonsCurrentlyInCreation哈希表中删除
  • 把bean实例注册到容器中,添加到singletonObjects哈希表中
protected void addSingleton(String beanName, Object singletonObject) {
	synchronized (this.singletonObjects) {
		this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
		this.singletonFactories.remove(beanName);
		this.earlySingletonObjects.remove(beanName);
		this.registeredSingletons.add(beanName);
	}
}

protected void afterSingletonCreation(String beanName) {
	if (!this.inCreationCheckExclusions.containsKey(beanName) &&
			!this.singletonsCurrentlyInCreation.remove(beanName)) {
		throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
	}
}

返回bean

bean创建工作完成之后接下来的工作是把bean返回给应用层:

  • 如果bean不是FactoryBean或者bean名称是以&开头,那么直接返回bean实例给应用层
  • 如果bean是FactoryBean,那么调用FactoryBean.getObject,把返回的对象返回给应用层。

代码在AbstractBeanFactory的getObjectForBeanInstance方法:

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

	// Don't let calling code try to dereference the factory if the bean isn't a factory.
	if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
		throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
	}

	// 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.
	if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
		return beanInstance;
	}

	Object object = null;
	if (mbd == null) {
		object = getCachedObjectForFactoryBean(beanName);
	}
	if (object == null) {
		// Return bean instance from factory.
		FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
		// Caches object obtained from FactoryBean if it is a singleton.
		if (mbd == null && containsBeanDefinition(beanName)) {
			mbd = getMergedLocalBeanDefinition(beanName);
		}
		boolean synthetic = (mbd != null && mbd.isSynthetic());
		object = getObjectFromFactoryBean(factory, beanName, !synthetic);
	}
	return object;
}
至此bean的初始化代码分析就全部完成了,代码太多,感觉文章写得有点乱,抽空再整理整理

告别ROS1!在Ubuntu 22.04上为VINS-Fusion适配ROS2 Humble的完整踩坑记录 本文详细记录了在Ubuntu 22.04上将VINS-Fusion从ROS1迁移到ROS2 Humble的完整过程,包括环境搭建、依赖管理、核心代码适配及性能优化。通过实战案例和调试技巧,帮助开发者高效解决迁移过程中的常见问题,提升系统稳定性和性能。 阅读详情

相关推荐

从零实现反激式电源仿真:LTspice高级应用实例

深入解析反激式开关电源的建模与仿真过程,利用LTspice实现从零搭建电路,精准验证电路仿真效果,提升电源设计效率与可靠性。

weixin_36149538的博客 1896

spring BeanDefinition详尽篇

定义 BeanDefinition接口继承了AttributeAccessor, BeanMetadataElement两个接口,其主要的作用是实现将Bean的定义转换为java对象,是对Bean定义的一个抽象,其中的各种属性对应了xml中的各种配置信息。 类依赖 Spring中最常用的就三个具体的实现类,分类是:RootBeanDefinition,ChildBeanDefinition,GenericBeanDefinition RootBeanDefinition:最常用的类,用于标.

yxLearnJava的博客 395

Python语言在工业控制中的简单应用

在工业控制中,经常需要对采集到的数据进行分析和处理,Python的这些库可以简化这一过程。传统的工业控制系统多依赖于专用的控制硬件和软件,但随着技术的发展,开放性和灵活性成为了新的需求焦点。还有,Python社区活跃,提供了大量的开源代码和模块,这对于工业控制领域来说是一个巨大的资产。Python作为一种高级编程语言,因其简洁的语法、强大的库支持和广泛的社区资源而在工业界获得了快速的发展和广泛的应用。在工业控制领域,Python的应用日益增多,这得益于其跨平台性、脚本语言的灵活性以及与硬件设备交互的能力。

2303_78014702的博客 1721

什么是MergedBeanDefinition?

什么是MergedBeanDefinition?

b306533659的博客 1944

Vivado2023.2与Vitis协同开发:从Hello World到BOOT.BIN的完整流程解析

本文详细解析了使用Vivado 2023.2与Vitis协同开发ZYNQ/MPSoC平台的完整流程。从环境安装、硬件设计、软件编写、在线调试到生成独立的BOOT.BIN启动文件,手把手指导开发者完成从Hello World到系统固化的全步骤,并提供了常见问题的避坑指南,帮助初学者快速掌握软硬件协同开发的核心技能。

weixin_29197051的博客 176

微信公众号 - 最新详细实现H5网页接入微信支付功能,开发移动端、PC端网站集成使用微信支付流程及示例代码,公众号网页利用JS-SDK/JSAPI/H5支付授权唤起微信支付,可脱离微信环境支付或内置浏

微信公众号,微信支付,网页,移动端,h5,扫码支付,二维码付款,手机网页,电脑pc网页生成支付二维码,js-sdk,jsapi,外部浏览器调起微信支付,脱离微信环境,在微信内置浏览器如何进行微信支付,前端H5微信支付,web网站,vue2,vue3,nuxt2,nuxt3,jquery,微信公众号h5支付流程,如何实现,怎么做,回调报错,redirect_uri参数错误,必须部署才能调试吗,怎么不打包发布就能在本机测试,微信H5支付能力,uniapp微信支付,h5页面调起支付,支付没反应,无效,失败,H5页

🏆 前端领域优质创作者 6102

Spring Boot【原理分析】(3)——BeanDefinition

一、简介BeanDefinition描述了一个Bean的实例,包括属性,构造方法参数,注解等更多信息。为后面实例化Bean提供元数据依据。 BeanDefinition的实现类有: 1. RootBeanDefinition:spring BeanFactory运行期里,内部特殊bean的定义。 2. ConfigurationClassBeanDefinition:继承RootBeanDef

wwmfeng的专栏 2381

《嵌入式最全面试题-Offer直通车》目录

嵌入式领域蓬勃发展,嵌入式工程师成为众多科技企业争抢的热门人才。如果你渴望在嵌入式面试中脱颖而出,成功斩获心仪的 offer,那么《嵌入式最全面试题 - Offer直通车》将是你的绝佳选择。本专栏是优快云是热门专栏,100多篇文章,总字数过百万。每月新增订阅用户过百,现在是优惠价9.9元,后面要逐渐恢复原价,早订阅早受益。本专栏精心整理了众多超万字的精华内容,总计达数十万字的嵌入式面试题总结。涵盖从嵌入式基础知识到各大厂面试真题,从驱动开发到操作系统,从硬件到软件等各个方面。

大模型大数据攻城狮的专栏 8400

Spring源码深度解析:九、bean的获取③ - createBeanInstance

的流程图如下,让我们根据流程图一步一步的学习一下spring是如何创建bean的吧 文章目录:Spring源码分析:文章目录这篇文章应该是接着 Spring源码深度解析:八、bean的获取② - getSingleton 的继续分析过程。 本文主要是分析的方法是,功能是Spring 具体创建bean的过程。调用如下: 根据方法名就知道,是创建bean的实例,也就注定了这个方法的不平凡。下面就来一步一步的剖析他。具体源码如下: 我们可以看到:下面我们来解析代码。这部分的功能 : 若中设置了则使用 提供的bea

知行 847

把消息说清楚:OData V2 的 sap-message、错误体 errordetails 与 ABAP 端落地实践(Gateway Foundation / RAP)

OData V2消息机制解析:SAP业务系统的结构化通信设计 本文深入剖析了SAP系统中OData V2协议的消息传递机制。该设计通过双通道(成功时使用sap-message响应头,失败时采用error响应体)实现业务数据与提示信息的结构化分离,解决了企业级应用中"只返回业务数据"或"简单报错"的不足。文章详细解读了消息结构中的关键要素:target字段实现精准UI定位、severity级别控制交互流程、transition标记区分状态消息与过渡消息。同时揭示了SAP

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

2026年数学建模国赛B题无线电干扰源的快速自动定位与清除 论文详细解析

数学建模竞赛论文无线电干扰源的快速自动定位与清除2026 年高教社杯全国大学生数学建模竞赛 B 题完整求解论文交会定位、极大极小测点优化、自适应多频道搜索与定向源恢复的统一建模模型、算法、代码、图表与验证一体化交付本文研究圆形目标区域中多个未知无线电干扰源的快速检测、定位与清除问题,建立了由误差楔交会模型、角度观测信息模型、分层勘测模型、鲁棒射线交会模型和定向覆盖反馈模型组成的统一求解框架。模型同时覆盖题目中的四个子问题:多测向射线形成的多边形定位区域及直径、第二个测点的极大极小优选、全向源自动搜索清除策略

YOLO 358

BeanDefinition

BeanDefinition 是实现扩展机制的基础,它提供了对 Bean 实例化和依赖注入过程的描述,从而使得开发者可以通过实现相应的接口来扩展 Spring 的功能。BeanDefinition 是实现 AOP 的基础,它定义了需要被代理的 Bean 实例以及代理所需的相关信息,从而实现了 AOP 功能。BeanDefinition 是 Spring 中的一个核心概念,它用于描述一个 Bean 实例的属性和行为,并提供了创建和管理 Bean 实例的基础信息。

hay23455的博客 1668

SAP S/4HANA 中 RAP 业务对象接口的消费模式

本文探讨了SAP S/4HANA中RAP业务对象接口的消费模式,重点介绍了通过EML直接调用和CDS投影两种Clean Core开发路径。文章分析了BO Interface作为稳定契约的价值,并提供了BAdI集成、OData服务发布等实际场景案例,同时对比了OData V2/V4的技术选型考量,最后强调了ADT向导使用中的DCL权限注意事项。全文旨在帮助开发者构建升级友好的业务对象消费方案。

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

Spring IOC 容器初始化Bean执行流程源码分析

Spring IOC 容器初始化Bean执行流程源码分析 看了两篇文章,写的非常好,先记录一下,以后有时间再自己整理一遍学习笔记 首推这篇,前提是能耐下心来看:https://javadoop.com/post/spring-ioc 写的超级无敌的详细 想简单点的就看这个:https://blog.youkuaiyun.com/qq_34203492/article/details/83865450 有查看源码步骤,新手友好 ...

who__are__you的博客 452

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Spring的IOC容器初始化源码分析四:载入注解Bean

refresh方法中,调用注解解析bean的loadBeanDefinitions方法如下: public class AnnotationConfigWebApplicationContext extends AbstractRefreshableWebApplicationContext implements AnnotationConfigRegistry //载入注解Bean...

qq_28825857的博客 513

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

「Spring源码」Spring IOC 容器源码分析(一)

Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器。既然大家平时都要用到 Spring,怎么可以不好好了解 Spring 呢?阅读本文并不能让你成为 Spring 专家,不过一定有助于大家理解 Spring 的很多概念,帮助大家排查应用中和 Spring 相关的一些问题。 本文采用的源码版本是 4.3.11.RELEASE,算是 5.0.x 前比较新的版本了。为了降低难度,本文所说的所有的内容都是基于 xml 的配置的方式,实际使用已经很少人

爱写代码的程序员 264

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

从宏观角度分析Spring源码之IOC

今天是5月3号,烈日似火,热的让人喘不过气来。就在这个让人燥热的时刻我准备开始着手写Spring源码分析一系列文章。一是巩固自己的知识体系,二是分享一些技术心得给铁子们,让Spring技术原理通俗易懂的展现在大家面前,从此让世界上不再有不懂Spring原理的Java程序猿,让世界从此没有回答不上来的Spring技术面试。 这篇文章我们从Spring核心IOC切入,分析一下Spring中的IOC机...

Java技术分享 1136

Spring IOC容器源码分析(转)

文章目录引言BeanFactory 简介启动过程分析创建 Bean 容器前的准备工作创建 Bean 容器,加载并注册 BeanBean 容器实例化完成后准备 Bean 容器: prepareBeanFactory初始化所有的 singleton beans附录id 和 name配置是否允许 Bean 覆盖、是否允许循环依赖profile工厂模式生成 BeanFactoryBean初始化 Bean ...

qq_24095055的博客 490

从源码的角度分析@Lazy和@Scope对IOC容器初始化影响以及IOC的总结

在之前的文章中说过lazy、scope对spring ioc容器的初始化影响(Spring中Lazy、Scope注解对IOC容器Bean初始化的影响分析),但是没有具体深入的说,而是通过表面数据判断。另外就是之前也写过spring ioc容器初始化的源码分析(Spring IOC容器初始化基础过程源码了解),这里算是前两篇文章的续集,也是对其补充和做一个总结性的结论。 情景简介 这里就直接进入主题,分别使用@Lazy和@Scope("prototype")来修饰两个bean,不会再去做其他的解释,如果这些有

IT-CRUD 313

spring-IOC容器源码分析(一)bean初始化流程

在传统的开发步骤中,如果一个类依赖于另一个类的实例才能完成任务的话,都需要开发者手动new一个实例。之后手动设置到任务类中。但spring的出现,为我们提供了一种称为“依赖注入”(Dependency Inject)的机制。bean的实例化在spring container内部完成,开发者只需要从xml或java code来配置bean达到定制实例化bean。而且,可以让我们通过注解的方式,为...

weixin_34077371的博客 147

spring容器及bean加载机制源码解读

spring的容器加载机制分为提前加载和运行时动态加载,本文通过源码解读容器加载机制和bean加载机制。

淡淡吹风的专栏 382

Spring入门心经之第一章 IOC详解

我们继续深入源码,会发现在XmlBeanDefinitionReader类中可以看到doLoadBeanDefinitions()方法,这个方法主要作用是载入Bean定义资源文件,然后将Bean定义资源转换为Document对象,具体过程由documentLoader实现。// 创建文件解析器工厂// 创建文档解析器// 解析// 设置解析XML的校验try {" +throw pcex;

成功不可复制,努力值得期待 220

Spring IOC 容器源码分析

原文出处:https://javadoop.com/post/spring-iocSpring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器。既然大家平时都要用到 Spring,怎么可以不好好了解 Spring 呢?阅读本文并不能让你成为 Spring 专家,不过一定有助于大家理解 Spring 的很多概念,帮助大家排查应用中和 Sprin...

Java_fenxiang的博客 235

SpringBoot学习小结之IOC

前言 IOC,全称Inversion of Control,中文名控制反转,是Spring框架的基石。 Spring 发展至今,家族越来越庞大,有SpringBoot提供一站式开发,SpringCloud微服务开发等等,各种框架提供了各种各样的功能。例如:使用SpringMVC,自定义一个类,添加@Controller,@RequstMapping注解就能实现接收HTTP请求,其底层原理就是IOC。 IOC可以用于对象之间的解耦。它还有个别名,依赖注入(DI), DI是实现控制反转的方式。程序

十十办文武的博客 653

【Spring】IOC核心源码学习(二):容器初始化过程

【Spring】IOC核心源码学习(二):容器初始化过程博客分类: JavaEE设计模式开源框架springioc容器初始化过程bean创建过程aware  接上文 啃啃老菜: Spring IOC核心源码学习(一) ,本文将以 ClassPathXmlApplicationContext 这个容器的实现作为基础,学习容器的初始化过程。ClassPathXmlApplicationContext 

evilcry2013的博客 279

Spring源码解析Bean的创建过程

通过Spring源码解析,讲述Spring创建Bean的详细过程。

Dom点滴博客 748
上一篇: Spring bean定义解析源码分析
下一篇: Spring bean的作用域
爱艺欣聊编程
博客等级 码龄20年 122粉丝 50原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值