spring-bean的理解

来源:互联网 发布:java装饰模式和注解 编辑:程序博客网 时间:2024/06/02 13:13

我们使用Spring框架所做的就是两件事:开发Bean、配置Bean。对于Spring矿建来说,它要做的就是根据配置文件来创建Bean实例,并调用Bean实例的方法完成“依赖注入”。

Bean通常被定义在配置文件当中,Bean实例化由Spring的Ioc容器进行管理,Bean的实例可以通过Beanfactory进行访问,实际上大部分J2EE应用,Bean是通过ApplicationContext来访问的,ApplicationContext是BeanFactory的子接口,功能要比BeanFactory强大许多。

ApplicationContext

  • 读取Bean定义文件
  • 维护Bean之间的依赖关系
  • 国际化的支持
  • 资源文件的读取getRource()方法可以轻松读取Rource对象
  • 事件传播
  • 多配置文件加载

Bean 的定义

基本组成

配置文件

<?xml version="1.0" encoding="UTF-8"?>  <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-3.0.xsd">      <!-- 定义第一个Bean实例:bean1 -->      <bean id="bean1" class="com.Bean1" />      <!-- 定义第二个Bean实例:bean2 -->      <bean id="bean2" class="com.Bean2" />  </bean>  

id:用来指明bean的标识符,这个标识符具有唯一性,Spring对bean的管理以及bean之间这种依赖关系都需要这个属性
class: 指明该bean的具体实现类,这里不能是接口(可以是接口实现类)全路径包名.类名
Bean在Spring容器中两种行为(通过scope来设置默认不写为singelton)
singleton:单实例模式(默认,构造方法为private),整个Spring的容器中只有一个共享实例存在(singleton)
non-singelton:每次请求该bean,Spring容器都会新建立一个bean实例,然后返回给程序(request,session,prototype)

创建Bean步骤

创建XML文件—-写入配置信息—生成Bean类—-加入Bean到配置文件

注入Bean

-ref元素进行标识
Ref元素通常有两个属性:
bean:指定不在同一个XML文件中的bean的id

<bean id="test" class="com.pb.test"><property name="user"><ref bean="其他的bean的id"/></property></bean></bean>

value和ref的区别:

使用ref元素,可以让Spring在部署时验证依赖的Bean是否真实存在
使用value元素,进行指定仅在创建Bean实例时做验证,会导致错误的延时出现,而且还会带来额外的类型转制开销

集合注入(了解 list,map, props,set)

<bean id="test" class="com.pb.test">        <property name="lists">        <list>        <value>1</value>        <value>2</value>        <value>3</value>        </list>        </property>    </bean><bean id="test" class="com.pb.test">        <property name="map">            <map>                <entry key="key1">                    <value>value1</value>                </entry>                <entry key="key2">                    <value>key2</value>                </entry>            </map>        </property>    </bean><bean id="test" class="com.pb.test"><property name="props"><props><prop key="key1">value1</prop><prop key="key2">value2</prop></props></property></bean><bean>< property  name ="interest" >                 < set >                     < value > 唱歌 </ value >                     < value > 跳舞 </ value >                     < value > 书法 </ value >                 </ set >        </ property >    </bean>

容器中Bean的生命周期

Spring可以管理singleton作用域Bean的生命周期,Spring可以精确地知道singleton域bean何时被创建,何时初始化完成,以及容器何时准备销毁Bean实例。因为,对于singleton作用域的Bean,客户端的每次请求都返回同一个Bean实例,客户端代码不能控制Bean的销毁,它的生命周期都在Spring的掌握之中。这么一来,容器就可以管理实例化结束后(某些资源的申请)和销毁之前(进行某些资源的回收)的行为。管理Bean的生命周期行为主要有两个时机:注入依赖关系后,销毁实例之前;具体的管理方法如下

Spring提供两种方式在Bean全部属性设置成功后执行特定行为

使用init-method 属性(代码污染小)
在类中编写一个方法,在属性中指定该方法在依赖关系设置完成后自动执行。
实现InitializingBean接口(耦合较高)
编写afterPropertiesSet()方法的具体实现
同理,若在Bean销毁之前,执行特定的方法,只需要①使用 destroy-method属性②实现DisposableBean接口(实现destroy()方法)

对于prototype作用域的Bean,Spring容器只负责Bean的创建,当容器创建实例完成后,Bean将完全交给客户端代码管理,容器不再负责其生命周期。每次客户端请求prototype作用域的Bean时,Spring容器都会产生一个全新的Bean实例交个客户端(prototype就是这么任性),Spring容器本省也不知道自己创建了多少个实例,更无从知道这些实例什么时候才会被销毁。

