Spring总结一:IOC与Bean注入

Spring 是什么?

  • Spring 是一个开源框架
  • Spring 为简化企业级应用开发而生。使用 Spring 可以使简单的 JavaBean 实现以前之后 EJB 才能实现的功能。
  • Spring 是一个 IOC(DI)和 AOP 容器框架。
  • 具体描述 Spring
  • 轻量级:Spring 是非侵入性的,基于 Spring 开发的应用中的对象可以不依赖 Spring 的 API
  • 依赖注入(DI — dependency injection、IOC)
  • 面向切面编程(AOP — aspect original programming)
  • 容器:Spring 是一个容器,因为它包含并且管理应用对象的生命周期
  • 框架:Spring 实现了使用简单的组件配置组合成一个复杂的应用。在 Spring 中可以使用 XML 和 Java 注解组合这些对象
  • 一站式:在 IOC 和 AOP 的基础上可以整合各种企业应用的开源框架和优秀的第三方类库(实际上 Spring 自身也提供了展现层的 SpringMVC 和 持久层 的 Spring JDBC)
  • Spring 的配置文件:一个典型的 Spring 项目需要创建一个或多个 Bean 配置文件,这些配置文件用于在 Spring IOC 容器里配置 Bean。 Bean 的配置文件可以放在 classpath下,也可以放在其他目录下。
  • 本文及以后的文章,所使用的版本是Spring4.x

IOC & DI 概述

Spring 的核心是控制反转(IOC)和面向切面(AOP)。

  • IOC(Inversion of Control):其思想是反转资源获取的方向。传统的资源查找方式要求组件向容器发起请求查找资源,作为回应,容器适时的返回资源。而应用了 IOC 之后,则是**容器主动的将资源推送给它所管理的组件,组件所要做的是选择一种合适的方式来接受资源。**这种行为也被称为查找的被动形式
  • DI(dependency Injection)–IOC 的另一种表述方式:即**组件以一些预定好的方式(例如setter方法)接受来自如容器的资源注入。**相对于 IOC 而言,这种表述更为直接

IOC即Inversion of Control,翻译过来就是控制反转。啥是控制反转啊?控制反转指的就是将对象的创建权反转给(交给)了Spring,其作用是实现了程序的解耦合。也可以说是获取对象的方式变了,对象创建的控制权不是"使用者",而是容器。这种方式不类似于以前写程序主动请求资源(new 对象的方式),而是我们通过配置将所需要的资源请求告诉容器,Spring 容器在创建过程中会将我们需要的资源交给我们,即依赖注入,各种资源是由容器创建并交给程序,反转了资源获取的方向,即控制反转。用更通俗的话来说,IOC就是指对象的创建,并不是在代码中用new出来的,而是通过Spring进行配置创建的。

IOC的底层原理就是工程模式+反射+XML配置文件。

AOP:即面向切面编程。Spring 后续总结中我再仔细讲,本文不会过多阐述它。
轻量级框架Spring的优点:
1、Spring的依赖注入将对象之间的依赖关系交给了框架来处理,减小了各个组件之间的耦合性;
2、AOP面向切面编程,可以将通用的任务抽取出来,复用性更高;
3、Spring对于其余主流框架都提供了很好的支持,代码的侵入性很低。

Spring 的XML配置文件一般是在 schema 约束下编写的,一般我们把配置文件创建在 src下,命名为applicationContext.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">
</beans>

所有的配置都要在beans标签内写,这是 Spring 配置文件的根元素。

在 Spring 的 IOC 容器里配置 Bean

  • 配置形式:基于 XML 文件的方式;基于注解的方式(我会在以后的文章中补充)
  • 在 xml 文件中通过 bean 节点来配置 bean
  • Bean 配置方式:通过全类名(反射)、通过工厂方法(静态工厂方法 & 实例工厂方法)、FactoryBean

Spirng 容器

  • 在 Spring IOC 容器读取 Bean 配置创建 Bean 实例之前, 必须对它进行实例化. 只有在容器实例化后, 才可以从 IOC
    容器里获取 Bean 实例并使用.

Spring 提供了两种类型的 IOC 容器实现.

  • BeanFactory: IOC 容器的基本实现.

  • ApplicationContext: 提供了更多的高级特性. 是 BeanFactory 的子接口.

  • BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身;ApplicationContext 面向使用
    Spring 框架的开发者,几乎所有的应用场合都直接使用 ApplicationContext 而非底层的 BeanFactory

  • 无论使用何种方式, 配置文件是相同的.

ApplicationContext
ApplicationContext 的主要实现类:

  • ClassPathXmlApplicationContext:从 类路径下加载配置文件

  • FileSystemXmlApplicationContext: 从文件系统中加载配置文件

