这篇文章将为大家详细讲解有关怎样进行Spring中IOC容器的概述与设计,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。
在依赖反转时实际是依赖对象的获得被反转了。
如果合作对象的引用或依赖关系的管理由具体对象来完成,会导致代码高耦合和可测试性降低,而在面向对象系统中,对象封装了数据和对数据的处理,对象的依赖关系常常在于对数据和方法的依赖,因此把对象的依赖注入交给框架和IoC容器来完成,解耦的同时可以提高代码的可测试性.
在Spring中IoC容器是实现依赖反转的载体,它可以让对象在生成或对象初始化时直接将数据注入到对象中;也可以通过将对象的引用注入到对象数据域中从而实现注入对方法调用的依赖.这种依赖注入可以递归的将对象逐层注入。
通过使用IoC容器,对象依赖关系的管理被反转了,转到IoC容器中来了,对象之间的相互依赖关系由IoC容器进行管理,并由IoC容器完成对象的注入。
在Spring IoC容器的设计中,可以看到二个主要的容器系列,一个是实现BeanFactory接口的简单容器系列,这系列容器只实现了容器的基本功能;
另一个是ApplicationContext应用上下文,作为容器的高级形态而存在.它在简单容器的基础上,增加了许多面向框架的特性,对应用环境进作了许多适配.
IoC容器的主要接口设计图如下图所示:
由上图可以看出IoC容器接口有二条设计路线:
从接口BeanFactory到HierarchicalBeanFactory,再到ConfigableBeanFactory是一条主要的设计路线。
另一条是以ApplicationContext应用上下文接口为核心的接口设计路线。从BeanFactory到ListableBeanFactory及HierarchicalBeanFactory,再到ApplicationContext,再到常用的WebApplicationContext或ConfigableApplicationContext。
图中绿色部分,为部分抽象类及接口实现类,暂不研究。
对于第一条接口设计路线,BeanFactory定义了基本的容器设计规范,HierarchicalBeanFactory继承了BeanFactory基本接口之后,增加了getParentBeanFactory()接口功能,使BeanFactory具备了双亲IoC容器的管理功能。而后面的ConfigableBeanFactory主要定义了一些BeanFactory的配置功能(如通过setParentBeanFacory()设置双亲IoC容器等)。通过这些功能的叠加就定义了BeanFactory简单IoC容器的基本功能。
对于第二条接口设计路线,ListableBeanFactory及HierarchicalBeanFactory是连接BeanFactory及ApplicationContext的接口;在ListableBeanFactory接口中细化了许多BeanFactory接口的功能,在HierarchicalBeanFactory接口中增加了getParentBeanFactory()接口功能,使BeanFactory具备了双亲IoC容器的管理功能;对于ApplicationContext接口,通过继承ResourcePatternResolver,ApplicationEventPublisher,MessageSource等接口,在BeanFactory简单容器的基础上增加了许多对高级容器特性的支持。
public interface BeanFactory { String FACTORY_BEAN_PREFIX = "&"; //如果以&开始则获取FactoryBean本身;否则获取FactoryBean创建的实例. //获取Bean Object getBean(String name) throws BeansException;//可以是别名 <T> T getBean(String name, Class<T> requiredType) throws BeansException; Object getBean(String name, Object... args) throws BeansException; <T> T getBean(Class<T> requiredType) throws BeansException; <T> T getBean(Class<T> requiredType, Object... args) throws BeansException; //判断是否包含bean。不管是抽象类,懒加载,是否在容器范围内,只要符合都返回true。所以返回true时,不一定能从getBean获取实例 boolean containsBean(String name); //单例,原型,bean类型的判断 boolean isSingleton(String name) throws NoSuchBeanDefinitionException; boolean isPrototype(String name) throws NoSuchBeanDefinitionException; boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException; boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException; //获取bean 的类型,别名 Class<?> getType(String name) throws NoSuchBeanDefinitionException; String[] getAliases(String name); }
以XmlBeanFactory为例,来说明简单IoC容器BeanFactory的设计原理。
可以看出XmlBeanFactory继承自DefaultListableBeanFactory,在Spring中实际上是把DefaultListableBeanFactory作为一个功能完整的IoC容器来使用的。
public class XmlBeanFactory extends DefaultListableBeanFactory { private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this); public XmlBeanFactory(Resource resource) throws BeansException { this(resource, null); } public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException { super(parentBeanFactory); this.reader.loadBeanDefinitions(resource); } }
从XmlBeanFactory的名字上可以看出,它是一个可以读取以XML文件方式定义的BeanDefinition的IoC容器。
在XmlBeanFactory中初始化了一个XmlBeanDefinitionReader对象,用来处理以XML文件方式定义的BeanDefinition。
构造XmlBeanFactory这个IoC容器时需要指定XML信息来源,这个信息来源需要封装成Spring的Resource类。
通过xml文件位置构造出Resource,然后将Resource传入XmlBeanFactory的构造函数。这样IoC容器就可以定位到需要的BeanDefinition信息来完成容器的初始化和依赖注入过程。
参考XmlBeanFactory的实现,我们以编程的方式使用DefaultListableBeanFactory来进行总结。
public void mytest(){ ClassPathResource resource = new ClassPathResource("applicationContext.xml"); DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(factory); System.out.println(beanDefinitionReader.loadBeanDefinitions(resource)); Person p = (Person) factory.getBean("personChild"); System.out.println(p); }
发现再使用 IoC容器时需要以下几个步骤:
创建IoC容器的抽象资源,这个抽象资源定义了BeanDefinition的定义信息。
创建一个BeanFactory。这里是DefaultListableBeanFactory。
创建一个BeanDefinition的读取器,通过一个回调配置给BeanFactory。这里是XmlBeanDefinitionReader。
从定义好的资源位置读入配置信息,具体的解析过程由XmlBeanDefinitionReader来完成。完成整个载入和注册Bean定义后,就可以使用IoC容器了。
ApplicationContext的接口关系:如下图所示。
可以看出ApplicationContext在BeanFactory的基础上增加了许多附加功能,为ApplicationContext提供了许多新特新,所以说,ApplicationContext在BeanFactory是一个高级形态意义的IoC容器。
在ApplicationContext在BeanFactory容器中,以FileSystemXMLApplicationContext实现为例来说明ApplicationContext在BeanFactory容器的设计原理。
FileSystemXMLApplicationContext的源代码如下:
public class FileSystemXmlApplicationContext extends AbstractXmlApplicationContext { public FileSystemXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException { super(parent); setConfigLocations(configLocations); //这个refresh操作会牵涉IoC容器启动的一系列操作。对不同的容器操作都是类似的,因此在基类中将他们封装好。 if (refresh) { refresh(); } } @Override protected Resource getResourceByPath(String path) { if (path != null && path.startsWith("/")) { path = path.substring(1); } return new FileSystemResource(path); } }
由代码可以看出主要功能已经在基类AbstractXmlApplicationContext中实现了,在FileSystemXmlApplicationContext中只需要二个与自身设计有关的功能。
应用直接使用FileSystemXmlApplicationContext容器时,对于实例化这个应用上下文的支持,及启动IoC容器的refresh功能。
不同的容器实现对应着不同BeanDefinition读取实现,在FileSystemXmlApplicationContext的读取BeanDefinition实现如上面的代码所示。
关于怎样进行Spring中IOC容器的概述与设计就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。