Spring概述(2)———IOC和DI

IOC和DI
2.1.1 IOC(Inversion of Control):反转控制
在应用程序中的组件需要获取资源时,传统的方式是组件主动的从容器中获取所需要的资源,在这样的模式下开发人员往往需要知道在具体容器中特定资源的获取方式,增加了学习成本,同时降低了开发效率。
反转控制的思想完全颠覆了应用程序组件获取资源的传统方式:反转了资源的获取方向——改由容器主动的将资源推送给需要的组件,开发人员不需要知道容器是如何创建资源对象的,只需要提供接收资源的方式即可,极大的降低了学习成本,提高了开发的效率。这种行为也称为查找的被动形式。

2.1.2 DI(Dependency Injection):依赖注入
IOC的另一种表述方式:即组件以一些预先定义好的方式(例如:setter 方法)接受来自于容器的资源注入。相对于IOC而言,这种表述更直接。
IOC描述的是一种思想 , 而DI是对IOC思想的具体实现。

2.1.3 IOC容器在Spring中的实现 (也就是创建IOC本身的对象)
1)在通过IOC容器读取Bean的实例之前,需要先将IOC容器本身实例化。
2)Spring提供了IOC容器的两种实现方式
① BeanFactory:IOC容器的基本实现,是Spring内部的基础设施,是面向Spring本身的,不是提供给开发人员使用的。
② ApplicationContext:BeanFactory的子接口,提供了更多高级特性。面向Spring的使用者,几乎所有场合都使用ApplicationContext而不是底层的BeanFactory

在这里插入图片描述

2.1.4 ApplicationContext的主要实现类
1)ClassPathXmlApplicationContext:对应类路径下的XML格式的配置文件
2)FileSystemXmlApplicationContext:对应文件系统中的XML格式的配置文件
3)在初始化时就创建单例的bean,也可以通过配置的方式指定创建的Bean是多实例的。

2.1.5 ConfigurableApplicationContext
1)是ApplicationContext的子接口,包含一些扩展方法
2)refresh()和close()让ApplicationContext具有启动、关闭和刷新上下文的能力。

2.1.6 WebApplicationContext
1)专门为WEB应用而准备的,它允许从相对于WEB根目录的路径中完成初始化工作

2.2 通过类型获取bean(三种,优缺点自己总结上)
1)通过id值获取 ,需要类型的强制转换
2)从IOC容器中获取bean时,除了通过id值获取,还可以通过bean的类型获取。但如果同一个类型的bean在XML文件中配置了多个,则获取时会抛出异常(NoUniqueBeanDefinitionException),所以同一个类型的bean在容器中必须是唯一的。
HelloWorld helloWorld = cxt.getBean(HelloWorld. class);
3)或者可以使用另外一个重载的方法,同时指定bean的id值和类型
HelloWorld helloWorld = cxt.getBean(“helloWorld”,HelloWorld. class);

2.3 给bean的属性赋值
2.3.1 依赖注入的方式

  1. 通过bean的setXxx()方法赋值
    Hello World中使用的就是这种方式

在这里插入图片描述
2. 通过bean的构造器赋值
1)Spring自动匹配合适的构造器

  <bean id="book" class="com.atguigu.spring.bean.Book" >
           <constructor-arg value= "10010"/>
           <constructor-arg value= "Book01"/>
           <constructor-arg value= "Author01"/>
           <constructor-arg value= "20.2"/>
     </bean >

2)通过索引值指定参数位置

     <bean id="book" class="com.atguigu.spring.bean.Book" >
           <constructor-arg value= "10010" index ="0"/>
           <constructor-arg value= "Book01" index ="1"/>
           <constructor-arg value= "Author01" index ="2"/>
           <constructor-arg value= "20.2" index ="3"/>
     </bean >

3)通过类型区分重载的构造器


<bean id="book" class="com.atguigu.spring.bean.Book" >
      <constructor-arg value= "10010" index ="0" type="java.lang.Integer" />
      <constructor-arg value= "Book01" index ="1" type="java.lang.String" />
      <constructor-arg value= "Author01" index ="2" type="java.lang.String" />
      <constructor-arg value= "20.2" index ="3" type="java.lang.Double" />
