Spring3.2 IoC容器实现
IoC(Inversion of Control),即控制反转, 也可简单说为依赖注入(DI),旨在将对象间的依赖关系交由 外部环境去处理, 而不是由对象自己去获取,这将大大提升开发效率和降低程序复杂度,在Spring中,这个外部环境就是Spring IoC容器, 也是Spring生态的核心基础,除了Spring的IoC实现外, 其他还有诸如Guice这样的IoC实现, 本文将对Spring的IoC实现进行探讨一番。
IoC(Bean)容器的定义
Spring中IoC容器(Spring Bean容器)的表现形式比较常见的是BeanFactory和ApplicationContext, 而BeanFactory作为最基础的容器抽象,其规范了一个最基本的IoC容器应该具备的功能:
public interface BeanFactory { /** * 用于区别普通Bean和FactoryBean的前缀符号, * 比如有一个叫myJndiObject的FactoryBean, * 那么需要通过&myJndiObjec将返回该Factory */ String FACTORY_BEAN_PREFIX = "&"; /** * 根据名称获取Bean */ Object getBean(String name) throws BeansException; /** * 根据名称获取Bean,并作类型检查 */ <T> T getBean(String name, Class<T> requiredType) throws BeansException; /** * 获取指定类型的Bean */ <T> T getBean(Class<T> requiredType) throws BeansException; /** * 根据名称获取Bean,若Bean为Prototype类型,使用args作为构造参数 */ Object getBean(String name, Object... args) throws BeansException; /** * 容器中是否包含名称或别名为name的Bean */ boolean containsBean(String name); /** * 容器中名称或别名为name的Bean是否为单例 */ boolean isSingleton(String name) throws NoSuchBeanDefinitionException; /** * 容器中名称或别名为name的Bean是否为原型 */ boolean isPrototype(String name) throws NoSuchBeanDefinitionException; /** * 判断名称或别名为name的Bean的类型是否为targetType */ boolean isTypeMatch(String name, Class<?> targetType) throws NoSuchBeanDefinitionException; /** * 获取名称或别名为name的Bean的类型 */ Class<?> getType(String name) throws NoSuchBeanDefinitionException; /** * 获取名称为name的Bean的所有别名,若name为别名,数组第一个元素为Bean原始名称 */ String[] getAliases(String name);} 可以看到BeanFactory中仅定义了如何获取Bean的功能,但一个Bean容器至少需要具备初始化Bean,创建Bean,装载Bean,注入Bean等基础功能,这些功能分别在其他接口中进行了扩展,可从BeanFacotry的继承树中可知:

