5. Bean的介绍

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Stream_who/article/details/83957150

一、Bean定义

1. 基本组成

1)配置文件

	<beans/>是Sring配置文件的根节点,一个<beans/>节点里面可以有多个<bean>节点
	
2)<bean/>常用属性

	id:用来指明bean的标识符,这个标识符具有唯一性,Spring对bean的管理以及bean之间这种依赖关系都需要这个属性	
	class: 指明该bean的具体实现类,全路径包名.类名
	
3)Bean在Spring容器中两种行为(通过scope来设置默认不写为singelton)

	singleton:单实例模式(默认,构造方法为private),整个Spring的容器中只有一个共享实例存在(singleton)
	non-singelton:每次请求该bean,Spring容器都会新建立一个bean实例,然后返回给程序(request,session,prototype)	

2. 创建Bean

1)Bean的命名机制(id---------->name--------------->类名)

	id 当在Spring的窗口当中,查找某个Bean对象时,首先根据id进行查找,将其余作为Bean的默认名称,如果ID属性不存在,则根据Name属性进行查找(将其中的第一个名称作为默认的名称),如果ID和NAME都不存在根据类的名称进行查找
	
2)Bean的别名

	<alias name="指定关联的Bean的名称fromname" alias="该关联类的别名的名称toname"/>

3. 创建Bean步骤

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


二、Bean注入参数详解

1. 基本类型和String(三种方式)

1)	<bean id="FileNameGenerator" class="com.lei.common.FileNameGenerator">
        <property name="name">
            <value>lei</value>
        </property>
        <property name="type">
            <value>txt</value>
        </property>
	 </bean>

2)	<bean id="FileNameGenerator" class="com.lei.common.FileNameGenerator">
        <property name="name" value="lei" />
        <property name="type" value="txt" />
	 </bean>

3)	<bean id="FileNameGenerator" class="com.lei.common.FileNameGenerator" p:name="lei" p:type="txt" />

2. 集合注入

<bean id="test" class="com.pb.test">
    <property name="lists">
        <list>
	        <value>1</value>
	        <value>2</value>
	        <value>3</value>
        </list>
    </property>
</bean>

3. set

<bean id="test" class="com.pb.test">
    <property name="lists">
        <set>
	        <value>1</value>
	        <value>2</value>
	        <value>3</value>
        </set>
    </property>
</bean>	

4. map

<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>

5. props

<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的依赖注入方式

1. Setter注入

<bean id="helloWorld" class="com.jdw.spring.beans.HelloWorld">
    <property name="name" value="Spring"></property>
</bean>

1)class属性需要全类名进行配置,说了ioc容器是通过反射进行创建bean的

2)bean类必须有默认的构造函数

2. 构造器注入

<bean id="car" class="com.jdw.spring.beans.Car">
    <constructor-arg value="audi" type="java.lang.String"></constructor-arg>
    <constructor-arg type="java.lang.String">
        <!-- 对于包含特殊字符的属性值,可以在value子节点使用CDATA -->
        <value><![CDATA[<shanghai>]]></value>
    </constructor-arg>
    <constructor-arg type="int">
        <value>240</value>
    </constructor-arg>
</bean>

1)构造器注入,言外之意,需要在bean之中配置构造器,可以不需要默认构造方法,但是必须保证构造器参数与配置文件中的参数数量和类型一致

2)于有多个构造器的bean,可通过下列的index和type属性进行配置,以区别重载的构造器

<bean id="car1" class="com.jdw.spring.beans.Car">
    <constructor-arg value="audi" index="0" type="java.lang.String"></constructor-arg>
    <constructor-arg value="shanghai" index="1" type="java.lang.String"></constructor-arg>
    <constructor-arg value="200000" index="2" type="double"></constructor-arg>
</bean>

3. 工厂方法注入

1)静态工厂方法注入
<bean id="car" class="com.jdw.spring.factory.StaticCarFactory" factory-method="getCar">
    <constructor-arg value="audi"></constructor-arg>
</bean>

(1)所谓静态工厂方法注入,不过是通过一个静态方法创建bean的实例

(2)在singelton情况下该静态方法只会在ioc容器初始化bean时调用一次,即不管getBean("car")多少次,都是返回的同一个Car对象

(3)而在prototype情况下,getBean("car")调用一次就会对应的调用一次静态方法getCar
2) 实例工厂方法注入
<!-- 配置实例工厂 -->
<bean id="carFactory" class="com.jdw.spring.factory.InstanceCarFactory"></bean>
 
