对Spring IOC容器相关整理(一)
1.IOC 控制反转(Inversion of Control)
控制反转是一种设计原则,用来降低代码之间的耦合性。其中最常见的方式叫做依赖注入(DI)通过控制反转,对象在被创建的时候,系统内所有对象将通过配置文件(XML,JavaCode,注解等…)配置的依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
容器(Container)容器的作用就是生成(生命周期开始时)、存放bean的实例并控制每个bean实例的生命周期 ,在适当的时候销毁bean实例(生命周期结束时)。。(单例()、原型()生命周期是Spring ApplicationContext //todo )
IoC模式中,系统通过引入实现了IoC模式的IoC容器,即可由IoC容器来管理对象的生命周期、依赖关系等,从而使得应用程序的配置和依赖性规范与实际的应用程序代码分离。其中一个特点就是通过文本的配置文件进行应用程序组件间相互关系的配置,而不用重新修改并编译具体的代码。
可以把IoC模式看作工厂模式的升华,把IoC容器看作是一个大工厂,只不过这个大工厂里要生成的对象都是在配置文件(XML,JavaCode,注解等…)中给出定义的。利用Java 的“反射”编程,根据配置文件(XML,JavaCode,注解等…)中给出的类定义生成相应的对象。从实现来看,以前在工厂模式里写死了的对象,IoC模式改为配置文件(XML,JavaCode,注解等…),这就把工厂和要生成的对象两者隔离,极大提高了灵活性和可维护性
1.1、BeanFactory
org.springframework.beans 和org.springframework.context 包是Spring 框架IOC容器的基础。BeanFactory 接口提供了一种高级配置机制,能够管理任何类型的对象。ApplicationContext 是BeanFactory的子接口。
BeanFacotry是spring中比较原始的Factory。如XMLBeanFactory就是一种典型的BeanFactory。原始的BeanFactory无法支持spring的许多插件,如AOP功能、Web应用等。
ApplicationContext接口,它由BeanFactory接口派生而来,ApplicationContext包含BeanFactory的所有功能,通常建议优先使用ApplicationContext
1 Resource resource = new FileSystemResource("beans.xml"); 2 BeanFactory factory = new XmlBeanFactory(resource);
1 ClassPathResource resource = new ClassPathResource("beans.xml"); 2 BeanFactory factory = new XmlBeanFactory(resource);
1 ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"applicationContext.xml", "applicationContext-part2.xml"}); 3 BeanFactory factory = (BeanFactory) context;
BeanFacotry 提供了六种方法供用户调用
- boolean containsBean(String beanName) 判断工厂中是否包含给定名称的bean定义,若有则返回true
- Object getBean(String) 返回给定名称注册的bean实例。根据bean的配置情况,如果是singleton模式将返回一个共享实例,否则将返回一个新建的实例,如果没有找到指定bean,该方法可能会抛出异常
- Object getBean(String, Class) 返回以给定名称注册的bean实例,并转换为给定class类型
- Class getType(String name) 返回给定名称的bean的Class,如果没有找到指定的bean实例,则抛出NoSuchBeanDefinitionException异常
- boolean isSingleton(String) 判断给定名称的bean定义是否为单例模式
- String[] getAliases(String name) 返回给定bean名称的所有别名
参考:Spring BeanFactory与FactoryBean的区别及其各自的详细介绍于用法
org.springframework.context.ApplicationContext接口表示SpringIoC容器,负责实例化、配置和组装bean。 BeanFactory 提供了配置框架和基本功能,ApplicationContext 添加了更多特定于企业的功能。ApplicationContext 是一个完整的BeanFactory 的扩展集
ApplicationContext 的实现类有FileSystemXmlApplicationContext、ClassPathXmlApplicationContext、AnnotationConfigApplicationContext。
ClassPathXmlApplicationContext 默认从类路径加载配置文件,FileSystemXmlApplicationContext 默认从文件系统中装载配置文件
和BeanFactory初始化相似,ApplicationContext的初始化也很简单,如果配置文件放置在类路径下,用户可以优先使用ClassPathXmlApplicationContext实现类:
ApplicationContext ctx = new ClassPathXmlApplicationContext(“com/baobaotao/context/beans.xml”)
对于ClassPathXmlApplicationContext来说,”com/baobaotao/context/beans.xml”等同于”classpath: com/baobaotao/context/beans.xml”。
如果配置文件放置在文件系统的路径下,则可以优先考虑使用FilySystemXmlApplicationContext实现类:
ApplicationContext ctx =new FileSystemXmlApplicationContext(“com/baobaotao/context/beans.xml”);
对于FileSystemXmlApplicationContext来说,“com/baobaotao/context/beans.xml”等同于“file:com/baobaotao/context/beans.xml”。
还可以指定一组配置文件,Spring会自动将多个配置文件在内存中”整合”成一个配置文件,如下所示:
ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{“conf/beans1.xml”,”conf/beans2.xml”});
ApplicationContext的初始化和BeanFactory有一个重大的区别:BeanFactory在初始化容器时,并未实例化Bean,直到第一次访问某个Bean时才实例目标Bean;而ApplicationContext则在初始化应用上下文时就实例化所有单实例的Bean。因此ApplicationContext的初始化时间会比BeanFactory稍长一些,不过稍后的调用则没有”第一次惩罚”的问题。
WebApplicationContext 继承了ApplicationContext接口,是ApplicationContext的扩展,它增加了WEB应用特性,还可以视图解析、主题解析、映射,通过ServletContext与servlet关联 ,WebApplicationContext被绑定在ServletContext上(通过ContextLoaderListener绑定),可以通过RequestContextUtils获取WebApplicationContext。
WebApplicationContext是专门为web应用准备的,他允许从相对于web根目录的路劲中装载配置文件完成初始化工作,从WebApplicationContext中可以获得ServletContext的引用,整个Web应用上下文对象将作为属性放置在ServletContext中,以便web应用可以访问spring上下文,spring中提供WebApplicationContextUtils的getWebApplicationContext(ServletContext src)方法来获得WebApplicationContext对象
WebApplicationContext扩展了ApplicationContext.在 WebApplicationContext中定义了一个常量 ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,在上下文启动时,WebApplicationContext以此为键放置在ServletContext属性列表中,
public static WebApplicationContext getWebApplicationContext(ServletContext sc) { return getWebApplicationContext(sc, WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); }
ConfigurableWebApplicationContext扩展了WebApplicationContext,它允许通过配置的方式实例化,同时设置两个重要方法
setServletContext(ServletContext context) 为spring设置web应用上下文,以便两者整合
setConfigLocations(String[]locations) 设置Spring配置的文件地址
webApplicationContext初始化需要ServletContext,也就是说需要web容器前提下才能·完成启动工作 可以通过在web.xml中配置自启动Servlet或Web容器监听来实现web容器的启动
Spring分别提供启动WebApplicationContext的servlet和Web容器监听器
org.springframework.web.context.ContextLoaderListener
org.springframework.web.context.ContexLoaderServlet 此方法目前以废弃
!--从类路径下加载Spring配置文件,classpath特指类路径下加载--> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:smart-context.xml </param-value> </context-param> <!--负责启动spring容器的监听器 还可以声明自启动的Servlet ContextLoaderServlet--> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
如果使用@Configuration的java类提供配置信息的配置 web.xml配置修改如下
<!--通过指定context参数,让Spring使用AnnotationConfigWebApplicationContext启动容器而非XmlWebApplicationContext 默认没配置时是使用XmlWebApplicationContext--> <context-param> <param-name>contextClass</param-name> <param-value> org.springframework.web.context.support.AnnotationConfigWebApplicationContext </param-value> </context-param> <!--指定标注了@Configuration的类,多个可以用逗号分隔--> <context-param> <param-name>contextConfigLocation</param-name> <param-value>com.example.Car,com.example.Boss</param-value> </context-param> <!--监听器将根据上面的配置使用AnnotationConfigWebApplicationContext 根据contextConfigLocation 指定的配置类启动Spring容器--> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
1.4 配置元数据
SpringIoC容器使用一种配置元数据。此配置元数据展示了Spring 容器如何在应用程序中实例化、配置和组装对象。
Spring容器支持基于XML的配置元数据配置,Spring2.5引入了对基于注释的配置元数据的支持,从Spring3.0开始,Spring JavaConfig 项目提供的许多特性成为核心Spring框架的一部分,引入了对基于Java的配置元数据的支持。
基于XML的配置元数据将这些bean配置为在顶层元素<beans/>内部的<bean/>元素。Java配置通常在带有@Configuration注释的类中使用带@Bean注释的方法。
基于XML的配置元数据的基本结构:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="..." class="..."> ① ② <!-- collaborators and configuration for this bean go here --> <!-这个bean的协作者(引用其他的bean)和配置在这里-> </bean> <bean id="..." class="..."> <!-- collaborators and configuration for this bean go here --> <!-这个bean的协作者和配置在这里-> </bean> <!-- more bean definitions go here --> <!-更多的bean配置在这里-> </beans>
<bean>中 id属性是标识单个bean定义的字符串,class属性定义Bean的类型,并使用完全限定的类名称。
基于Java的配置元数据的基本结构:
@Configuration public class SpringConfig { @Bean public Piano piano(){ return new Piano(); } @Bean(name = "counter") public Counter counter(){ return new Counter(12,"Shake it Off",piano()); } }