《JavaPub源码》
Spring IOC 源码分析之深入理解 IOC
如果你要学习,最好的时间是十年前,其次就是当下。
在Spring框架中,IOC(Inversion of Control,控制反转)是其中最重要的一个核心概念。它的实现方式是通过BeanFactory和ApplicationContext等容器来管理对象的创建、依赖注入、生命周期等等。
下面,我们将通过分析Spring的源码,来深入理解IOC的实现原理
BeanFactory接口
在Spring的IOC容器中,BeanFactory是最基本的容器接口。它定义了IOC容器的基本行为,包括获取Bean、销毁Bean等操作。
public interface BeanFactory {
Object getBean(String name) throws BeansException;
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
<T> T getBean(Class<T> requiredType) throws BeansException;
boolean containsBean(String name);
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException;
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
String[] getAliases(String name);
}
上述接口中,最核心的方法是 getBean()
方法,它通过Bean的名称或类型,返回对应的Bean对象。在Spring IOC的实现中,getBean()
方法是通过BeanFactory实现的,我们来看一下BeanFactory的默认实现类:DefaultListableBeanFactory。
DefaultListableBeanFactory
DefaultListableBeanFactory是Spring IOC容器的默认实现类。它实现了BeanFactory接口,并提供了Bean的定义、注册、获取等操作。
在DefaultListableBeanFactory中,最核心的是BeanDefinition对象。它是Spring IOC容器中的核心数据结构,表示一个Bean的定义信息,包括Bean的类名、构造方法、属性、依赖等等。下面是BeanDefinition接口的定义:
public interface BeanDefinition {
String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
String getBeanClassName();
void setBeanClassName(String beanClassName);
String getScope();
void setScope(String scope);
boolean isSingleton();
boolean isPrototype();
String getFactoryMethodName();
void setFactoryMethodName(String factoryMethodName);
String getFactoryBeanName();
void setFactoryBeanName(String factoryBeanName);
String[] getDependsOn();
void setDependsOn(String... dependsOn);
boolean isLazyInit();
void setLazyInit(boolean lazyInit);
ConstructorArgumentValues getConstructorArgumentValues();
MutablePropertyValues getPropertyValues();
boolean isAutowireCandidate();
void setAutowireCandidate(boolean autowireCandidate);
}
上述接口中,最核心的是 getBeanClassName()
和 getPropertyValues()
方法。 getBeanClassName()
返回Bean的类名,getPropertyValues()
返回Bean的属性值。在DefaultListableBeanFactory中,BeanDefinition是在DefaultListableBeanFactory中,BeanDefinition是通过Map来存储的,其中key是Bean的名称,value是对应的BeanDefinition对象。具体实现如下:
// 搜索 JavaPub,Spring 源码讲解。
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
// 存储BeanDefinition的Map
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
// BeanDefinition注册接口的实现方法
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
synchronized (this.beanDefinitionMap) {
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
if (!beanDefinition.equals(existingDefinition)) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(),
beanName, "Definition of bean '" + beanName + "' differs from existing " +
"definition for the same bean name. " + "Consider deleting or renaming the existing " +
"bean definition with the same name.");
}
}
else {
this.beanDefinitionMap.put(beanName, beanDefinition);
this.frozenBeanDefinitionNames = null;
}
}
}
// BeanDefinition获取接口的实现方法
@Override
public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
Assert.hasText(beanName, "Bean name must not be empty");
BeanDefinition bd = this.beanDefinitionMap.get(beanName);
if (bd == null) {
throw new NoSuchBeanDefinitionException(beanName);
}
return bd;
}
// 根据Bean名称获取Bean对象
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
// 根据Bean类型获取Bean对象
@Override
public <T> T getBean(Class<T> requiredType) throws BeansException {
return doGetBean(requiredType.getName(), requiredType, null, false);
}
// 根据Bean名称和类型获取Bean对象
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return doGetBean(name, requiredType, null, false);
}
// 核心方法,通过Bean名称或类型获取Bean对象
protected <T> T doGetBean(final String name, final Class<T> requiredType,
final Object[] args, boolean typeCheckOnly) throws BeansException {
// 根据名称或类型解析BeanDefinition对象
final BeanDefinition beanDefinition = getBeanDefinition(name);
// 根据BeanDefinition对象创建Bean实例
Object bean = createBean(name, beanDefinition, args);
// 对Bean实例进行依赖注入
populateBean(beanName, beanDefinition, bean);
// 对Bean实例进行初始化
initializeBean(beanName, bean, beanDefinition);
// 返回Bean实例
return (T) bean;
}
}
在DefaultListableBeanFactory中,Bean的创建、依赖注入和初始化等操作都是在doGetBean()方法中完成的。接下来,我们将重点介绍Bean的创建和依赖注入过程。
Bean
Bean的创建过程
在DefaultListableBeanFactory中,Bean的创建是通过createBean()方法完成的,具体实现如下:
protected Object createBean(final String beanName, final BeanDefinition beanDefinition, final Object[] args) {
// 创建Bean实例
Object beanInstance = createBeanInstance(beanDefinition, beanName, args);
// 设置Bean实例的Class属性
Class<?> beanType = beanInstance.getClass();
if (!beanType.equals(Object.class)) {
beanDefinition.setBeanClass(beanType);
}
// 对Bean实例进行属性赋值和方法注入
applyPropertyValues(beanName, beanDefinition, beanInstance);
// 处理Aware接口的回调
invokeAwareMethods(beanName, beanInstance);
// Bean后处理器的前置处理
Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(beanInstance, beanName);
// 调用Bean实例的初始化方法
try {
invokeInitMethods(beanName, wrappedBean, beanDefinition);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Invocation of init method failed", ex);
}
// Bean后处理器的后置处理
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
// 返回Bean实例
return wrappedBean;
}
在createBean()方法中,首先通过createBeanInstance()方法创建Bean实例,然后设置Bean实例的Class属性、对Bean实例进行属性赋值和方法注入、处理Aware接口的回调、调用Bean实例的初始化方法,最后通过Bean后处理器进行前置处理和后置处理,最终返回Bean实例。
Bean的依赖注入过程
在DefaultListableBeanFactory中,Bean的依赖注入是通过applyPropertyValues()方法完成的,具体实现如下:
protected void applyPropertyValues(String beanName, BeanDefinition beanDefinition, Object bean) {
try {
// 对Bean实例进行属性赋值和方法注入
PropertyValues pvs = beanDefinition.getPropertyValues();
if (pvs != null) {
for (PropertyValue pv : pvs.getPropertyValues()) {
String propertyName = pv.getName();
Object originalValue = pv.getValue();
Object resolvedValue = resolveValueIfNecessary(beanName, beanDefinition, propertyName, originalValue);
BeanWrapper bw = new BeanWrapperImpl(bean);
bw.setPropertyValue(propertyName, resolvedValue);
}
}
}
catch (BeansException ex) {
throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
}
}
在applyPropertyValues()方法中,首先获取BeanDefinition对象的PropertyValues属性,然后遍历其中的PropertyValue对象,获取属性名称和属性值,并通过resolveValueIfNecessary()方法解析属性值,最后通过BeanWrapperImpl对Bean实例进行属性赋值。
在属性赋值过程中,如果属性值是一个引用类型,会尝试进行自动装配。具体实现如下:
protected Object resolveValueIfNecessary(String beanName, BeanDefinition beanDefinition, String propertyName,
Object originalValue) {
if (originalValue instanceof BeanDefinitionHolder) {
// 如果属性值是一个BeanDefinitionHolder对象,说明属性是一个引用类型
BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) originalValue;
Object ref = resolveReference(bdHolder, beanName, propertyName);
if (ref instanceof NullBean) {
return null;
}
return ref;
}
else if (originalValue instanceof RuntimeBeanReference) {
// 如果属性值是一个RuntimeBeanReference对象,说明属性是一个引用类型
RuntimeBeanReference ref = (RuntimeBeanReference) originalValue;
return resolveReference(ref, beanName, propertyName);
}
else if (originalValue instanceof ObjectFactory) {
// 如果属性值是一个ObjectFactory对象,说明属性是一个懒加载类型
ObjectFactory<?> objectFactory = (ObjectFactory<?>) originalValue;
return objectFactory.getObject();
}
else if (originalValue instanceof ObjectProvider) {
// 如果属性值是一个ObjectProvider对象,说明属性是一个懒加载类型
ObjectProvider<?> objectProvider = (ObjectProvider<?>) originalValue;
return objectProvider.getObject();
}
else {
// 如果属性值不是一个引用类型,直接返回原始值
return originalValue;
}
}
protected Object resolveReference(Object ref, String beanName, String propertyName) {
if (ref instanceof RuntimeBeanReference) {
// 如果引用类型是一个RuntimeBeanReference对象,说明需要进行自动装配
RuntimeBeanReference reference = (RuntimeBeanReference) ref;
String refName = reference.getBeanName();
Object bean;
try {
bean = getBean(refName);
}
catch (BeansException ex) {
throw new BeanCreationException(beanName, "Could not resolve reference to bean '" + refName + "' in property '" + propertyName + "'", ex);
}
if (bean instanceof NullBean) {
return null;
}
return bean;
}
else if (ref instanceof BeanDefinitionHolder) {
// 如果引用类型是一个BeanDefinitionHolder对象,说明需要进行自动装配
BeanDefinitionHolder bdHolder = (BeanDefinitionHolder) ref;
return resolveReference(bdHolder.getBeanDefinition(), beanName, propertyName);
}
else {
// 如果引用类型不是一个RuntimeBeanReference或者BeanDefinitionHolder对象,直接返回引用类型
return ref;
}
}
在resolveValueIfNecessary()方法中,如果属性值是一个BeanDefinitionHolder对象或者RuntimeBeanReference对象,说明属性是一个引用类型,需要进行自动装配。此时会调用resolveReference()方法进行引用的解析和自动装配。
在resolveReference()方法中,如果引用类型是一个RuntimeBeanReference对象或者BeanDefinitionHolder对象,说明需要进行自动装配。此时会通过getBean()方法获取引用类型对应的Bean实例,并返回该实例。如果获取不到Bean实例,则会抛出异常。
在自动装配的过程中,Spring会先根据属性的类型进行匹配,如果找到一个唯一的Bean实例,则使用该实例进行自动装配。如果还是找不到唯一的Bean实例,则会抛出异常。
除了自动装配外,Spring还支持手动装配,即通过配置元素来显式地指定属性值。例如:
<bean id="foo" class="com.example.Foo">
<property name="bar" value="hello"/>
</bean>
上述配置表示创建一个名为foo的Bean实例,该实例的class属性为com.example.Foo,bar属性的值为字符串hello。
在手动装配的过程中,Spring会将配置的属性值解析为一个String类型的值,并将其转换为目标属性类型,最终将转换后的值设置到目标属性中。
以上就是Spring IOC源码分析的基本内容,通过阅读源码,我们可以深入理解Spring IOC的实现原理,为使用和定制Spring提供了很好的基础。
硬核源码刨析 · Spring · JavaPub
硬核源码刨析 · SpringMVC · JavaPub
硬核源码刨析 · MyBatis · JavaPub
硬核源码刨析 · Dubbo · JavaPub
硬核源码刨析 · Netty · JavaPub
硬核源码刨析 · Elastic-Job · JavaPub
硬核源码刨析 · GoLang · JavaPub