Spring Ioc容器的设计理解

Spring ioc容器的设计主要是基于BeanFactory和ApplicationContext两个接口,其中ApplicationContext是BeanFactory的子接口之一,换句话说BeanFactory是spring ioc容器所定义的最底层接口,而ApplicationContext是其高级接口之一,并且对BeanFactory功能做了许多有用的扩展,所以在绝大部分的工作场景下,都会使用ApplicationContext作为Spring Ioc容器,列一下Spring 相关的iOC容器接口的主要设计:

架构图

这是Spring Ioc的主要设计图,我们可以看到BeanFactory是设计的最底层,提供了Ioc最底层的设计,来分析下源码:

package org.springframework.beans.factory;

import org.springframework.beans.BeansException;
import org.springframework.core.ResolvableType;

public interface BeanFactory {
    String FACTORY_BEAN_PREFIX = "&";

/*返回指定bean的实例,该实例可以是共享的或独立的。 
此方法允许将Spring BeanFactory用作* Singleton或Prototype设计模式的替代品。对于Singleton bean,调用者可以保留对返回对象的引用。
将别名转换回相应的规范bean名称。 将询问父工厂是否在此工厂实例中找不到bean。 
@param 命名要检索的bean的名称
@return bean的实例
@throws NoSuchBeanDefinitionException如果没有具有指定名称的bean定义
@throws BeansException如果无法获取bean
Object getBean(String var1) throws BeansException;*/

/*返回指定bean的实例,该实例可以是共享的或独立的。
标注:与{@link #getBean(String)}的行为相同,但如果bean不是* required类型,则通过抛出BeanNotOfRequiredTypeException来提供类型*安全性的度量。这意味着在正确地转换*结果时不能抛出ClassCastException,就像{@link #getBean(String)}一样。 将别名转换回相应的规范bean名称。 将询问父工厂是否在此工厂实例中找不到bean。
@param命名要检索的bean的名称
@param requiredType类型必须匹配的bean。可以是实际类的接口或超类,或任何匹配的{@code null}。例如,如果值*是{@code Object.class},则无论返回的实例的类如何,此方法都将成功。 * @return bean的一个实例
@throws NoSuchBeanDefinitionException如果没有这样的bean定义
@throws BeanNotOfRequiredTypeException如果bean不是必需的类型
@throws BeansException如果无法创建bean*/

    <T> T getBean(String var1, Class<T> var2) throws BeansException;

/*返回指定bean的实例,该实例可以是共享的或独立的。
允许指定显式构造函数参数/工厂方法参数,覆盖bean定义中指定的默认参数(如果有)。 
@param命名要检索的bean的名称
@param args在使用显式参数创建bean实例时使用的参数(仅在创建新实例时应用而不是检索现有实例)
@return实例bean
@throws NoSuchBeanDefinitionException如果没有这样的bean定义
@throws BeanDefinitionStoreException如果已经给出参数但受影响的bean不是原型
@throws BeansException如果无法创建bean
    Object getBean(String var1, Object... var2) throws BeansException;
返回唯一匹配给定对象类型的bean实例(如果有)。
此方法进入{@link ListableBeanFactory} by-type lookup territory ,但也可以根据给定类型的名称*转换为常规的按名称查找。对于跨bean集的更广泛的检索操作,使用{@link ListableBeanFactory}和/或{@link BeanFactoryUtils}。 
@param requiredType类型必须匹配;可以是接口或超类。{@code null}是不允许的。 
@return匹配所需类型的单个bean的实例
@throws NoSuchBeanDefinitionException如果没有找到给定类型的bean
@throws NoUniqueBeanDefinitionException如果找到多个给定类型的bean
@throws BeansException如果bean不能被创造*/

