Spring的基本用法
依赖注入
Spring的核心机制:依赖注入。
不管是控制反转还是依赖注入,其含义完全相同:当某个Java实例(调用者)需要另一个Java实例(被调用者)时,在传统的程序设计中,通常由调用者来创建被调用者的实例。在依赖注入的模式下,创建被调用者的工作不再由调用者来完成。因此称为控制反转;创建被调用者实例的工作通常由Spring容器来完成,然后注入调用者,因此也成为依赖注入。这都说明Spring采用动态、灵活的方式来管理各种对象。对象与对象之间的具体实现相互透明。
依赖注入通常由以下两种:
- 设值注入:IoC容器使用属性的setter方法来注入被依赖的实例。
- 构造注入:IoC容器使用构造器来注入被依赖的梳理。
设值注入
设值注入是指IoC容器使用属性的sertter方法来注入被依赖的实例。
Spring配置Bean实例通常会指定两个属性:
- id:指定该Bean的唯一标识,程序通过id属性值来访问该Bean实例。
- class:指定该bean的实现类,此处不可再用接口,必须使用实现类,Spring的容器会使用XML解析器读取该属性值,并用反射来创建该实现类的实例。
Spring会自动接管每个
<?xml version="1.0" encoding="utf-8"?>
<!-- Spring配置文件的根元素,使用spring-beans-4.2.xsd语义约束 -->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">
<!-- 配置chinese实例,其实现类是Chinese -->
<bean id="chinese" class="com.bh.service.impl.Chinese">
<!-- 将stoneAxe注入给axe属性 -->
<property name="axe" ref="stoneAxe"/>
</bean>
<!-- 配置stoneAxe实例,其实现类是StoneAxe -->
<bean id="stoneAxe" class="com.bh.service.impl.StoneAxe"/>
<!-- 配置steelAxe实例,其实现类是SteelAxe -->
<bean id="steelAxe" class="com.bh.service.impl.SteelAxe"/>
</beans>
Bean与Bean之间的依赖关系由Spring管理,Spring采用setter方法为目标BeanHuru所依赖的Bean,这种方式成为设值注入。
Spring容器的3个基本要点:
- 应用程序的各组件面向接口编程,面向接口编程可以将各组件之间的耦合提升到接口层次,从而有利于项目后期的扩展。
- 应用程度的各组件不再由程序主动产生,而是由spring容器负责产生,并初始化。
- Spring采用配置我呢间或由Annotation来管理Bean的实现类,依赖关系,Spring容器则根据配置文件,利用反射来创建实例,并为之注入依赖关系。
构造注入:
在构造实例时已经为其完成了依赖关系的初始化,这种利用构造器来设值依赖关系的方式称为构造注入。
<?xml version="1.0" encoding="utf-8"?>
<!-- Spring配置文件的根元素,使用spring-beans-4.2.xsd语义约束 -->
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd">
<!-- 配置chinese实例,其实现类是Chinese -->
<bean id="chinese" class="com.bh.service.impl.Chinese">
<!-- 使用构造注入,为chinese实例注入steelAxe实例 -->
<constructor-arg ref="steelAxe" />
</bean>
<!-- 配置stoneAxe实例,其实现类是StoneAxe -->
<bean id="stoneAxe" class="com.bh.service.impl.StoneAxe" />
<!-- 配置steelAxe实例,其实现类是SteelAxe -->
<bean id="steelAxe" class="com.bh.service.impl.SteelAxe" />
</beans>
上面的配置文件使用<constructor-arg.../>
元素制定了一个构造器函数,该参数类型是Axe,这指定Spring调用Chinese类里带一个Axe参数的构造器来虎藏剑Chinese实例,因为使用了有参数的构造器创建实例,所以当Bean实例被创建完成后,该Bean的依赖关系已经设置完成。
配置<constructor-arg.../>
元素时指定一个index属性,用于指定该构造参数值作为第几个构造参数值。
两种注入方式的对比:
设值注入有以下的有点:
- 与传统的JavaBean的写法更相似,程序开发人员更容易理解、接受。通过setter方法设定依赖关系显得更加直观、自然。
- 对于复杂的依赖关系,如果采用构造注入,会导致构造器过于臃肿,难于阅读。Spring在创建Bean实例时需要同时实例化其依赖的全部实例,因而导致性能下降。而使用设值注入则能避免这些问题。
- 在某些参数可选的情况下,多参数的构造器更加笨重。
使用Spring容器
Spring容器有两个核心的接口:BeanFactory和ApplicationContext,其中ApplicationContext是BeanFactory的子接口。他们都可代表Spring容器,Spring容器是生成Bean实例的工厂,并管理容器中的Bean。Bean是Spring管理的基本单位,再给予Spring的Java EE应用中,所有的组件都被当成Bean处理,包括数据源、Hibernate的SessionFactory、事务管理器等。
Spring容器:
Spring容器最基本的接口就是BeanFactory。BeanFactory负责配置、创建、管理Bean,他有一个子接口;ApplicationContext,因此也被称为Spring上下文。Spring容器还负责管理Bean与Bean之间的依赖关系。
使用ApplicationContext
大部分的时候我们都不会使用BeanFactory实例作为Spring容器,而是使用ApplicationContext实例作为容器。因此我们也把spring容器也叫作Spring上下文。ApplicationContext是BeanFactory接口的子接口,它增强了BeanFactory的功能。
ApplicationContext的事件机制:
APplicationContext的事件机制是观察者设计模式的实现,通过ApplicationEvent类和ApplicationListener接口,可以实现ApplicationContext的事件处理。如果容器中有一个ApplicationListen Bean,每当ApplicationContext发布ApplicationEvent时,ApplicationListener Bean将自动被触发。
实际上,Spring的事件机制与所有事件机制都基本都基本相似,他们都需要事件源、事件和事件监听器组成,只是此处的事件源是ApplicationContext,且事件必须由java程序显式触发。
让Bean获取Spring容器:
在实际应用中,Spring容器通常采用声明式方式配置产生:开发者只要在web.xml文件中配置一个Listener,该Listener将会负责初始化Spring容器。前端MVC框架可以直接调用Spring容器。在这种情况下,容器中的Bean处于容器管理下,无须主动访问容器,只需接受容器的注入管理即可。Bean实例的依赖关系通常由容器动态注入,无须Bean实例主动请求。
实现BeanFactoryAware接口的Bean,拥有访问BeanFactory容器的能力,改实例被容器创建后,它会拥有一个引用,该引用指向创建它的BeanFactory。BeanFactoryAware接口只有如下一个方法:
Spring容器中的Bean:
<beans.../>
元素是Spring配置文件的根元素,该元素可以指定如下属性。
容器中Bean的作用域
当通过Spring容器创建一个Bean实例时,不仅可以完成Bean实例的实例化,还可以为Bean指定特定的作用域。Spring支持以下5种作用域:
Spring3.0提供的Java配置管理:
Java配置类的三个常用的Annotation。
混合使用XML配置和Java类配置:
如果以XML配置为主,就需要让XML配置能加载Java类配置。
如果以Java类配置为主,就需要让Java配置类能加载XML配置。这就使用@ImportResource,这个annotation可修饰Java配置类,用于导入指定的XML配置文件。
容器中Bean的生命周期:
Spring可以管理singleton作用域Bean的生命周期,Spring可以精确地知道该Bean何时被创建、何时被初始化完成、容器何时准备销毁该bean实例。
对于prototype作用域的Bean,Spring容器仅仅负责创建,当容器创建了Bean实例之后,Bean实例完全交给客户端代码管理,容器不再跟踪其生命周期。