在这里插入图片描述

  • ConfigurableApplicationContext 扩展于
    ApplicationContext,新增加两个主要方法:refresh() 和 close(), 让
    ApplicationContext 具有启动、刷新和关闭上下文的能力

  • ApplicationContext 在初始化上下文时就实例化所有单例的 Bean。

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

Spring 支持三种依赖注入的方式

  • 属性注入
  • 构造器注入
  • 工厂方法注入(很少使用)

1、属性注入

属性注入即通过 setter 方法注入 Bean 的属性值或依赖的对象。
属性注入通过 <property> 元素,使用 name 属性指定 Bean 的属性名称,value 属性或 <value>节点指定属性值。
		
		class:bean的全类名,通过反射的方式在 IOC容器中创建Bean,所以要求Bean中必须有无参数的构造器
		id:标识容器中的bean,id值一定是唯一的
	<bean id="helloWorld" class="com.qlgydx.spring.beans.HelloWorld">
		<property name="name" value="Spring"></property>
	</bean>

id:Bean 的名称。

  • 在 IOC 容器中必须是唯一的
  • 若 id 没有指定,Spring 自动将权限定性类名作为 Bean 的名字
  • id 可以指定多个名字,名字之间可用逗号、分号、或空格分隔

2、构造器注入

构造方法注入Bean 的属性值或依赖的对象,它保证了 Bean 实例在实例化后就可以使用。
构造器注入在  <constructor-arg> 元素里声明属性。
<constructor-arg> 中没有name属性
<bean id="car" class="com.qlgydx.spring.beans.Car">
		<constructor-arg value="Audi" index="0"></constructor-arg>
		<constructor-arg value="Shanghai" index="1"></constructor-arg>
		<constructor-arg value="300000" type="double"></constructor-arg>
	</bean>

注意:有两种形式入参,一种是按照索引匹配入参,另一种是按照类型匹配入参
<!-- 使用构造器注入属性值可以指定参数的位置和参数的类型! 以区分重载的构造器! -->
	<bean id="car2" class="com.qlgydx.spring.beans.Car">
		<constructor-arg value="Baoma" type="java.lang.String"></constructor-arg>
		<!-- 如果字面值包含特殊字符可以使用 <![CDATA[]]> 包裹起来 -->
		<!-- 属性值也可以使用value子节点进行配置 -->
		<constructor-arg type="java.lang.String">
			<value><![CDATA[<ShangHai^>]]></value>
		</constructor-arg>
		<constructor-arg type="int">
			<value>250</value>
		</constructor-arg>
	</bean>

注入属性的时候牵扯到一些注入方式的区别,稍微解释一下。

字面值:可用字符串表示的值,可以通过 < value> 元素标签或者value属性进行注入
基本数据类型及其封装类、String等类型都可以采取字面值注入的方式。
字面值中包含特殊字符,可以使用<![CDATA[]]>把字面值包裹起来。

Bean的引用

  • 组成应用程序的Bean经常需要相互协作以完成应用程序的功能。要使 Bean 能够相互访问,就必须在 Bean 配置文件中指定对 Bean 的引用。

  • 在 Bean 的配置文件中,可以通过< ref >元素或 ref 属性为 Bean 的属性或构造器参数指定对 Bean 的引用。

  • 也可以在属性或构造器里包含对 Bean 的声明,这样的 Bean 称为内部 Bean

当 Bean 实例仅仅给一个特定的属性使用时,可以将其声明为内部 Bean。内部 Bean 声明直接包含在 < property > 或 < constructor-arg >元素里,不需要设置任何 id 或 name 属性
注意:内部 Bean 不能使用在任何地方

<bean id="person" class="com.qlgydx.spring.beans.Person">
		<property name="name" value="Tom"></property>
		<property name="age" value="24"></property>
		
		<!-- 可以使用property 的 ref 属性建立bean之间的引用关系 -->
		<!-- 
			<property name="car" ref="car2"></property>
		 -->
		 
		<!-- 
			<property name="car">
				<ref bean="car2"/>
			</property>
		 -->
		<!-- 内部bean,不能被外部引用,只能在内部使用 -->
		<property name="car" >
			<bean class="com.qlgydx.spring.beans.Car">
				<constructor-arg value="Ford"></constructor-arg>
				<constructor-arg value="Changan"></constructor-arg>
				<constructor-arg value="2000000" type="double"></constructor-arg>
			</bean>
		</property>
	</bean>
	

