本文介绍bean加载,对应代码:
Cat cat = (Cat) bf.getBean("testCat");
Spring对这行代码的具体实现大致步骤如下:
1. 转换beanName
为什么需要转换beanName?因为传入的参数name不一定是真实的beanName,可能是alias,也可能是FactoryBean,所以需要:
2. 尝试从缓存中加载单例
单例在Spring的同一个容器内只会被创建一次,后续再获取bean,就直接从单例缓存中获取了。
3. bean的实例化
如果从缓存中取到了的bean的原始状态,则需要对bean进行实例化。缓存中记录的是最原始的bean状态,不一定是我们最终想要的bean。举个例子,比如从缓存中获得的是工厂bean的初始状态,我们真正需要的是factory-method方法中返回的bean。
4. GenericBeanDefinition转换为RootBeanDefinition
从XML配置文件中读取到的Bean信息是存储在GenericBeanDefinition中的,但是所有的Bean后续处理都是针对于RootBeanDefinition的,所以需要转换。
5. 寻找依赖
在Spring的加载顺序中,在初始化某一个bean的时候,首先会初始化这个bean所对应的依赖。
6. 针对不同scope进行bean的创建
bean scope可以是prototype、request、singleton等,Spring在这个步骤根据不同的scope进行不同的初始化策略。
7. 类型转换
将返回的bean转换为requiredType指定的类型。
选最重要的第6步细说。
常规bean的创建在AbstractAutowireCapableBeanFactory的doCreateBean方法中。为了能够体现主要逻辑,去除日志、异常的处理、循环依赖的处理:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
// 如果是单例,首先清除缓存
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//根据指定bean使用对应的策略创建新的实例,如:工厂方法、构造函数自动注入、简单初始化
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
//应用MergedBeanDefinitionProcessor
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
mbd.postProcessed = true;
}
}
// Initialize the bean instance.
Object exposedObject = bean;
//对bean进行填充,将各个属性注入
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
// Register bean as disposable.
registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
}
步骤很清晰:
1. 如果是单例,首先清除缓存;
2. 实例化bean,将BeanDefinition转换为BeanWrapper;
实例化bean的策略有:
3.属性填充,将所有属性填充到bean的实例中;
4.注册DisposableBean
如果配置了destroy-method方法,这里需要注册以便于在销毁时候使用。
进一步来解析第2步和第三步。
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) {
// Make sure bean class is actually resolved at this point.
Class> beanClass = resolveBeanClass(mbd, beanName);
// 如果工厂方法不为空则使用工厂方法初始化策略
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 需要根据参数解析构造函数
Constructor>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
//使用默认构造函数构造
return instantiateBean(beanName, mbd);
}
1.如果RootBeanDefinition中存在factoryMethodName属性,或者说在配置文件中配置了factory-method,那么Spring会尝试使用instantiateUsingFactoryMethod方法根据RootBeanDefiniton中的配置生成bean的实例。
2.解析构造函数并进行构造函数的实例化。因为一个bean对应的类中可能会有多个构造函数,而每个构造函数的参数不同,Spring在根据参数及类型去判断最终会使用哪个构造函数进行实例化。
3.如果需要使用构造函数实例化,那么就根据实例化策略、得到的构造函数、以及构造函数的参数(BeanDefinition中)实例化bean;如果是使用默认的构造函数实例化,就直接调用实例化策略进行实例化。
public Object instantiate(RootBeanDefinition beanDefinition, String beanName, BeanFactory owner) {
// 如果有需要覆盖或者动态替换的方法,需要使用cglib进行动态代理;因为动态可以在创建代理的同时将动态方法织入类中;
//如果没有动态需要改变的方法,直接反射就可以了
if (beanDefinition.getMethodOverrides().isEmpty()) {
Constructor> constructorToUse;
synchronized (beanDefinition.constructorArgumentLock) {
constructorToUse = (Constructor>) beanDefinition.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
final Class> clazz = beanDefinition.getBeanClass();
constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
beanDefinition.resolvedConstructorOrFactoryMethod = constructorToUse;
}
}
return BeanUtils.instantiateClass(constructorToUse);
}
else {
return instantiateWithMethodInjection(beanDefinition, beanName, owner);
}
}
BeanUtils的instantiateClass方法:
public static T instantiateClass(Constructor<T> ctor, Object... args) {
ReflectionUtils.makeAccessible(ctor);
return ctor.newInstance(args);
}
属性注入发生在AbstractAutowireCapableBeanFactory的populateBean方法。
这个方法中有两个需要关注的点:
1.当bean配置了autowire属性,那么会根据注入类型(byName/byType),提取依赖的bean,并统一存入PropertyValues中;
2.将所有PropertyValues中的属性填充至BeanWrapper中;
protected void autowireByName(
String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
//寻找bw中需要依赖注入的属性
String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
for (String propertyName : propertyNames) {
if (containsBean(propertyName)) {
// 使用当前Bean的属性名作为Bean的名字,向IOC容器索取Bean,然后把从IOC容器中取到的Bean,设置到当前Bean的属性中去;
//递归初始化相关bean
Object bean = getBean(propertyName);
pvs.add(propertyName, bean);
registerDependentBean(propertyName, beanName);
}
}
}
对于autowireByName,首先通过反射机制从当前Bean中得到需要注入的属性名,然后使用这个属性名向Spring容器申请与之同名的Bean,这样实际又触发了另一个Bean的生成和依赖注入的过程。
autowireByType
首先也是寻找bw(BeanWrapper )需要依赖注入的属性,然后遍历这些属性寻找类型匹配的bean。
applyPropertyValues
获取的属性以PropertyValues形式存在,还没有应用到实例化bean中,这一工作在AbstractAutowireCapableBeanFactory中。
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
if (mpvs.isConverted()) {
// 如果mpvs中的值已经被转换为对应的类型,那么可以直接设置到beanwrapper中
bw.setPropertyValues(mpvs);
return;
}
original = mpvs.getPropertyValueList();
}
else {
// 如果mpvs不是MutablePropertyValues封装的类型,直接使用原始的属性获取
original = Arrays.asList(pvs.getPropertyValues());
}
// 获取对应的解析器
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
List deepCopy = new ArrayList(original.size());
boolean resolveNecessary = false;
//遍历属性,将属性转换为对应类的对应属性的类型
for (PropertyValue pv : original) {
if (pv.isConverted()) {
deepCopy.add(pv);
}
else {
String propertyName = pv.getName();
Object originalValue = pv.getValue();
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
Object convertedValue = resolvedValue;
boolean convertible = bw.isWritableProperty(propertyName) &&
!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
if (convertible) {
convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
}
if (resolvedValue == originalValue) {
if (convertible) {
pv.setConvertedValue(convertedValue);
}
deepCopy.add(pv);
}
else if (convertible && originalValue instanceof TypedStringValue &&
!((TypedStringValue) originalValue).isDynamic() &&
!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
pv.setConvertedValue(convertedValue);
deepCopy.add(pv);
}
else {
resolveNecessary = true;
deepCopy.add(new PropertyValue(pv, convertedValue));
}
}
}
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}