org.springframework.context.ApplicationContext 表明 Spring IoC 容器,并负责实例化,配置和组装上述 bean 。容器经过读取配置元数据得到哪些对象须要实例化、配置和组装的指定。配置元数据能够在XML、Java注解和Java代码中配置。它运行你描述组成你应用程序的对象和对象之间复杂的关系。web
Spring提供了一些开箱即用的ApplicationContext接口的实现。在独立的应用程序中,通常能够建立ClassPathXmlApplicationContext或FileSystemXmlApplicationContext的实例。虽然XML一直是传统的定义配置元数据的格式,但也能够指示容器使用Java注解或者代码做为元数据的格式,并提供少许的XML配置以声明的方式启用这些额外的元数据格式的支持。spring
在大多数的应用场景,用户代码并不须要明确的实例化一个或多个Spring IoC容器的实例。例如,在web应用场景中,程序的web.xml文件中定义一个8行左右的web部署描述符XML就能够知足要求。若是使用的是基于Eclipse的 Spring Tool Suite开发环境,该配置能够很容易地用敲几下鼠标或键盘建立。sql
下图是展现 Spring 如何工做的高级视图。应用程序的类与配置元数据进行结合,以便在 ApplicationContext建立和初始化后,拥有一个彻底配置和可执行的系统或应用程序。session
如上述图所示,Spring IoC 容器使用配置元数据;这个配置元数据表明了应用程序开发人员告诉 Spring 容器在应用程序中如何来实例化,配置和组装对象。架构
传统的配置元数据是一个简单而直观的 XML 格式。框架
基于 XML 的元数据并非配置元数据的惟一容许的形式。 Spring IoC容器自己是彻底与配置元数据的实际写入格式分离的。如今,许多开发人员选择基于 Java 的配置来开发他们的应用程序。函数
其余格式的元数据:ui
Spring 配置至少一个、一般不止一个 bean 由容器来管理。基于 XML 的配置元数据将这些 bean 配置为<bean/>元素,并放置到<beans/> 元素内部。 Java 配置一般在 @Configuration注解的类中使用 @Bean 注解的方法。this
这些bean定义对应组成应用程序的实际对象。一般会定义服务层对象,数据访问对象(DAO),展现对象,例如Structs Action实例,基础设施的对象,如 Hibernate 的 SessionFactories,JMS Queues等等。一般,在容器中不配置细粒度的域对象,由于一般由DAO和业务逻辑负责建立和加载域对象(这里的域对象应该相似于POJO)。可是你可使用 Spring 和 AspectJ的集成配置在 IoC 容器的控制以外建立的对象。url
如下示例显示基于 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 http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="..." class="..."> <!-- collaborators and configuration for this bean go here --> </bean> <bean id="..." class="..."> <!-- collaborators and configuration for this bean go here --> </bean> <!-- more bean definitions go here --> </beans>
id 属性是一个字符串,惟一识别一个独立的 bean 定义。class 属性定义了 bean 的类型,使用完整的类名。 id 属性的值指向协做对象。在XML 配置协做对象未在本例中示给出(关于协做对象这句,应该是指在依赖关系的引用时使用id属性,这个例子并无给出依赖关系的引用)。
实例化 Spring IoC 容器是简单的。提供给ApplicationContext构造函数的位置路径其实是容器从各类外部资源(如本地文件系统、Java ClassPath等)加载配置元数据的资源字符串。
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});
当了解了Spring IoC容器后,由必要了解Spring Resource抽象概念,它提供了一种便捷的机制从uri语法定义的位置读取InputStream。一般,Resource路径用于构造应用上下文。
下面的例子展现了业务层对象(services.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 http://www.springframework.org/schema/beans/spring-beans.xsd"> <!-- services --> <bean id="petStore" class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl"> <property name="accountDao" ref="accountDao"/> <property name="itemDao" ref="itemDao"/> <!-- additional collaborators and configuration for this bean go here --> </bean> <!-- more bean definitions for services go here --> </beans>
下面的例子展现数据接入层(daos.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 http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="accountDao" class="org.springframework.samples.jpetstore.dao.jpa.JpaAccountDao"> <!-- additional collaborators and configuration for this bean go here --> </bean> <bean id="itemDao" class="org.springframework.samples.jpetstore.dao.jpa.JpaItemDao"> <!-- additional collaborators and configuration for this bean go here --> </bean> <!-- more bean definitions for data access objects go here --> </beans>
上面的例子中,业务层包含了PetStoreServiceImpl类和两个类型为JpaAccountDao和JpaItemDao数据接入对象(基于JPA对象/关系映射标准)。property元素的 name 属性是指 JavaBean 属性的名称,而 ref 属性引用另外一个 bean 定义的名称。 id 和 ref 元素之间的这种联系表达了协做对象之间的依赖关系。
bean的定义跨越多个XML文件是有用的。通常一个XML配置文件表明程序架构中的一个业务层或业务模块。
可使用应用上下文的构造函数从全部XML段中加载bean定义。构造函数加载多个Resource地址,正如上文的例子那样。另外一种方法,可使用一个或多个<import/>元素从其它文件中加载bean定义。例如:
<beans> <import resource="services.xml"/> <import resource="resources/messageSource.xml"/> <import resource="/resources/themeSource.xml"/> <bean id="bean1" class="..."/> <bean id="bean2" class="..."/> </beans>
上例中,从三个文件中加载外部的bean定义:services.xml,messageSource.xml和themeSource.xml。全部的位置路径都相对于导入文件的路径,所以services.xml必须位于导入它的文件的相同文件夹或类路径,而messageSource.xml和themeSource.xml需位于导入它们的文件路径的resources下。前面的斜线能够被忽略,但考虑到这些路径是相对的,最好不使用斜线。被导入的文件(要包含顶级元素<beans/>),必须是有效的bean定义(根据Spring Schema)。
使用相对路径../是可行的,可是并不推荐。这样作会对当前应用程序以外的文件产生依赖。通常状况下,这种相对路径并不推荐用于classpach:URLs的格式(例如,classpath: ../services.xml),运行时解析进程选择最近的classpath根目录而后查找它的父文件夹。classpath配置改变也许会致使选择了一个不一样的、错误的文件夹。
应该老是使用绝对路径代替相对路径:例如"file:C:/config/services.xml"或者"classpath:/config/services.xml"。然而,应当注意这样应用程序就和特定的绝对路径耦合了。因此一般使用间接的方式应对这种绝对路径,例如使用在JVM系统运行时解析的占位符${...}。
XML文件中的import指令是由beans的命名空间自己提供的功能。不在beans命名空间中的更多配置功能由Spring的可选命名空间提供,例如context和util命名空间。
做为外部配置元数据的进一步例子,bean定义可使用Spring的Groovy Bean Definition DSL(来自Grails框架)表示。通常的,这种配置保存在.groovy文件中并有以下的格式:
beans { dataSource(BasicDataSource) { driverClassName = "org.hsqldb.jdbcDriver" url = "jdbc:hsqldb:mem:grailsDB" username = "sa" password = "" settings = [mynew:"setting"] } sessionFactory(SessionFactory) { dataSource = dataSource } myService(MyService) { nestedBean = { AnotherBean bean -> dataSource = dataSource } } }
这种配置风格在很大程度上等同于XML bean定义,甚至支持Spring XML配置的命名空间。它还容许经过“importBeans”指令导入XML bean定义文件。
ApplicationContext是拥有注册不一样bean和它们之间依赖关系的高级工厂接口。使用方法 T getBean(String name, Class requiredType)就能够获取 bean 的实例。
ApplicationContext可使你按以下方法读取bean定义并获取它们:
// create and configure beans ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml"); // retrieve configured instance PetStoreService service = context.getBean("petStore", PetStoreService.class); // use configured instance List<String> userList = service.getUsernameList();
使用Groovy配置的启动方式相似,仅仅是使用理解Groovy的context实现类(这个类依然可以识别XML的bean定义):
ApplicationContext context = new GenericGroovyApplicationContext("services.groovy", "daos.groovy");
最灵活的方式是将GenericApplicationContext类与reader代理一块儿使用,例如读取XML文件的XmlBeanDefinitionReader:
GenericApplicationContext context = new GenericApplicationContext(); new XmlBeanDefinitionReader(context).loadBeanDefinitions("services.xml", "daos.xml"); context.refresh();
或者读取Groovy文件的GroovyBeanDefinitionReader:
GenericApplicationContext context = new GenericApplicationContext(); new GroovyBeanDefinitionReader(context).loadBeanDefinitions("services.groovy", "daos.groovy"); context.refresh();
若是须要这些reader代理能够和同一ApplicationContext混合使用,从不一样的配置源读取bean定义。
可使用 getBean() 方法来获取 bean 的实例。 ApplicationContext 接口有一些其余的方法来获取 bean,但理想的应用程序代码不该该使用它们。事实上,你的应用程序代码不该该调用的getBean() 方法,所以不会产生对 Spring 的 API 依赖性的。例如,Spring与web框架集成,为web框架组件例如(controllers、JSF管理bean)提供依赖注入,容许你经过元数据为特殊的bean声明依赖关系。