</bean >

2.3.2 p名称空间
为了简化XML文件的配置,越来越多的XML文件采用属性而非子元素配置信息。Spring 从2.5版本开始引入了一个新的p命名空间,可以通过元素属性的方式配置Bean 的属性。
使用p命名空间后,基于XML的配置方式将进一步简化。

<bean>
	id="studentSuper" 
	class="com.atguigu.helloworld.bean.Student"
	p:studentId="2002" p:stuName="Jerry2016" p:age="18" />
</bean>

2.3.3 可以使用的值

  1. 字面量 (与其相对的应该是非字面量吧?)
    1)可以使用字符串表示的值,可以通过value属性或value子节点的方式指定
    2)基本数据类型及其封装类、String等类型都可以采取字面值注入的方式
    3)若字面值中包含特殊字符,可以使用<![CDATA[]]>把字面值包裹起来
  2. null值

 <bean class="com.atguigu.spring.bean.Book" id="bookNull" >
           <property name= "bookId" value ="2000"/>
           <property name= "bookName">
               <null/>
           </property>
           <property name= "author" value ="nullAuthor"/>
           <property name= "price" value ="50"/>
     </bean >

*推荐上图这种用标签的方式,如果是引用类对象有多个成员变量的,value就不能对应多个值了。不推荐下图这种用元素属性的方式。

  <bean class="com.atguigu.spring.bean.Book" id="bookNull" >
           <property name= "bookId" value ="2000"/>
           <property name= "bookName" value=”null”></property>
           <property name= "author" value ="nullAuthor"/>
           <property name= "price" value ="50"/>
     </bean >

*用构造器给参数赋值的形式,也可以用null值

<bean id="student8" class="spring.Student">
		<constructor-arg value="1008" type="Integer" />
		<constructor-arg  type="String"><null/></constructor-arg>
		<constructor-arg value="33" type="int"/>
		<constructor-arg value="" type="char"></constructor-arg>
		<constructor-arg  ref="car" />
		
	</bean>

  1. 给bean的级联属性赋值
 <bean id="action" class="com.atguigu.spring.ref.Action">
          <property name="service" ref="service"/>
          <!-- 设置级联属性(了解) -->
          <property name="service.dao.dataSource" value="DBCP"/>
     </bean>
  1. (引用)外部已声明的bean
  <bean id="shop" class="com.atguigu.spring.bean.Shop" >
           <property name= "book" ref ="book"/>
     </bean >
  1. 内部bean
    当bean实例仅仅给一个特定的属性使用时,可以将其声明为内部bean。内部bean声明直接包含在或元素里,不需要设置任何id或name属性
    内部bean不能使用在任何其他地方
<bean id="shop2" class="com.atguigu.spring.bean.Shop" >
    <property name= "book">
        <bean class= "com.atguigu.spring.bean.Book" >
           <property name= "bookId" value ="1000"/>
           <property name= "bookName" value="innerBook" />
           <property name= "author" value="innerAuthor" />
           <property name= "price" value ="50"/>
        </bean>
    </property>
</bean >

FactoryBean
Spring中有两种类型的bean,一种是普通bean,另一种是工厂bean,即FactoryBean。
工厂bean跟普通bean不同,其返回的对象不是指定类的一个实例,其返回的是该工 厂bean的getObject方法所返回的对象。
工厂bean必须实现org.springframework.beans.factory.FactoryBean接口。

在这里插入图片描述

<bean id="product" class="com.atguigu.spring.bean.ProductFactory">
	<property name="productName" value="Mp3" />
</bean>

bean的高级配置
2.6.1 配置信息的继承

  1. 背景
    查看下面两个Employee的配置,其中dept属性是重复的。
<bean id="dept" class="com.atguigu.parent.bean.Department">
	<property name="deptId" value="100"/>
	<property name="deptName" value="IT"/>
</bean>
<bean id="emp01" class="com.atguigu.parent.bean.Employee">
	<property name="empId" value="1001"/>
	<property name="empName" value="Tom"/>
	<property name="age" value="20"/>

	<!-- 重复的属性值 -->	
	<property name="dept" ref="dept"/>
