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提供了很好的基础。