Spring 的 Bean 和 JavaBean比较

  • 规范:Spring容器对Bean 没有特殊要求,不像JavaBean 一样遵循一些规范(为每个属性提供相应的setter 和 getter 方法),不过对于设值注入的Bean,一定要提供setter 方法。
  • 作用:Spring 中的Bean 是 java 实例,java组件,它的作用几乎无所不包,任何应用组件都被称为Bean,而传统的Java应用中的JavaBean通常作为DTO(数据传输对象),来封装值对象,在各层之间传递数据。
  • 生命周期:传统的JavaBean作为值对象传递,不接受任何容器管理其生命周期,Spring中的Bean有Spring管理其生命周期行为。

Spring 的Bean继承和java继承的区别

Spring中子Bean和父Bean可以是不同的类型,而java中的继承子类只是父类的一种特殊类型。
Spring中Bean的继承是实例之间的关系,主要表现为参数值的延续,而java终的继承是类之间的关系,主要表现为属性,方法的延续。

Spring中子Bean不可做父Bean使用,不具备多态性,java中的子类实例完全可以做父类的实例使用

Bean 实例的创建方式及依赖配置

大多数情况下,BeanFactory 直接通过new 关键字调用构造器来创建Bean 实例,而class属性指定了Bean实例的实现类。但这并不是实例化Bean的唯一方法。

创建Bean通常有以下三种方式
- 调用构造器创建Bean 实例
- 调用静态工厂方法创建Bean
- 调用实例工厂方法创建Bean

调用构造器创建Bean 实例

调用构造器创建Bean实例是最常见的情况,,BeanFactory 将使用默认的构造器来创建Bean实例,该实例是个默认实例,Spring对Bean实例的所有属性执行默认初始化,即所有基本类型的值初始化为0或false,引用类型初始化为null,接下来BeanFactory会根据配置文件决定依赖关系,先实例化被依赖的Bean 实例,然后为Bean注入依赖关系,最后将一个完整的Bean实例返回给程序,该Bean实例化的所有属性,已经由Spring容器完成了初始化。

使用静态工厂方法创建Bean

使用静态工厂方法创建Bean实例时,class属性也必须指定,但此时class属性并不是指定Bean实例的实现类,而是静态工厂类,Spring需要根据工厂类的工厂方法来创建Bean实例,除此之外,还需要使用factory-method 属性来指定静态工厂方法名,Spring调用静态工厂方法(可能包含一组参数,若需要,使< constructor-arg…/>元素传入)返回一个Bean实例,获得Bean实例后,Spring后面的处理步骤与采用普通方法创建Bean实例完全一样。

使用静态工厂方法创建Bean实例时,Spring将先解析配置文件,并根据配置文件指定的信息,通过反射调用静态工厂类的静态工厂方法,将该静态工厂方法的凡湖值作为Bean实例。在这个过程中,Spring不再负责创建Bean实例,Bean实例的创建是用户提供的静态工厂类负责创建的。但是Spring容器依然可以管理Bean实例的依赖关系,生命周期。

使用实例工厂方法

实例工厂方法与静态工厂方法不同:调用静态工厂方法只需使用工厂类,调用实例工厂方法则必须使用工厂实例。采用实例工厂方法时,配置Bean实例的< bean../>元素无需class属性,因为Spring容器不再直接实例化该Bean,Spring容器仅仅调用实例工厂的工厂方法,工厂方法负责创建Bean实例。采用实例工厂方法创建Bean时,需要为< bean../>元素指定如下两个属性:factory-bean:该属性的值为工厂Bean的id.factory-method:该属性指定实例工厂的工厂方法。与静态工厂方法相似,如果需要调用工厂方法时传入参数,使用< constructor-arg…/>元素确定参数值。

静态工厂方法创建实例和工厂方法创建实例的异同点:

调用实例工厂方法创建Bean,必须将实例工厂配置成Bean实例。而静态工厂方法创建Bean,则无需配置工厂Bean。

调用实例工厂方法创建Bean,必须使用factory-bean属性确定工厂Bean。而静态工厂方法创建Bean,则使用class 元素确定静态工厂类。

都需要factory-method 指定相应产生Bean实例的工厂方法。

工厂方法需要参数都可以使用< constructor-art…/>元素指定参数。