当
BeanDefinition
注册完毕以后,
Spring Bean
工厂就可以随时根据需要进行实例化了。对于
XmlBeanFactory
来说,实例化默认是延迟进行的,也就是说在
getBean
的时候才会;而对于
ApplicationContext
来说,实例化会在容器启动后通过
AbstractApplicationContext
中
reflash
方法自动进行,主要经过方法链:
reflesh()
à
finishBeanFactoryInitialization
(factory)
à
DefaultListableBeanFactory.preInstantiateSingletons
(),
在这里会根据注册的
BeanDefinition
信息依此调用
getBean(beanName)
。而真正实例化的逻辑和
BeanFactory
是“殊途同归”的,所有有关
Bean
实例化都可以从
getBean(beanName)
入手。
AbstractBeanFactory
有四个
getBean
的重载方法,不管调用哪个方法最终都是会调用另一个
doGetBean
方法:
public Object getBean(String name) throws BeansException {
return getBean(name, null, null);
}
public Object getBean(String name, Class requiredType) throws BeansException {
return getBean(name, requiredType, null);
}
public Object getBean(String name, Object[] args) throws BeansException {
return getBean(name, null, args);
}
/**
* Return an instance, which may be shared or independent, of the specified bean.
* @param name the name of the bean to retrieve
* @param requiredType the required type of the bean to retrieve
* @param args arguments to use if creating a prototype using explicit arguments to a
* static factory method. It is invalid to use a non-null args value in any other case.
* @return an instance of the bean
* @throws BeansException if the bean could not be created
*/
public Object getBean(String name, Class requiredType, Object[] args) throws BeansException {
return doGetBean(name, requiredType, args, false);
}
doGetBean方法比较长一点,见下面注释:
protected Object doGetBean(
final String name, final Class requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
//bean name处理,去除FactoryBean前缀等
final String beanName = transformedBeanName(name);
Object bean = null;
//先从singleton缓存中查看是否已经实例化过该Bean,根据是否有缓存分为两个分支分别处理
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// 分支一,若缓存中获取到了并且该BeanDefinition信息表明该bean是singleton的,直接将获取到的缓存Bean
//(有可能是半成品)交给getObjectForBeanInstance处理
/*.........省略logger部分代码............*/
//调用getObjectForBeanInstance处理
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}else {
// 分之二:没有缓存,则需要从头实例化该bean
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);}
// 检查BeanDefinition是否在当前工厂或父工厂
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (args != null) {
// 父工厂getBean
return parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}
//将bean加入“正在创建”的集合,完成后会remove,对应afterSingletonCreation/afterPrototypeCreation方法
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 解决依赖关系,将依赖的bean提前实例化
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (int i = 0; i < dependsOn.length; i++) {
String dependsOnBean = dependsOn[i];
getBean(dependsOnBean);
registerDependentBean(dependsOnBean, beanName);
}
}
// 这里又需要根据bean的类型分为三种情况:singleton、prototype、request/session
if (mbd.isSingleton()) {
//通过自定义ObjectFactory实例化Bean,此结果可能是半成品(是FactoryBean等)
sharedInstance = getSingleton(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
try {
//真正实例化装配的逻辑在createBean方法中
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方法处理
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
//真正实例化装配的逻辑在createBean方法中
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
//上一步半成品的Bean交给getObjectForBeanInstance方法处理
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
//request、session 的bean
String scopeName = mbd.getScope();
final Scope scope = (Scope) this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
//真正实例化装配的逻辑在createBean方法中
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
}
});
//上一步半成品的Bean交给getObjectForBeanInstance方法处理
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; " +
"consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
}
// Check if required type matches the type of the actual bean instance.
if (requiredType != null && bean != null &&
!requiredType.isAssignableFrom(bean.getClass())) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return bean;
}
通过注释,可以整理出较清晰的逻辑: 检查Bean缓存,已经有缓存的Bean对象(有可能是半成品)则交给getObjectForBeanInstance方法处理;否则先根据Bean的生命周期类型分别实例化,每种情况大致都分两步,第一步都交给createBean方法生产一个半成品的bean对象,然后同样是将半成品的bean交给getObjectForBeanInstance方法处理。所以关键的逻辑就在这两个方法了,下面以singleton为例看看这两个方法,具体代码:
sharedInstance = getSingleton(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
getSingleton方法做的工作主要是实例化bean之前和之后回调beforeSingletonCreation/afterSingletonCreation、实例化bean、以及将bean对象缓存起来,具体实例化bean是通过回调匿名对象ObjectFactory的getObject方法实现的,从代码中明显看到主要是createBean方法。这里要特别注意下,缓存的bean对象是createBean生产的,这个方法生产的bean只是“半成品”,有可能是个factoryBean,真正返回给客户端使用的bean还必须进行下一步getObjectBeanInstance处理。所以缓存的bean对象可以认为是“半成品”,这就和前文代码中的注释相呼应(缓存中若取到了bean,必须进行getObjectBeanInstance处理)。
对createBean方法实际上在“Spring IOC之BeanFactory”中已经有过分析,所以流程就不再简单重复,直接按步骤:
1. resolveBeanClass(mbd, beanName);
2. mbd.prepareMethodOverrides();//Spring IOC之BeanFactory已有解释,不重复
3. Object bean = resolveBeforeInstantiation(beanName, mbd);
解释下,这里主要对于一些代理的bean做处理,我们平常经常会配置一些AOP模块,对于需要aop增强的bean实际上都会经过spring代理织入,而这些bean的代理逻辑应该就在这里处理了,具体看看这部分的代码:
/**
* Apply before-instantiation post-processors, resolving whether there is a
* before-instantiation shortcut for the specified bean.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @return the shortcut-determined bean instance, or <code>null</code> if none
*/
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 = Boolean.valueOf(bean != null);
}
return bean;
}
/**
* Apply InstantiationAwareBeanPostProcessors to the specified bean definition
* (by class and name), invoking their <code>postProcessBeforeInstantiation</code> methods.
* <p>Any returned object will be used as the bean instead of actually instantiating
* the target bean. A <code>null</code> return value from the post-processor will
* result in the target bean being instantiated.
* @param beanClass the class of the bean to be instantiated
* @param beanName the name of the bean
* @return the bean object to use instead of a default instance of the target bean, or <code>null</code>
* @throws BeansException if any post-processing failed
* @see InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
*/
protected Object applyBeanPostProcessorsBeforeInstantiation(Class beanClass, String beanName)
throws BeansException {
for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext();) {
BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();
if (beanProcessor instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) beanProcessor;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
//AbstractAutoProxyCreator
public Object postProcessBeforeInstantiation(Class beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName);
if (!this.targetSourcedBeans.contains(cacheKey)) {
if (this.advisedBeans.contains(cacheKey) || this.nonAdvisedBeans.contains(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass, beanName) || shouldSkip(beanClass, beanName)) {
this.nonAdvisedBeans.add(cacheKey);
return null;
}
}
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
this.targetSourcedBeans.add(beanName);
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
对于AutoProxy部分代码要放到spring aop部分中去写了,这里只要明白如果是代理bean在postProcessBeforeInstantiation阶段会返回一个proxy,这时候bean已经算是实例化好了,再调用applyBeanPostProcessorsAfterInitialization即BeanPostProcessor.postProcessAfterInitialization回调进行属性的设置。最后的结果就可以返回bean对象了,只是一个Proxy Bean Object.
4. Object beanInstance = doCreateBean(beanName, mbd, args);//如果是代理bean就不会走到这一步
解释下:对于非代理的bean,基本上实例化的逻辑就在doCreateBean这个方法了,这个方法在“Spring IOC之BeanFactory”中已经有过分析,所以不重复解释了,贴一个bean生命周期的流程图做为createBean方法的结尾:
上图不是我所画,来源于spring IOC容器介绍。
半成品出来之后还需要调用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;
}
开始部分是逻辑检查,是否是FactoryBean,后面是从factoryBean中获取实际的Bean。获取bean也是先检查缓存,没有缓存再getObjectFromFactoryBean获取,详细再doGetObjectFromFactoryBean方法中,最后将获取的bean缓存起来。代码就不贴了。
- 大小: 41 KB
分享到:
相关推荐
在本文中,我将讨论棘手的Spring Boot bean定义覆盖机制。 为了使您对该主题更加清楚,让我们从小测验开始。请看下一个简单的例子。 因此,我们有2种配置,它们使用名称beanName实例化bean,在主应用程序中,我们仅...
Spring BeanDefinition 类图结构,形象展示Spring是如何存储Bean信息的。通过类图和源码更好的理解Spring BeanDefinition存储结构
- ChildBeanDefinition则用于表示从父BeanDefinition派生出来的Bean定义,它会继承父定义并可以覆盖或添加额外的属性。 此外,BeanDefinition还涉及到的类和接口有: - AttributeAccessor接口,允许在任意对象上...
BeanDefinition可以设置自动装配,通过设置autowireCandidate属性可以指定是否可以自动装配到其他Bean中。 ### BeanDefinition的主要接口 BeanDefinition的主要接口有两个:AttributeAccessor和...
在实际应用中,Spring的BeanDefinition解析涉及到BeanDefinitionReader和BeanDefinitionRegistry两个组件。BeanDefinitionReader负责读取XML、Java配置或注解信息并创建BeanDefinition对象。BeanDefinitionRegistry...
XmlBeanDefinitionReader 是一个用于从 XML 文件中读取 BeanDefinition 的读取器。它的 loadBeanDefinitions 方法是核心实现方法。 public int loadBeanDefinitions(EncodedResource encodedResource) throws ...
总结来说,Spring的BeanDefinition装载过程涉及了从XML配置文件解析、BeanDefinition创建、BeanFactory初始化到Bean实例化的多个步骤。在学习源码时,应重点关注BeanDefinition的创建、加载和实例化过程,理解Spring...
在BeanFactory篇中,我们了解到BeanFactory在启动时会从配置元信息(通常是XML文件)中读取BeanDefinition,并将它们注册到BeanDefinitionRegistry中。这个过程是通过一系列的委托和解析机制完成的。 当我们运行...
Spring Bean Factory, Bean definition 结构图;processOn
首先,我们需要从 beanDefinitionMap 中通过 beanName 获得 BeanDefinition,然后从 BeanDefinition 中获得 beanClassName,最后通过反射初始化 beanClassName 的实例 instance。构造函数从 BeanDefinition 的 ...
在Spring容器启动时,会通过BeanDefinitionReader读取XML配置文件或通过AnnotationConfigApplicationContext读取注解配置,将BeanDefinition注册到BeanDefinitionRegistry中。注册过程包括解析配置源,创建Bean...
BeanDefinition接口提供了获取和设置这些属性的方法,例如getBeanClassName()用于获取Bean的类名,setParentName()用于设置父BeanDefinition的名称,isSingleton()检查Bean是否为单例,等等。通过BeanDefinition,...
- **Spring的解析过程**:Spring利用了强大的类路径扫描工具,结合注解处理器来解析注解,并将相关信息存储到BeanDefinition中。 - **MetadataReader读取信息后的处理**:`MetadataReader`读取到类信息、注解信息...
这些BeanDefinition被注册到Spring的BeanDefinitionRegistry中,形成一个Bean的元数据集合。 3. **Bean的作用域**: 在注册时,Spring会根据@Bean、@Scope等注解确定Bean的作用域。默认情况下,Bean是单例...
#### 创建BeanDefinition 接下来,使用`BeanDefinitionBuilder`来构建Bean的定义。`BeanDefinitionBuilder`提供了简洁的API来定义一个Bean的所有属性和行为,包括它的类型、依赖注入的属性等。在这个例子中,我们...
`ConfigurationClassBeanDefinitionReader`这个类负责从`ConfigurationClass`读取模型并创建BeanDefinition。在这个过程中,Spring会遍历所有的`ConfigurationClass`,将它们转换为BeanDefinition。通常情况下,一个...
import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support....
1、<bean>标签主要用来进行Bean定义; 2、alias用于定义Bean别名的;...这两种方式都是通过调用Bean Definition Reader 读取Bean定义,内部实现没有任何区别。标签可以放在下的任何位置,没有顺序关系。
在 Spring 中,Bean 定义是由 `BeanDefinition` 接口来表示的,它包含了关于 Bean 的所有元信息。 1. **BeanDefinition**: - **Bean 类名**:指定了 Bean 对应的具体实现类,不能是抽象类或接口。 - **Bean 行为...
- 当Spring容器启动时,它首先读取配置文件,解析Bean的定义,并创建一个BeanDefinition对象,该对象包含了Bean的所有信息,如类名、属性、依赖等。 - 如果有`@Component`注解的类,Spring会通过组件扫描找到并...