HierarchicalBeanFactory
HierarchicalBeanFactory定义了Bean容器之间的父子关系:
/** * 具有层级关系的Bean容器 */public interface HierarchicalBeanFactory extends BeanFactory { /** * 获取父级Bean容器或null */ BeanFactory getParentBeanFactory(); /** * 当前Bean容器是否包含名称为name的Bean(不会在父级容器中查询) */ boolean containsLocalBean(String name);} ListableBeanFactory
ListableBeanFactory丰富了获取Bean的功能,如获取多个Bean:
/** * 具有获取多个Bean的Bean容器<br> */public interface ListableBeanFactory extends BeanFactory { /** * 是否包含名称为beanName的BeanDefinition * @param beanName Bean名称 */ boolean containsBeanDefinition(String beanName); /** * 获取BeanDefinition数量 */ int getBeanDefinitionCount(); /** * 获取该Bean容器中内的所有Bean名称 */ String[] getBeanDefinitionNames(); /** * 获取指定类型(包括子类)的Bean名称列表 * @param type 指定类型或接口 */ String[] getBeanNamesForType(Class<?> type); /** * 获取指定类型(包括子类)的Bean名称列表 * @param type 指定类型或接口 * @param includeNonSingletons 是否包含非单例的Bean * @param allowEagerInit 是否初始化懒初始化的单例Bean */ String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit); /** * 获取指定类型(包括子类)的Bean Map信息(包括其他方式注册的单例Bean) * @param type 指定类型或接口 */ <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException; /** * 获取指定类型(包括子类)的Bean Map信息(包括其他方式注册的单例Bean) * @param type 指定类型或接口 * @param includeNonSingletons 是否包含非单例的Bean * @param allowEagerInit 是否初始化懒初始化的单例Bean */ <T> Map<String, T> getBeansOfType(Class<T> type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException; /** * 获取具有指定注解的Bean Map信息 * @param annotationType 注解类型 */ Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException; /** * 获取指定Bean的某个注解信息 * @param beanName bean名称 * @param annotationType 注解类型 */ <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType);} AutowireCapableBeanFactory
AutowireCapableBeanFactory定义了自动装配Bean的功能:
/** * 具有自动装配Bean的Bean容器 */public interface AutowireCapableBeanFactory extends BeanFactory { /** * 非自动装配 */ int AUTOWIRE_NO = 0; /** * 通过名称自动装配 */ int AUTOWIRE_BY_NAME = 1; /** * 通过类型自动装配 */ int AUTOWIRE_BY_TYPE = 2; /** * 通过构造器自动装配 */ int AUTOWIRE_CONSTRUCTOR = 3; //--------------------------- // 创建和设置外部bean实例的方法: //--------------------------- /** * 完全创建一个Bean实例, 包括所有的BeanPostProcessor<br> * [email protected] 并不影响按名字或类型装配的属性} * @param beanClass Bean类型 */ <T> T createBean(Class<T> beanClass) throws BeansException; /** * 装配一个Bean实例(初始化回调或post-processing处理),<br> * 用于对新实例或反序列化实例,(重新)设置带注解的字段和方法。<br> * [email protected] 并不影响按名字或类型装配的属性} * @param existingBean 存在的bean实例 */ void autowireBean(Object existingBean) throws BeansException; /** * 配置Bean实例 * (包括自动装配bean属性,设置属性值,设置工厂回调,如setBeanName,setBeanFactory,及Bean初始化后的post processors) * @param existingBean 存在的Bean实例 * @param beanName bean名称 */ Object configureBean(Object existingBean, String beanName) throws BeansException; /** * 解析bean的依赖信息 * @param descriptor 依赖描述对象 * @param beanName bean名称 */ Object resolveDependency(DependencyDescriptor descriptor, String beanName) throws BeansException; //--------------------------- // 细粒度控制bean生命周期的方法: //--------------------------- /** * 完全创建一个Bean实例, 包括所有的BeanPostProcessor<br> * @param beanClass bean类型 * @param autowireMode 使用名称或类型装配模式 * @param dependencyCheck 是否执行依赖检查 */ Object createBean(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException; /** * 装配一个bean实例 * @param beanClass bean类型 * @param autowireMode 使用名称或类型装配模式 * @param dependencyCheck 是否执行依赖检查 */ Object autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException; /** * 装配bean实例的属性 * @param existingBean 存在的bean实例 * @param autowireMode 使用名称或类型装配模式 * @param dependencyCheck 是否执行依赖检查 */ void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck) throws BeansException; /** * 将名称为beanName的BeanDefinition的属性值赋给existingBean * @param existingBean bean实例 * @param beanName BeanDefinition名称 */ void applyBeanPropertyValues(Object existingBean, String beanName) throws BeansException; /** * 初始化Bean * @param existingBean 存在的bean实例 * @param beanName bean名称 */ Object initializeBean(Object existingBean, String beanName) throws BeansException; /** * 调用bean实例的postProcessBeforeInitialization方法 * @param existingBean 存在的bean实例 * @param beanName bean名称 */ Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException; /** * 调用bean实例的postProcessAfterInitialization方法 * @param existingBean 存在的bean实例 * @param beanName bean名称 */ Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException; /** * 解析bean的依赖信息 * @param descriptor 依赖描述信息 * @param beanName bean名称 * @param autowiredBeanNames 自动装配的bean名称集 * @param typeConverter 类型转换器 */ Object resolveDependency(DependencyDescriptor descriptor, String beanName, Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException;} ConfigurableBeanFactory
ConfigurableBeanFactory定义了一些配置Bean容器的功能:
/** * 扩展一些配置Bean容器的功能 */public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry { /** * 单例bean */ String SCOPE_SINGLETON = "singleton"; /** * 原型bean */ String SCOPE_PROTOTYPE = "prototype"; /** * 设置父容器 */ void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException; /** * 设置Bean类加载器 */ void setBeanClassLoader(ClassLoader beanClassLoader); ClassLoader getBeanClassLoader(); /** * 设置临时类加载器 */ void setTempClassLoader(ClassLoader tempClassLoader); ClassLoader getTempClassLoader(); /** * 设置是否缓存Bean元数据 */ void setCacheBeanMetadata(boolean cacheBeanMetadata); boolean isCacheBeanMetadata(); /** * 设置Bean表达式解析器 */ void setBeanExpressionResolver(BeanExpressionResolver resolver); BeanExpressionResolver getBeanExpressionResolver(); /** * 设置类型转换服务 */ void setConversionService(ConversionService conversionService); ConversionService getConversionService(); ...} ApplicationContext
ApplicationContext作为最常用的Bean容器,比如WebApplicationContext,ClassPathXmlApplicationContext等,其对最基础的BeanFactory进行了一些扩展,如EnvironmentCapable(容器运行时环境,有了它就能在Spring使用中区分开发,测试,生产等环境),MessageSource(消息参数化和国际化功能),ApplicationEventPublisher(应用事件发布功能),ResourcePatternResolver(资源解析功能),似乎ApplicationContext缺少了一些功能,如AutowireCapableBeanFactory(自动装配功能),但其实ApplicationContext通过内部包装了一个AutowireCapableBeanFactory来重用基础Bean容器的功能:
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver { /** * 应用ID */ String getId(); /** * 应用名称,默认"" */ String getApplicationName(); /** * 应用易读的名称 */ String getDisplayName(); /** * 容器第一次加载的时间戳 */ long getStartupDate(); /** * 父容器 */ ApplicationContext getParent(); /** * 包装一个可自动装配的Bean容器 */ AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;} ApplicationContext作为开发人员最常用的Bean容器,Spring已经为我们提供很多现成的实现可用,从ApplicationContext的继承树中可以看出:

其中有我们非常熟悉的ClassPathXmlApplicationContext和XmlWebApplicationContext。
Bean定义
既然有了Bean容器,那么Bean是什么呢?在Spring中,Bean的定义抽象为BeanDefinition:
/** * 基础Bean定义 */public interface BeanDefinition { /** * 获取该Bean的父级Bean名称 */ String getParentName(); void setParentName(String parentName); /** * 获取Bean的类名称(并不一定是该Bean实际的类名称,比如子Bean重写或继承父级Bean的类名称) */ String getBeanClassName(); void setBeanClassName(String beanClassName); /** * 获取FactoryBean名称 */ String getFactoryBeanName(); void setFactoryBeanName(String factoryBeanName); /** * 获取构建该Bean的工厂方法名称,将使用构造器参数调用该工厂方法 */ String getFactoryMethodName(); void setFactoryMethodName(String factoryMethodName); /** * 获取Bean的元类型,SINGLETON或PROTOTYPE */ String getScope(); void setScope(String scope); /** * 该Bean是否懒加载,即不在Spring容器启动时初始化,只针对SINGLETON类型的Bean */ boolean isLazyInit(); void setLazyInit(boolean lazyInit); /** * 该Bean所依赖的其他Bean名称列表 */ String[] getDependsOn(); void setDependsOn(String[] dependsOn); /** * 该Bean是否会注入到其他Bean中 */ boolean isAutowireCandidate(); void setAutowireCandidate(boolean autowireCandidate); /** * 该Bean是否注入到了多个Bean中 */ boolean isPrimary(); void setPrimary(boolean primary); /** * 是否为SINGLETON元类型 */ boolean isSingleton(); /** * 是否为PROTOTYPE元类型 */ boolean isPrototype(); /** * 该Bean是否是"抽象的", 就是不能实例化 */ boolean isAbstract(); /** * 该Bean的角色: * 0: 应用级别的Bean,如用户定义的Bean * 1: 支持级别的Bean,比如一些配置Bean * 2: 基础级别Bean,与用户无关, */ int getRole(); /** * Bean描述 */ String getDescription(); /** * 该Bean来自的上下文描述,用于错误信息记录 */ String getResourceDescription(); /** * 递归获取该BeanDefinition包装的内部BeanDefinition */ BeanDefinition getOriginatingBeanDefinition();} Resource定义
在构建Bean容器时,我们会传入对应的配置文件路径,如:
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:application-context.xml"); 对于传入的文件等资源信息,Spring内部会抽象为Resource接口:
public interface Resource extends InputStreamSource { /** * Return whether this resource actually exists in physical form. * <p>This method performs a definitive existence check, whereas the * existence of a [email protected] Resource} handle only guarantees a * valid descriptor handle. */ boolean exists(); /** * Return whether the contents of this resource can be read, * e.g. via [email protected] #getInputStream()} or [email protected] #getFile()}. * <p>Will be [email protected] true} for typical resource descriptors; * note that actual content reading may still fail when attempted. * However, a value of