</bean>


<bean id="emp02" class="com.atguigu.parent.bean.Employee">
	<property name="empId" value="1002"/>
	<property name="empName" value="Jerry"/>
	<property name="age" value="25"/>

	<!-- 重复的属性值 -->
	<property name="dept" ref="dept"/>
</bean>

  1. 配置信息的继承
<!-- 以emp01作为父bean,继承后可以省略公共属性值的配置 -->
<bean id="emp02" parent="emp01">
	<property name="empId" value="1002"/>
	<property name="empName" value="Jerry"/>
	<property name="age" value="25"/>
</bean>
Spring允许继承bean的配置,被继承的bean称为父bean。继承这个父bean的bean	称为子bean
子bean从父bean中继承配置,包括bean的属性配置
子bean也可以覆盖从父bean继承过来的配置
  1. 补充说明
    父bean可以作为配置模板,也可以作为bean实例。若只想把父bean作为模板,可以设置的abstract 属性为true,这样Spring将不会实例化这个bean
    如果一个bean的class属性没有指定,则必须是抽象bean
    并不是元素里的所有属性都会被继承。比如:autowire,abstract等。
    也可以忽略父bean的class属性,让子bean指定自己的类,而共享相同的属性配置。 但 此时abstract必须设为true。

2.6.2 bean之间的依赖
有的时候创建一个bean的时候需要保证另外一个bean也被创建,这时我们称前面的bean对后面的bean有依赖。例如:要求创建Employee对象的时候必须创建Department。 这里需要注意的是依赖关系不等于引用关系,Employee即使依赖Department也可以不引用它。

<bean id="emp03" class="com.atguigu.parent.bean.Employee" depends-on="dept">
	<property name="empId" value="1003"/>
	<property name="empName" value="Kate"/>
	<property name="age" value="21"/>
</bean>

2.7 bean的作用域★
在Spring中,可以在元素的scope属性里设置bean的作用域,以决定这个bean是单实例的还是多实例的。
默认情况下,Spring只为每个在IOC容器里声明的bean创建唯一一个实例,整个IOC容器范围内都能共享该实例:所有后续的getBean()调用和bean引用都将返回这个唯一的bean实例。该作用域被称为singleton,它是所有bean的默认作用域。在这里插入图片描述
当bean的作用域为单例时,Spring会在IOC容器对象创建时就创建bean的对象实例。而当bean的作用域为prototype时,IOC容器在获取bean的实例时创建bean的实例对象。

bean的生命周期
1)Spring IOC容器可以管理bean的生命周期,Spring允许在bean生命周期内特定的时间点执行指定的任务。
2)Spring IOC容器对bean的生命周期进行管理的过程:
① 通过构造器或工厂方法创建bean实例
② 为bean的属性设置值和对其他bean的引用
③ 调用bean的初始化方法
④ bean可以使用了
⑤ 当容器关闭时,调用bean的销毁方法
3)在配置bean时,通过init-method和destroy-method 属性为bean指定初始化和销毁方法
4)bean的后置处理器
① bean后置处理器允许在调用初始化方法前后对bean进行额外的处理
② bean后置处理器对IOC容器里的所有bean实例逐一处理,而非单一实例。其典型 应用是:检查bean属性的正确性或根据特定的标准更改bean的属性。
③ bean后置处理器时需要实现接口:
org.springframework.beans.factory.config.BeanPostProcessor。在初始化方法被调用前后,Spring将把每个bean实例分别传递给上述接口的以下两个方法:
●postProcessBeforeInitialization(Object, String)
●postProcessAfterInitialization(Object, String)
5)添加bean后置处理器后bean的生命周期
①通过构造器或工厂方法创建bean实例
②为bean的属性设置值和对其他bean的引用
③将bean实例传递给bean后置处理器的postProcessBeforeInitialization()方法
④调用bean的初始化方法
⑤将bean实例传递给bean后置处理器的postProcessAfterInitialization()方法
⑥bean可以使用了
⑦当容器关闭时调用bean的销毁方法

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值