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初始化过程