注入参数详解:null值和级联属性

  • 可以使用专用的 < null/ >元素标签为 Bean 的字符串或其他对象类型的属性注入 null 值
	<bean id="person2" class="com.qlgydx.spring.beans.Person">
		<constructor-arg value="Jerry"></constructor-arg>		
		<constructor-arg value="25"></constructor-arg>		
		<constructor-arg><null/></constructor-arg>
	</bean>
  • 和 Structs、Hibernate 等框架一样,Spring 支持级联属性的配置
	<bean id="person2" class="com.qlgydx.spring.beans.Person">
		<constructor-arg value="Jerry"></constructor-arg>		
		<constructor-arg value="25"></constructor-arg>		 
		 <!-- 为级联属性赋值,注意: 属性需要先初始化后才可以为级联属性赋值,否则会有异常 ,和struts2不同 -->
		 <constructor-arg ref="car"></constructor-arg>
		<property name="car.maxSpeed" value="250"></property>
	</bean>

集合属性的注入

  • 在 Spring 中可以通过一组内置的 xml 标签(例如:< list >,< set > 或 < map >)来配置集合属性。
  • 配置 Java.util.List 类型的属性,需要指定< list >标签,在标签里包含一些元素。这些标签可以通过 < value >指定简单的常量值,通过 < ref >指定对其他 Bean 的引用。通过 < bean >指定内置 Bean 定义。通过 < null/ > 指定空元素。甚至可以内嵌其他集合。
	<bean id="person3" class="com.qlgydx.spring.beans.collection.Person">
		<property name="name" value="Mike"></property>
		<property name="age" value="27"></property>
		<property name="cars">
			<!--  使用 list  节点为 List 类型的属性赋值 -->
			<list>
				<ref bean="car"/>
				<ref bean="car2"/>
				<bean class="com.qlgydx.spring.beans.Car">
					<constructor-arg value="Ford"></constructor-arg>
					<constructor-arg value="Changan"></constructor-arg>
					<constructor-arg value="2000000" type="double"></constructor-arg>
				</bean>
			</list>
		</property>
	</bean>
	
  • 数组的定义和 List 一样,都使用 < list >
  • 配置 Java.util.Set 需要使用 < set >标签,定义元素的方法与 List 一样。
  • Java.util.Map 通过 < map > 标签定义, < map > 标签里可以使用多个 < entry > 作为子标签.
    每个条目包含一个键和一个值.
  • 必须在 < key > 标签里定义键
  • 因为键和值的类型没有限制, 所以可以自由地为它们指定 < value >, < ref >, < bean > 或 < null >元素.
  • 可以将 Map 的键和值作为 < entry > 的属性定义: 简单常量使用 key 和 value 来定义; Bean 引用通过 key-ref 和 value-ref 属性定义
	<!-- 配置Map属性值 -->
	<bean id="newPerson" class="com.qlgydx.spring.beans.collection.NewPerson">
		<property name="name" value="Rose"></property>
		<property name="age" value="28"></property>
		<property name="cars">
			<!-- 使用 map 节点及 map 的 entry 子节点配置Map类型的成员变量-->
			<map>
				<entry key="AA" value-ref="car"></entry>
				<entry key="BB" value-ref="car2"></entry>
			</map>
		</property>
	</bean>
  • 使用 < props > 定义 java.util.Properties, 该标签使用多个 < prop > 作为子标签. 每个 <
    prop > 标签必须定义 key 属性.
<!-- 配置 Propertis 属性值 -->
	<bean id="dataSourse" class="com.qlgydx.spring.beans.collection.DataSourse">
		<property name="properties">
			<!-- 通过 props 和 prop 子节点来为Properties 属性赋值 -->
			<props>
				<prop key="user">root</prop>
				<prop key="password">1234</prop>
				<prop key="jdbcUrl">jdbc:mysql///test</prop>
				<prop key="driverClass">com.mysql.jdbc.Driver</prop>
			</props>
		</property>
	</bean>

集合的注入

  • 使用基本的集合标签定义集合时, 不能将集合作为独立的 Bean 定义, 导致其他 Bean 无法引用该集合, 所以无法在不同 Bean 之间共享集合.
  • 可以使用 util schema 里的集合标签定义独立的集合 Bean. 需要注意的是, 必须在 根元素里添加 util schema 定义
<!-- 配置独立的集合 bean ,以供多个 bean 进行引用, 需要导入 util 命名空间-->
	<util:list id="cars" >
		<ref bean="car"/>
		<ref bean="car2"/>
	</util:list>

使用 p 命名空间

  • 为了简化 XML 文件的配置,越来越多的 XML 文件采用属性而非子元素配置信息。
  • Spring 从 2.5 版本开始引入了一个新的 p 命名空间,可以通过 元素属性的方式配置 Bean 的属性。
  • 使用 p 命名空间后,基于 XML 的配置方式将进一步简化
<!-- 通过 p 命名空间对 bean 的属性赋值,需要先导入 p 命名空间 ,相对于传统的方式更加简洁-->
	<bean id="person5" class="com.qlgydx.spring.beans.collection.Person" p:age="30" 
			p:name="Queen" p:cars-ref="cars"></bean>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值