基本流程
完成了XML配置文件的解析,接下来就是对bean加载的探索。
//2.从ioc容器中获取bean实例
MyTestBean myTestBean = (MyTestBean) beanFactory.getBean("myTestBean");
跟踪进Spring的源码
public Object getBean(String name) throws BeansException {
return this.doGetBean(name, (Class)null, (Object[])null, false);
}
protected <T> T doGetBean(String name, Class<T> requiredType, final Object[] args, boolean typeCheckOnly) throws BeansException {
// 1. 提取对应的beanName
final String beanName = this.transformedBeanName(name);
// 2. 直接尝试从缓存获取或者singletonFactories中的ObjectFactory中获取
Object sharedInstance = this.getSingleton(beanName);
Object bean;
if (sharedInstance != null && args == null) {
if (this.logger.isDebugEnabled()) {
if (this.isSingletonCurrentlyInCreation(beanName)) {
this.logger.debug("Returning eagerly cached instance of singleton bean '" + beanName + "' that is not fully initialized yet - a consequence of a circular reference");
} else {
this.logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
// 3.返回对应的实例,有时候存储诸如BeanFactory的情况并不是直接返回实例本身而是返回指定方法返回的实例
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
} else {
// 4.
if (this.isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
BeanFactory parentBeanFactory = this.getParentBeanFactory();
// 5.如果beanDefinitionMap中也就是在所有已经加载的类中不包括beanName,则尝试从parentBeanFactory中检测
if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
String nameToLookup = this.originalBeanName(name);
// 递归到BeanFactory中寻找
if (args != null) {
return parentBeanFactory.getBean(nameToLookup, args);
}
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
// 如果不是仅仅做类型检查则是创建bean,这里要进行记录
if (!typeCheckOnly) {
this.markBeanAsCreated(beanName);
}
try {
// 6.将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition,如果指定BeanName是子Bean的话同时会合并父类的相关属性
final RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
this.checkMergedBeanDefinition(mbd, beanName, args);
String[] dependsOn = mbd.getDependsOn();
String[] var11;
// 7.若存在依赖则需要递归实例化依赖的bean
if (dependsOn != null) {
var11 = dependsOn;
int var12 = dependsOn.length;
for(int var13 = 0; var13 < var12; ++var13) {
String dep = var11[var13];
if (this.isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 缓存依赖调用
this.registerDependentBean(dep, beanName);
this.getBean(dep);
}
}
// 8.singleton模式的创建
if (mbd.isSingleton()) {
sharedInstance = this.getSingleton(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
try {
return AbstractBeanFactory.this.createBean(beanName, mbd, args);
} catch (BeansException var2) {
AbstractBeanFactory.this.destroySingleton(beanName);
throw var2;
}
}
});
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
// prototype模式的创建
var11 = null;
Object prototypeInstance;
try {
this.beforePrototypeCreation(beanName);
prototypeInstance = this.createBean(beanName, mbd, args);
} finally {
this.afterPrototypeCreation(beanName);
}
bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} else {
// 指定的scope是实例化bean
String scopeName = mbd.getScope();
Scope scope = (Scope)this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
AbstractBeanFactory.this.beforePrototypeCreation(beanName);
Object var1;
try {
var1 = AbstractBeanFactory.this.createBean(beanName, mbd, args);
} finally {
AbstractBeanFactory.this.afterPrototypeCreation(beanName);
}
return var1;
}
});
bean = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
} catch (IllegalStateException var21) {
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", var21);
}
}
} catch (BeansException var23) {
this.cleanupAfterBeanCreationFailure(beanName);
throw var23;
}
}
// 9.检查需要的类型是否符合bean的实际类型
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
try {
return this.getTypeConverter().convertIfNecessary(bean, requiredType);
} catch (TypeMismatchException var22) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Failed to convert bean '" + name + "' to required type '" + ClassUtils.getQualifiedName(requiredType) + "'", var22);
}
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
} else {
return bean;
}
}
- 转换对应beanName
在beanFactory.getBean(String name)
传入的参数,可能是别名,可能是beanName,也可能是FactoryBean,所以需要进行一系列的解析 - 尝试从缓存中加载单例
单例在Spring的同一个容器内只会被创建一次,后续再获取bean,就直接从单例缓存中获取了。如果获取不成功,则再次尝试从singletonFactories中加载。因为在创建bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,在Spring中创建bean的原则是不等bean创建完成就会创建bean的ObjectFactory提早曝光加入到缓存中,一旦下一个bean创建时候需要依赖上一个bean则直接使用ObjectFactory - bean的实例化
如果从缓存中得到了bean的原始状态,则需要对bean进行实例化。这里需要说明:缓存中记录的只是最原始的bean状态,并不一定是我们最终想要的bean。而getObjectForBeanInstance
就是完成这个工作的 - 原型模式的依赖检查
只有在单例情况下才会尝试解决循环依赖,如果存在A中有B的属性,B中有A的属性,那么当依赖注入的时候,就会产生A还未创建完的时候因为对于B的创建再次返回创建A,造成循环依赖,也就是情况isPrototypeCurrentlyInCreation(beanName)
判断true - 检查parentBeanFactory
如果缓存没有数据的话直接转到父类工程上去加载 - 将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition
因为从XML配置文件中读取到的Bean信息是存储在GernericBeanDefinition中的,但是所有的Bean后续处理都是针对于RootBeanDefinition的,所以这里需要进行一个转换,转换的同时如果父类bean不为空的话,则会一并合并父类的属性 - 寻找依赖
因为bean的初始化过程中很可能会用到某些属性,而某些属性很可能是动态配置的,并且配置成依赖于其他的bean,那么这个时候就有必要先加载依赖的bean,所以,在Spring的加载顺序中,在初始化某一个bean的时候首先会初始化这个bean所对应的依赖 - 针对不同的scope进行bean的创建
Spring中存在着不同的备scope,其中默认的是singleton,但是还有些其他的配置诸如prototype、request之类的。在这个步骤中,Spring会根据不同的配置进行不同的初始化策略 - 类型转换
将生产的bean,转换为参数requiredType的类型。
FactoryBean
一般情况下,Spring通过反射机制利用bean的class属性指定实现类来实例化bean。
除此之外,Spring还提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化bean的逻辑。FactoryBean接口对于Spring来说很重要,它隐藏了实例化一些复杂bean的细节。
public interface FactoryBean<T> {
// 返回由FactoryBean创建的bean实例
// 如果isSingleton()返回true,则该实例会放到Spring容器中单实例缓存池中
T getObject() throws Exception;
// 返回FactoryBean创建的bean类型
Class<?> getObjectType();
// 返回由FactoryBean创建的bean实例的作用域是singleton还是prototype
boolean isSingleton();
}
当配置文件中<bean>
的class属性配置的实现类是FactoryBean时,通过getBean()方法返回的不是FactoryBean本身,而是FactoryBean.getObject()方法所返回的对象,相当于FactoryBean.getObject()代理了getBean()方法
public class Car {
private int maxSpeed;
private String brand;
private double price;
// get/set
}
如果使用传统方式配置Car的时候,Car的每个属性分别对应一个<property>
元素标签
如果用FactoryBean的方式实现就会灵活一些
public class CarFactoryBean implements FactoryBean<Car> {
private String carInfo;
public Car getObject() throws Exception {
Car car = new Car();
String[] infos = carInfo.split(",");
car.setBrand(infos[0]);
car.setMaxSpeed(Integer.valueOf(infos[1]));
car.setPrice(Double.valueOf(infos[2]));
return car;
}
public Class<Car> getObjectType() {
return Car.class;
}
public boolean isSingleton() {
return false;
}
public String getCarInfo() {
return this.carInfo;
}
public void setCarInfo(String carInfo) {
this.carInfo = carInfo;
}
}
有了这个CarFactoryBean后,就可以如下配置了
<bean id="car" class="com.whyalwaysmea.factorybean.CarFactoryBean" >
<property name="carInfo" value="超级跑车,400,20000000" />
</bean>
当调用getBean("car")
时,Spring通过反射机制发现CarFactoryBean实现了FactoryBean的接口,这时Spring容器就调用接口方法CarFactoryBean.getObject()方法返回。
如果希望获取CarFacoryBean的实例,则调用getBean("&car")