<!-- 通过实例工厂配置bean -->
<bean id="car1" factory-bean="carFactory" factory-method="getCar">
    <constructor-arg name="brand" value="audi"></constructor-arg>
</bean>

(1)实例工厂的getCar为非静态,这就导致,必须先实例化该工厂,即需要配置该工厂的bean

四、之间的关系

1. 继承关系

  • 1)在面向对象的编程原理中,当多个类拥有相同的方法和属性,则可以引入父类消除代码重复

  • 2)在Spring容器中,如果多个Bean存在相同的配置信息,同样可以定义一个父Bean,子Bean将自动继承父Bean的配置信息

  • 3)父bean中的所有属性值也会出现在子bean当中,那么假如子bean当中配置了父bean已有的属性的话,会覆盖掉父bean中的配置

  • 4)配置为父bean的bean当中的abstract属性值得赋值为true

  • 5)若想父bean只是作为一个模板,可以设置的abstract属性为true,IOC容器将不会实例化这个bean。若直接获得,则会报一个BeanIsAbstractException的异常

  • 6)示例

(1)未使用父子<bean>的配置(两个car bean除了color属性不同之外,其他属性都是完全一样的)

	<bean id=“car1” class=“cn.lovepi.***.Car” p:brand=“奔驰E300” p:price=“2000” p:color=“黑色”/>
	<bean id=“car1” class=“cn.lovepi.***.Car” p:brand=“奔驰E300” p:price=“2000” p:color=“红色”/>

(2)使用父子<bean>的配置	

	<bean id=“abstractCar” class=“cn.lovepi.***.Car” p:brand=“奔驰E300” p:price=“2000” p:color=“黑色” abstract=“true”/>
	<bean id=“car1” p:color=“红色” parent=“abstractCar” />
	<bean id=“car1” p:color=“白色” parent=“abstractCar” />

2. 依赖关系

  • 1) 在Spring容器中,当使用depends-on标签建立对其他Bean的依赖关系时,Spring容器负责管理这些Bean的关系,当实例化一个Bean时,容器保证该Bean所依赖的Bean已经初始化

  • 2) 如果前置依赖多个Bean,可以通过逗号或空格方式配置Bean名称

  • 3) 示例:

<bean id=“manager” class=“cn.lovepi.***.CacheManager” depends-on=“sysInit”/>
<bean id=“sysInit” class=“cn.lovepi.***.SysInit” />

3. 引用关系

  • 1)在Spring容器中,当使用标签引用另外一个Bean时,但实际上两者并没有建立引用关系,即使我们编写错误,也需要在运行期才可以发现

  • 2)因此Spring提供了元素标签,通过引用另一个Bean的名字,可以在容器启动的时候,检查引用关系的正确性,这样可以提前发现错误的配置信息

  • 3)常规配置方法

<bean id=“car” class=“cn.lovepi.***.Car”/>
<bean id=“boss” class=“cn.lovepi.***.Boss” p:carId=“car” scope=“prototype” />
  • 4)配置方法
<bean id=“car” class=“cn.lovepi.***.Car”/>
<bean id=“boss” class=“cn.lovepi.***.Boss” >
      <property name=“carId”>
             <idref bean=“car”/>
      </property>
</bean>

五、Bean的作用域(的scope属性)

1. singleton(单例模式):spring容器只会存在一个共享的bean实例,并且所有针对该bean的请求只会返回同一个bean实例

2. propertype(no-singleton): 对每一次针对该bean的请求都会生成一个新的bean实例。 相当于java中的new 操作。定义为propertype的bean其生命周期很长,不易回收,通常要额外的处理

3. request:针对每一次的http请求都会产生一个新的bean实例,Bean仅在当前的http request范围内有效

4. session:限定一个Bean的作用域为HTTPsession的生命周期。同样,只有基于web的Spring ApplicationContext才能使用

5. global session:限定一个Bean的作用域为全局HTTPSession的生命周期。通常用于门户网站场景,同样,只有基于web的Spring ApplicationContext可用

六、Bean的生命周期

在这里插入图片描述

1. 生命周期

1)BeanFactoryPostProcessor的postProcessorBeanFactory()方法:若某个IoC容器内添加了实现了BeanFactoryPostProcessor接口的实现类Bean,那么在该容器中实例化任何其他Bean之前可以回调该Bean中的postPrcessorBeanFactory()方法来对Bean的配置元数据进行更改,比如从XML配置文件中获取到的配置信息

