前言
本系列全部基于 Spring 5.2.2.BUILD-SNAPSHOT 版本。因为 Spring 整个体系太过于庞大,所以只会进行关键部分的源码解析。
本篇文章主要介绍 Spring IoC 容器是怎么加载 bean 的。
正文
我们先看一下Spring IoC BeanDefinition 的加载和注册一文中获取 bean 的实例代码:
Copy
public class BeanDefinitionDemo {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions("META-INF/bean-definition.xml");
User user = beanFactory.getBean("user", User.class);
System.err.println(user);
}
}
通过 beanFactory.getBean() 这个方法就获取了在 XML 中定义的 bean,下面我们就重点分析这个方法背后做了什么操作。
在正式开始之前,我们先了解一下 FactoryBean 及其用法。
FactoryBean 介绍#
FactoryBean 接口对于 Spring 框架来说占有重要的地位,Spring 自身就提供了70多个 FactoryBean 的实现。它们隐藏了一下复杂 bean 的细节,给上层应用带来了便利。下面是该接口的定义:
Copy
public interface FactoryBean {
// 返回由FactoryBean创建的bean实例,如果isSingleton()返回true,
// 则该实例会放到Spring容器中单例缓存池中
@Nullable
T getObject() throws Exception;
// 返回FactoryBean创建的bean类型
@Nullable
Class<?> getObjectType();
// 返回由FactoryBean创建的bean实例的作用域是singleton还是prototype
default boolean isSingleton() {
return true;
}
}
当配置文件中 的 class 属性配置的实现类时 FactoryBean 时,通过 getBean() 返回的不是 FactoryBean 本身,而是 FactoryBean#getObject() 所返回的对象,相当于 FactoryBean#getObject() 代理了 getBean()。下面用简单的代码演示一下:
首先定义一个 Car 实体类:
Copy
public class Car {
private Integer maxSpeed;
private String brand;
private Double price;
public Integer getMaxSpeed() {
return maxSpeed;
}
public void setMaxSpeed(Integer maxSpeed) {
this.maxSpeed = maxSpeed;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public Double getPrice() {
return price;
}
public void setPrice(Double price) {
this.price = price;
}
}
上面的实体类,如果用传统方式配置,每一个属性都会对应一个 元素标签。如果用 FactoryBean 的方式实现就会灵活一点,下面通过逗号分隔的方式一次性的为 Car 的所有属性配置值。
Copy
public class CarFactoryBean implements FactoryBean {
private String carInfo;
@Override
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;
}
@Override
public Class<?> getObjectType() {
return Car.class;
}
@Override
public boolean isSingleton() {
return true;
}
public String getCarInfo() {
return carInfo;
}
public void setCarInfo(String carInfo) {
this.carInfo = carInfo;
}
}
接下来,我们在 XML 中配置。
Copy
最后看下测试代码和运行结果:
Copy
@Test
public void factoryBeanTest() {
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions(“META-INF/factory-bean.xml”);
Car car = beanFactory.getBean(“car”, Car.class);
System.out.println(car);
CarFactoryBean carFactoryBean = beanFactory.getBean("&car", CarFactoryBean.class);
System.out.println(carFactoryBean);
}
可以看到如果 beanName 前面加上 & 获取的是 FactoryBean 本身,不加获取的 getObject() 返回的对象。
FactoryBean 的特殊之处在于它可以向容器中注册两个 bean,一个是它本身,一个是 FactoryBean.getObject() 方法返回值所代表的 bean。
bean 的加载#
AbstractBeanFactory#getBean#
Copy
public T getBean(String name, Class requiredType) throws BeansException {
// 调用doGetBean方法(方法以do开头实际做操作的方法)
return doGetBean(name, requiredType, null, false);
}
/**
-
@param name bean的名称
-
@param requiredType bean的类型
-
@param args 显示传入的构造参数
-
@param typeCheckOnly 是否仅仅做类型检查
*/
protected T doGetBean(final String name, @Nullable final Class requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
// 获取bean的实际名称,见下文详解
final String beanName = transformedBeanName(name);
Object bean;// 直接尝试从缓存获取或 singletonFactories 中的 ObjectFactory 中获取,见下文详解
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// 检查bean是否是FactoryBean的实现。不是直接返回bean,
// 是的话首先检查beanName是否以&开头,如果是返回FactoryBean本身,
// 不是调用FactoryBean#getObject()返回对象,见下文详解
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}else {
// 只有在单例情况下才会去尝试解决循环依赖,原型模式下,如果存在A中有
// B属性,B中有A属性,那么当依赖注入时,就会产生当A还未创建完的时候
// 对于B的创建而在此返回创建A,造成循环依赖
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}// 检查当前bean的BeanDefinition是否在当前的bean工厂中, // 不在递归调用父工厂的getBean()去获取bean BeanFactory parentBeanFactory = getParentBeanFactory(); if (parentBeanFactory != null && !containsBeanDefinition(beanName)) { String nameToLookup = originalBeanName(name); if (parentBeanFactory instanceof AbstractBeanFactory) { return ((AbstractBeanFactory) parentBeanFactory).doGetBean( nameToLookup, requiredType, args, typeCheckOnly); } else if (args != null) { return (T) parentBeanFactory.getBean(nameToLookup, args); } else if (requiredType != null) { return parentBeanFactory.getBean(nameToLookup, requiredType); } else { return (T) parentBeanFactory.getBean(nameToLookup); } } // 如果不是仅仅做类型检查,则是创建bean,这里要进行记录 if (!typeCheckOnly) { // 记录bean已经创建过 markBeanAsCreated(beanName); } try { // 合并BeanDefinition,见下文详解 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName); checkMergedBeanDefinition(mbd, beanName, args); // 实例化bean前先实例化依赖bean,也就是depends-on属性中配置的beanName String[] dependsOn = mbd.getDependsOn(); if (dependsOn != null) { for (String dep : dependsOn) { // 检查是否循环依赖,即当前bean依赖dep,dep依赖当前bean,见下文详解 if (isDependent(beanName, dep)) { throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'"); } // 将dep和beanName的依赖关系放入到缓存中,见下文详解 registerDependentBean(d