    <T> T getBean(Class<T> var1) throws BeansException;

/*返回指定bean的实例,该实例可以是共享的或独立的
允许指定显式构造函数参数/工厂方法参数,覆盖bean定义中指定的默认参数(如果有)。
此方法进入{@link ListableBeanFactory} by-type lookup territory ,但也可以根据给定类型的名称
转换为常规的按名称查找。对于跨bean集的更广泛的检索操作,使用{@link ListableBeanFactory}和/或{@link BeanFactoryUtils}。
@param requiredType类型必须匹配;可以是接口或超类。{@code null}是不允许的。 
@param args在使用显式参数创建bean实例时使用的参数(仅在创建新实例时应用而不是检索现有实例)
@return bean的实例
@throws NoSuchBeanDefinitionException如果没有这样的bean定义
@throws BeanDefinitionStoreException如果已经给出参数但受影响的bean不是原型
@throws BeansException如果无法创建bean*/

    <T> T getBean(Class<T> var1, Object... var2) throws BeansException;

//此bean工厂是否包含具有给定名称的bean定义或外部注册的singleton *实例? 
//如果给定的名称是别名,它将被转换回相应的规范bean名称。 
//如果此工厂是分层的,则会询问任何父工厂是否在此工厂实例中找不到bean。
//如果找到与给定名称匹配的bean定义或单例实例,此方法将返回{@code true},无论命名bean定义是具体
//还是抽象,是否在范围内。因此,请注意,此方法的{@code true} 返回值不一定表示{@link #getBean} //将能够获取同名的实例。 *
//@param命名要查询的bean的名称
//@return是否存在具有给定名称的bean
    boolean containsBean(String var1);
//判断是否返利,如果返回为true则则作为唯一的单例存在
    boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
//如果判断为true,就是当你从容器中获取bean,容器就为你生成了一个新的实例
    boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;

    Class<?> getType(String var1) throws NoSuchBeanDefinitionException;
//获取别名的方法
    String[] getAliases(String var1);
}

getBean的多个方法用于获取配置给Spring ioc容器的Bean,从参数

类型看可以是字符串,也可以是Class类型,由于Class类型可以扩展接口

也可以继承父类,所以在一定程度上会存在使用父类类型无法准确获得实例

的异常,比如获取学生类,但是学生子类有男学生和女学生两个雷,这个时候通过

学生类就无法从容器中得到实例,因为容器无法判断具体的实现类。

isSigleton用于判断是否是单例,如果判断为true,其意思是该Bean在容器中是作为一个唯一

单例存在的,而isProTotype则相反,如果判断为true,就是当你从容器中获取bean,容器就为你生成了一个新的实例,在默认情况下,Spring会为Bean创建一个单例,也就是默认情况下isSingLeton返回true,而isPrototype返回false。

关于type的匹配,这是一个按java类型匹配的方式。

这是Spring Ioc最底层的设计,所有关于spring ioc的容器将遵守它所定义的方法。为了扩展更多的功能,ApplicationContext接口扩展了许多的接口,因此它的功能比较强大。

public interface WebApplicationContext extends ApplicationContext {
    String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";
    String SCOPE_REQUEST = "request";
    String SCOPE_SESSION = "session";
    String SCOPE_GLOBAL_SESSION = "globalSession";
    String SCOPE_APPLICATION = "application";
    String SERVLET_CONTEXT_BEAN_NAME = "servletContext";
    String CONTEXT_PARAMETERS_BEAN_NAME = "contextParameters";
    String CONTEXT_ATTRIBUTES_BEAN_NAME = "contextAttributes";

    ServletContext getServletContext();
}

由此可看到WebApplicationContext也进行了扩展,在实际应用中常常会使用到ApplicationContext接口,因为BeanFactory所提供的方法较少,而ApplicationContext方法和功能较多,而具体的ApplicationContext的实现类会使用在某一个领域,比如说Spring Mvc中的GenericWebApplicationContext,就广泛应用于Java web工程之中。

使用ClassPathXmlApplicationContext·(ApplicationContext的子类)容器可以将其初始化。有什么不对的地方,可以交流起来,并及时修正,IOC初始化过程

猜你喜欢

转载自blog.csdn.net/crossroads10/article/details/89248805