SpringIOC介绍
IOC,也就是我们所说控制反转,在spring中,它通过ioc容器来管理对象,包括对象的生命周期和与其他对象的关系,实现控制反转,将对象-对象 这样的关系转为 对象-容器-对象,它在程序运行时通过反射动态的提供对象来实现依赖注入(DI)。
SpringIOC容器体系
springIOC的容器体系最重要的接口有BeanFactroy和ApplicationContext,我们将容器类型也分为BanFactory和ApplicationContext两类,其中BeanFactory代表容器的基本实现,只有容器的基础功能,ApplicationContext则被认为是容器的高级实现,在基础功能上附加了很多额外的功能以供使用。
根据这个思路,我们来学习spring中的容器体系,按照基础实现和高级实现两条线来分析:
第一条线,容器的基本实现:BeanFactory
BeanFactory==》HierarchicalBeanFactory==》ConfigurableBeanFactory ==》…==》DefaultListableBeanFactory
我将UML图附上:
绿色部分是ioc容器的基本功能实现路线,
红色部分是继承了顶级接口BeanFactory的三个二级几口
简单介绍下这些:
BeanFactory:顶级接口,定义了容器的基本规范:getBean() etc.
HierarchicalBeanFactory(二级接口):双亲Ioc容器的概念,还记得上一篇解析CntextLoaderListener中我们提到过:CntextLoaderListener和DispatcherServlet共同建立springMVC中的ioc容器体系,其中CntextLoaderListener创建的是Root WebApplicationContext,是作为DispatcherServlet创建的springMVC WebApplication的双亲容器存在的,这个双亲的概念就是从HierarchicalBeanFactory开始的。
ListableBeanFactory(二级接口):引入beanDefinition的概念,将容器中的bean对象以集合
形式获取,不需要通过名称一个个来获取,将容器需要实现类似预加载所有beanDefinition的功能时可以通过该接口实现。
AutowireCapableBeanFactory(二级接口):通过源码上的注释我们可以了解到这个接口的作用是让那些非spring管理的对象也能拥有spring自动注入的特性。同时spring中常问到的spring中的装配方式也是在这边提到的:
/**
* Constant that indicates no externally defined autowiring. Note that
* BeanFactoryAware etc and annotation-driven injection will still be applied.
* @see #createBean
* @see #autowire
* @see #autowireBeanProperties
*/
int AUTOWIRE_NO = 0;
/**
* Constant that indicates autowiring bean properties by name
* (applying to all bean property setters).
* @see #createBean
* @see #autowire
* @see #autowireBeanProperties
*/
int AUTOWIRE_BY_NAME = 1;
/**
* Constant that indicates autowiring bean properties by type
* (applying to all bean property setters).
* @see #createBean
* @see #autowire
* @see #autowireBeanProperties
*/
int AUTOWIRE_BY_TYPE = 2;
/**
* Constant that indicates autowiring the greediest constructor that
* can be satisfied (involves resolving the appropriate constructor).
* @see #createBean
* @see #autowire
*/
int AUTOWIRE_CONSTRUCTOR = 3;
/**
* Constant that indicates determining an appropriate autowire strategy
* through introspection of the bean class.
* @see #createBean
* @see #autowire
* @deprecated as of Spring 3.0: If you are using mixed autowiring strategies,
* prefer annotation-based autowiring for clearer demarcation of autowiring needs.
*/
@Deprecated
int AUTOWIRE_AUTODETECT = 4;
ConfigurableBeanFactory:提供一系列可插拔的配置项,填充BeanFactory的功能。
DeFaultLsitableBeanFactory:这个类是这条设计线的第一个具体实现类,它实现了ioc容器的所有基本功能。
第二条线,容器的高级实现:ApplicationContext
BeanFactory==》ListableBeanFactory==》Application==》WebApplication
我将UML图附上:
绿色部分是ioc容器的高级功能的实现路线
红色部分是最终的几个具体实现类:
ApplicationContext:
public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
之所以说ApplicationContext是ioc容器的高级实现,是因为他在beanFactory的基础功能上附加了很多其他功能来对应用实现支持,这部分附加的内容主要就是通过继承的这些类实现:
* Central interface to provide configuration for an application.
* This is read-only while the application is running, but may be
* reloaded if the implementation supports this.
*
* <p>An ApplicationContext provides:
* <ul>
* <li>Bean factory methods for accessing application components.
* Inherited from {@link org.springframework.beans.factory.ListableBeanFactory}.
* <li>The ability to load file resources in a generic fashion.
* Inherited from the {@link org.springframework.core.io.ResourceLoader} interface.
* <li>The ability to publish events to registered listeners.
* Inherited from the {@link ApplicationEventPublisher} interface.
* <li>The ability to resolve messages, supporting internationalization.
* Inherited from the {@link MessageSource} interface.
* <li>Inheritance from a parent context. Definitions in a descendant context
* will always take priority. This means, for example, that a single parent
* context can be used by an entire web application, while each servlet has
* its own child context that is independent of that of any other servlet.
* </ul>
ApplicationContext为应用提供配置,通过:
ListableBeanFactory可以访问应用中的组件;
ResourceLoader可以加载资源;
ApplicationEventPublisher可以注册监听器分发事件;
MessageSource可以支持国际化;
WeblicationContext:
public interface WebApplicationContext extends ApplicationContext {
/**
* Context attribute to bind root WebApplicationContext to on successful startup.
* <p>Note: If the startup of the root context fails, this attribute can contain
* an exception or error as value. Use WebApplicationContextUtils for convenient
* lookup of the root WebApplicationContext.
* @see org.springframework.web.context.support.WebApplicationContextUtils#getWebApplicationContext
* @see org.springframework.web.context.support.WebApplicationContextUtils#getRequiredWebApplicationContext
*/
String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";
/**
* Scope identifier for request scope: "request".
* Supported in addition to the standard scopes "singleton" and "prototype".
*/
String SCOPE_REQUEST = "request";
/**
* Scope identifier for session scope: "session".
* Supported in addition to the standard scopes "singleton" and "prototype".
*/
String SCOPE_SESSION = "session";
/**
* Scope identifier for global session scope: "globalSession".
* Supported in addition to the standard scopes "singleton" and "prototype".
*/
String SCOPE_GLOBAL_SESSION = "globalSession";
/**
* Scope identifier for the global web application scope: "application".
* Supported in addition to the standard scopes "singleton" and "prototype".
*/
String SCOPE_APPLICATION = "application";
/**
* Name of the ServletContext environment bean in the factory.
* @see javax.servlet.ServletContext
*/
String SERVLET_CONTEXT_BEAN_NAME = "servletContext";
/**
* Name of the ServletContext/PortletContext init-params environment bean in the factory.
* <p>Note: Possibly merged with ServletConfig/PortletConfig parameters.
* ServletConfig parameters override ServletContext parameters of the same name.
* @see javax.servlet.ServletContext#getInitParameterNames()
* @see javax.servlet.ServletContext#getInitParameter(String)
* @see javax.servlet.ServletConfig#getInitParameterNames()
* @see javax.servlet.ServletConfig#getInitParameter(String)
*/
String CONTEXT_PARAMETERS_BEAN_NAME = "contextParameters";
/**
* Name of the ServletContext/PortletContext attributes environment bean in the factory.
* @see javax.servlet.ServletContext#getAttributeNames()
* @see javax.servlet.ServletContext#getAttribute(String)
*/
String CONTEXT_ATTRIBUTES_BEAN_NAME = "contextAttributes";
/**
* Return the standard Servlet API ServletContext for this application.
* <p>Also available for a Portlet application, in addition to the PortletContext.
*/
ServletContext getServletContext();
}
重点是最后一个方法:
/**
* Return the standard Servlet API ServletContext for this application.
* <p>Also available for a Portlet application, in addition to the PortletContext.
*/
ServletContext getServletContext();
通过这个方法将spring中的ioc容器与web应用中的ServletContext联系起来。
总结
从UML图可以看到,整个ioc体系是非常复杂的,在面向接口+单一职责的设计下,一个庞大的接口体系成型,这样设计的好处是显而易见的,我们可以非常方便的设计出符合自己需求的容器,打造自定义的容器以供使用。
这里只是简单介绍了springIOC容器,后面会更加深入的进行解析,同时会通过阅读源码穿插设计模式的内容。