Spring3.2 IoC容器实现

JerryXia 发表于 , 阅读 (0)
2016 年 01 月 25 日
spring

IoC(Inversion of Control),即控制反转, 也可简单说为依赖注入(DI),旨在将对象间的依赖关系交由 外部环境去处理, 而不是由对象自己去获取,这将大大提升开发效率和降低程序复杂度,在Spring中,这个外部环境就是Spring IoC容器, 也是Spring生态的核心基础,除了Spring的IoC实现外, 其他还有诸如Guice这样的IoC实现, 本文将对Spring的IoC实现进行探讨一番。

IoC(Bean)容器的定义

Spring中IoC容器(Spring Bean容器)的表现形式比较常见的是BeanFactoryApplicationContext, 而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的继承树中可知:

bean-factory-uml.png

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容器,比如WebApplicationContextClassPathXmlApplicationContext等,其对最基础的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的继承树中可以看出:

application-context-uml.png

其中有我们非常熟悉的ClassPathXmlApplicationContextXmlWebApplicationContext

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