2)Bean的实例化:Bean的实例化是使用反射实现的

3)Bean属性注入:Bean实例化完成后,利用反射技术实现属性及依赖Bean的注入

4)BeanNameAware的setBeanName()方法:如果某个Bean实现了BeanNameAware接口,那么Spring将会将Bean实例的ID传递给setBeanName()方法,在Bean类中新增一个beanName字段,并实现setBeanName()方法

5)BeanFactoryAware的setBeanFactory()方法:如果某个Bean实现了BeanFactoryAware接口,那么Spring将会将创建Bean的BeanFactory传递给setBeanFactory()方法,在Bean类中新增了一个beanFactory字段用来保存BeanFactory的值,并实现setBeanFactory()方法

6)ApplicationContextAware的setApplicationContext()方法:如果某个Bean实现了ApplicationContextAware接口,那么Spring将会将该Bean所在的上下文环境ApplicationContext传递给setApplicationContext()方法,在Bean类中新增一个ApplicationContext字段用来保存ApplicationContext的值,并实现setApplicationContext()方法

7)BeanPostProcessor预初始化方法:如果某个IoC容器中增加的实现BeanPostProcessor接口的实现类Bean,那么在该容器中实例化Bean之后,执行初始化之前会调用BeanPostProcessor中的postProcessBeforeInitialization()方法执行预初始化处理

8)InitializingBean的afterPropertiesSet()方法:如果Bean实现了InitializingBean接口,那么Bean在实例化完成后将会执行接口中的afterPropertiesSet()方法来进行初始化

9)自定义的inti-method指定的方法:如果配置文件中使用init-method属性指定了初始化方法,那么Bean在实例化完成后将会调用该属性指定的初始化方法进行Bean的初始化

10)BeanPostProcessor初始化后方法:如果某个IoC容器中增加的实现BeanPostProcessor接口的实现类Bean,那么在该容器中实例化Bean之后并且完成初始化调用后执行该接口中的postProcessorAfterInitialization()方法进行初始化后处理

11)使用Bean:此时有关Bean的所有准备工作均已完成,Bean可以被程序使用了,它们将会一直驻留在应用上下文中,直到该上下文环境被销毁

12)DisposableBean的destory()方法:如果Bean实现了DisposableBean接口,Spring将会在Bean实例销毁之前调用该接口的destory()方法,来完成一些销毁之前的处理工作

13)自定义的destory-method指定的方法:如果在配置文件中使用destory-method指定了销毁方法,那么在Bean实例销毁之前会调用该指定的方法完成一些销毁之前的处理工作

2. 各种接口方法分类

1)Bean自身的方法: 这个包括了Bean本身调用的方法和通过配置文件中<bean>的init-method和destroy-method指定的方法

2)Bean级生命周期接口方法: 这个包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这些接口的方法

3)容器级生命周期接口方法: 这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。

4)工厂后处理器接口方法: 这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用

3. 注意

1)BeanFactoryPostProcessor接口与BeanPostProcessor接口的作用范围是整个上下文环境中,使用方法是单独新增一个类来实现这些接口,那么在处理其他Bean的某些时刻就会回调响应的接口中的方法

2)BeanNameAware、BeanFactoryAware、ApplicationContextAware的作用范围的Bean范围,即仅仅对实现了该接口的指定Bean有效,所有其使用方法是在要使用该功能的Bean自己来实现该接口

3)第8点与第9点所述的两个初始化方法作用是一样的,我们完全可以使用其中的一种即可,一般情况我们使用第9点所述的方式,尽量少的去来Bean中实现某些接口,保持其独立性,低耦合性,尽量不要与Spring代码耦合在一起。第12和第13也是如此(InitializingBean和DisposableBean属于侵入性设计不建议使用)

参考网址

Spring(二)Bean入门

Spring3系列5-Bean的基本用法

spring4之依赖注入的三种方式

Spring学习(二十)Bean 的依赖关系介绍

Spring中Bean的生命周期及其扩展点

注:文章是经过参考其他的文章然后自己整理出来的,有可能是小部分参考,也有可能是大部分参考,但绝对不是直接转载,觉得侵权了我会删,我只是把这个用于自己的笔记,顺便整理下知识的同时,能帮到一部分人。
ps : 有错误的还望各位大佬指正,小弟不胜感激

猜你喜欢

转载自blog.csdn.net/Stream_who/article/details/83957150