Spring bean
的封装机制
Spring
从核心而言,是一个
DI
容器,其设计哲学是提供一种无侵入式的高扩展性框架。即无需代码中涉及
Spring
专有类,即可将其纳入
Spring
容器进行管理。
作为对比,
EJB
则是一种高度侵入性的框架规范,它制定了众多的接口和编码规范,要求实现者必须遵从。侵入性的后果就是,一旦系统基于侵入性框架设计开发,那么之后任何脱离这个框架的企图都将付出极大的代价。
为了避免这种情况,实现无侵入性的目标。
Spring
大量引入了
Java
的
Reflection
机制,通过动态调用的方式避免硬编码方式的约束,并在此基础上建立了其核心组件
BeanFactory
,以此作为其依赖注入机制的实现基础。
org.springframework.beans
包中包括了这些核心组件的实现类,核心中的核心为
BeanWrapper
和
BeanFactory
类。这两个类从技术角度而言并不复杂,但对于
Spring
框架而言,却是关键所在,如果有时间,建议对其源码进行研读,必有所获。
(1)BeanWrapper
Spring
中的核心接口:通过配置文件中的设定,
java Bean
就可以在运行期动态创建对象并设定其属性
(
依赖关系
)
。
(2)BeanFactory
Bean Factory
,顾名思义,负责创建并维护
Bean
实例
Bean Factory
负责根据配置文件创建
Bean
实例,可以配置的项目有:
<1>
.
Bean
属性值及依赖关系(对其他
Bean
的引用)
<2>
.
Bean
创建模式(是否
Singleton
模式,即是否只针对指定类维持全局唯一的实例)
<3>
.
Bean
初始化和销毁方法
<4>
.
Bean
的依赖关系
联合上面关于
BeanWrapper
的内容,我们可以看到,
BeanWrapper
实现了针对单个
Bean
的属性设定操作。而
BeanFactory
则是针对多个
Bean
的管理容器,根据给定的配置文件,
BeanFactory
从中读取类名、属性名
/
值,然后通过
Reflection
机制进行
Bean
加载和属性设定。
在
Spring
中,
BeanFactory
是
IOC
容器的核心接口。它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。
(3)ApplicationContext
BeanFactory
提供了针对
Java Bean
的管理功能,而
ApplicationContext
提供了一个更为框架化的实现(从上面的示例中可以看出,
BeanFactory
的使用方式更加类似一个
API
,而非
Framework style
)。
ApplicationContext
覆盖了
BeanFactory
的所有功能,并提供了更多的特性。此外,
ApplicationContext
为与现有应用框架相整合,提供了更为开放式的实现(如对于
Web
应用,我们可以在
web.xml
中对
ApplicationContext
进行配置)。相对
BeanFactory
而言,
ApplicationContext
提供了以下扩展功能:
<1>
.
国际化支持
我们可以在
Beans.xml
文件中,对程序中的语言信息(如提示信息)进行定义,将程序
中的提示信息抽取到配置文件中加以定义,为我们进行应用的各语言版本转换提供了极
大的灵活性。
<2>
.
资源访问
支持对文件和
URL
的访问。
<3>
.
事件传播
事件传播特性为系统中状态改变时的检测提供了良好支持。
<4>
.
多实例加载
可以在同一个应用中加载多个
Context
实例。
(4)Web Context
对于
Web
应用,
Spring
提供了可配置的
Application
Context
加载机制。
加载器目前有两种选择:
ContextLoaderListener
和
ContextLoaderServlet
。这两者在功能上完全等同,只是一个是基于
Servlet2.3
版本中新引入的
Listener
接口实现,而另一个基于
Servlet
接口实现。
开发中可根据目标
Web
容器的实际情况进行选择。
配置非常简单,在
web.xml
中增加:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
或:
<servlet>
<servlet-name>context</servlet-name>
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
|
通过以上配置,
Web
容器会自动加载
/WEB-INF/applicationContext.xml
初始化
Application Context
实例,如果需要指定配置文件位置,可通过
context-param
加以指定:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/myApplicationContext.xml</param-value>
</context-param>
|
配置完成之后,即可通过
WebApplicationContextUtils.getWebApplicationContext
方法在
Web
应用中获取
ApplicationContext
引用。
注入参数
(Injection
Parameters)
(1)
简单的值注入
将简单的值注入到
beans
里面是很简单的。如果需要,只需要简单地在配置标记中指定值,将其封装在一个
<value>
标记中,默认情况,
<value>
标记不仅能读取
String
值,而且也可以将这些值转换到任何原生数据类型或者原生封装类。
示例:
Bean
:
public class InjectSimple{
private
String name;
private int
age;
private float
height;
private boolean
isProgrammer;
private Long
ageInSeconds;
//property
set method……
}
配置
Bean
:
<bean id=”injectSimple” class=”com.bean.InjectSimple”>
<property
name=”name”>
<value>John Smith</value>
</property>
<property
name=”age”>
<value>35</value>
</property>
<property
name=”height”>
<value>1.78</value>
</property>
<property
name=” isProgrammer”>
<value>true</value>
</property>
<property
name=” ageInSeconds”>
<value>1103760000</value>
</property>
</bean>
|
(2)
在同一个工厂注入
Beans
Spring
允许使用
<ref>
标记将一个
bean
注入到另一个
bean
中。
示例
Bean
:
public class InjectRef{
private
Oracle oracle;
public void
setOracle(Oracle oracle){
this. oracle = oracle;
}
}
配置
Bean
:
<bean id=”injectRef” class=”com.bean.InjectRef”>
<property
name=”oracle”>
<ref local=”oracle”/>
</property>
</bean>
<bean id=”oracle” class=”com.bean.Oracle”/>
|
注:
<ref>
标记使用
local
属性,那么意味着
<ref>
标记仅仅通过
bean
的
id
属性查找,而不通过任何别名查找。通过别名查找可以使用
bean
属性。如:
<bean id=”injectRef” class=”com.bean.InjectRef”>
<property
name=”oracle”>
<ref bean=” wiseworm”/>
</property>
</bean>
<bean id=”oracle” name=”wiseworm”
class=”com.bean.Oracle”/>
|
(3)
使用集合进行注入
很多时候,你的
Bean
需要访问对象的集合,而不是访问一个单一的
bean
或者值。因此,理所当然的,
Spring
允许你在你的一个
bean
中注入一个对象的集合。使用集合很简单:你可以选择
<list><map><set>
或者
<props>
来描述
List
、
Map
、
Set
或者
Properties
的实例,然后你就像在其他注入中所用到的方式一样传递这些对象。这个
<props>
标记只允许传递
String
值,因为
Properties
类只允许
String
作为属性的值。当使用
<list>
、
<map>
或者
<set>
时,你可以使用注入到属性时的任何可用标记,甚至可以是其他的集合标记。这样,允许你传递存储
Map
的
List
,存储
Set
的
Map
,甚至是像
List
存储
Map
、
Map
存储
Set
、
Set
中存储
List
这样的嵌套!
示例代码:
public class CollectionDI{
private Map
map;
private Set
set;
private List
list;
private
Properties props;
//setter
method……
}
配置文件:
<bean
id=”collectionDI” class=”com.spring.CollectionDI”>
<property
name=”map”>
<map>
<entry key=”key1”>
<value>Lily</value>
//<ref bean=”user”/>
</entry>
</map>
</property>
<property
name=”set”>
<set>
<value>Jack</value>
//<ref bean=”user”/>
</set>
</property>
<property
name=”list”>
<list>
<value>Tom</value>
//<ref bean=”user”/>
</list>
</property>
<property
name=”props”>
<props>
<prop key=”username”>
Jack
//
只能给
properties
实例的每个属性指定一个
String
的值
</prop>
</props>
</property>
</bean>
|
自动装配你的
Bean
如果你不喜欢自己将你的程序装配起来,你可以尝试让
Spring
自动装配。默认情况,自动装配是被关闭的。开启它,需要指定你想要使用哪种自动装配方法,给你想要自动装配的
bean
配置指定
autowire
属性。
Spring
支持四种自动装配模式:通过命名、通过类型、构造器或自动检测。
通过命名自动装配:
Spring
尝试将每个属性连接到一个同名的
bean
上。因此,如果目标
bean
拥有一个叫做
foo
的属性而
Bean
工厂中定义了一个命名为
foo
的
Bean
,那么
foo
这个
Bean
会被分配给目标的
foo
属性。
部分配置代码:
<bean
id=”foo”
class=”com.autowire.Foo”
autowire=”byName”/>
|
通过类型自动装配:
Spring
试图将目标
bean
的每个属性与
Bean
工厂中对应的同类型的
bean
连接起来。如果在目标
bean
中有一个
String
类型的属性,而在
Bean
工厂中有
String
类型的
bean
,那么
Spring
会将
String
的
bean
和目标类型的
String
属性连接起来。如果你在同一个
Bean
工厂中有多个相同的类型的
bean
,比如
String
,那么
Spring
不能确定使用哪个进行自动装配,而后会抛出异常。
部分配置代码:
<bean
id=”foo”
class=”com.autowire.Foo”
autowire=”byType”/>
|
构造器自动装配:
与通过类型的自动装配类似,只是它通过构造器代替
setter
进行注入。
Spring
试图最大数量地匹配构造器中包含的参数。比如,如果你的
bean
拥有两个构造器,一个接受一个
String
,另一个接受一个
String
和一个整数,而你的的
Bean
工厂中同时有
String
和整数
bean
,
Spring
会使用那个接受两个参数的构器。
部分配置代码:
<bean
id=”foo”
class=”com.autowire.Foo”
autowire=”constructor”/>
|
自动检测自动装配:
通知
Spring
在构造器自动装配和通过类型的自动装配间进行选择。
部分配置代码:
<bean
id=”foo”
class=”com.autowire.Foo”
autowire=”autodetect”/>
|
注意:什么时候使用自动装配?
在大部分情况下,关于是否应该使用自动装配这个问题的答案当然是“不!”,虽然自动装配可以在小规模的程序中节省你的时间,但是它会让你养成坏习惯,在大规模的程序中弹性也不够。实际上对
bean
进行精确的定义并不会消耗你太多的工作,那样你通够从精确的语义,完全自由的属性命名还有规定要管理同一个类型的多少个实例这些地方受益。除了非常小的应用程序,无论如何也要绕开使用自动装配。
Bean
继承
某些情况下,你也许需要定义多个实现了共用接口的相同类型的
bean
。这时,如果你希望这些
bean
共享一些配置但又有一些不同的设置,这会是个问题。保持共享配置同步的过程经常出错,在大项目中这样做还非常耗时。为了解决这个问题,
Spring
允许你定义一个
<bean>
从
Bean
工厂的其他
bean
处继承属性设置。如果需要,你可以重写需要的子
bean
中的任何一个属性的值,这使你可以进行完全的控制,父
bean
可以给你的每个
bean
提供一个基础配置。
配置代码示例:
<bean
id=”parentUserBean” class=”com.spring.UserBean”>
<property
name=”name”>
<value>Rob</value>
</property>
<property
name=”age”>
<value>23</value>
</property>
</bean>
<bean
id=”childUserBean” class=”com.spring.UserBean” parent=”parentUserBean”
>
<property
name=”age”>
<value>21</value>
</property>
</bean>
|
程序中指定了
parent=”parentUserBean”
,表明
spring
将
parentUserBean
视为
childUserBean
的父
bean
,在
childUserBean
中,设置了
age
属性,没有
name
属性的值,
Spring
会把来自
parentUserBean
的值传递给
childUserBean
。
分享到:
相关推荐
**二、Spring Ioc容器** Spring Ioc容器是整个Spring框架的基石,它负责创建、配置和管理对象。容器通过读取XML、Java注解或Java配置类等方式,获取对象的定义信息,然后根据这些信息实例化对象并进行依赖注入。 *...
SpringIOC是Spring Framework中的核心组件之一,负责管理应用程序中的对象、依赖关系和生命周期。 在 Spring IOC 中,对象的创建和管理是通过 BeanFactory 或 ApplicationContext 实现的。BeanFactory 是 Spring ...
springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC手写框架分析springIOC...
spring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demospring ioc模块手写demo...
Spring 框架是Java开发中的核心框架,它主要由两个关键部分组成:IOC(Inversion of Control,控制反转)和AOP(Aspect Oriented Programming,面向切面编程)。这两个概念是Spring框架的核心特性,极大地简化了企业...
Spring IoC 加载流程讲解 在本节中,我们将对 Spring IoC 加载流程进行详细的讲解,并探讨 IoC 思想和依赖倒置原则的应用。 IoC 控制反转 IoC(Inversion of Control)是指在软件设计中,将对象实例的控制权从...
spring Ioc容器配置 IOC容器数据源配置 <!-- 配置数据源 --> destroy-method="close"> <value>org.gjt.mm.mysql.Driver <value>jdbc:mysql://localhost:3306/demo <value>root ...
Spring IOC,全称Inversion of Control,即“控制反转”,是Spring框架的核心特性之一。在传统的Java应用程序中,对象的创建和管理通常由开发者自己控制。而在Spring IOC中,这种控制权被反转,对象的创建、初始化、...
Spring 中 IoC 优点与缺点解析 IoC(Inversion of Control)是 Spring 框架中的一种设计模式,它的主要思想是将对象的创建和管理交给容器,从而解耦合对象之间的依赖关系。今天,我们将详细解析 IoC 的优点和缺点。 ...
Spring IOC(Inversion of Control,控制反转)是Spring框架的核心特性之一,它允许开发者将对象的创建和管理交给Spring容器来处理,从而使代码更加松耦合,更易于测试和维护。下面将详细介绍Spring IOC的基本概念、...
标题 "Spring IOC" 描述了我们讨论的核心主题——Spring 框架中的依赖注入(Inversion of Control,简称 IOC)机制。Spring 是一个广泛应用的 Java 应用开发框架,其核心特性之一就是IOC,它极大地简化了软件组件...
Spring IOC(Inversion of Control,控制反转)是Spring框架的核心特性,它极大地简化了Java应用的开发,通过将对象的创建和管理交由Spring容器来处理,开发者可以更专注于业务逻辑。下面,我们将深入探讨Spring IOC...
Spring IOC(Inversion of Control,控制反转)是Spring框架的核心特性,它将对象的创建和管理权交由Spring容器来负责,从而实现了依赖倒置,增强了代码的可测试性和可维护性。DI(Dependency Injection,依赖注入)...
Spring IoC,全称为Inversion of Control,即控制反转,是Spring框架的核心特性之一。它是一种设计模式,改变了传统程序中的对象创建和管理的方式,将对象的生命周期管理交由Spring容器来负责,使得代码更加解耦,...
Spring框架是Java开发中不可或缺的一部分,它通过提供两种核心特性——控制反转(IoC)和面向切面编程(AOP)来简化应用的构建。理解并掌握这两种技术对于任何Java开发者来说都至关重要。 **控制反转(IoC)**,也...
Spring IOC,即Spring控制反转,是Spring框架的核心特性之一。控制反转(Inversion of Control,简称IoC)是一种设计原则,用于减少代码间的耦合,提高系统模块化和代码的重用性。在Spring框架中,IOC具体体现在对...
标题《Spring IoC源码深度剖析开源架构源码2021.pdf》和描述《Spring IoC源码深度剖析开源架构源码2021.pdf》表明该文档主要面向于分析Spring框架中控制反转(IoC)容器的核心源码,解析和理解其内部的工作机制及...
Java反射和Spring IOC是Java开发中的两个重要概念,它们在构建灵活、可扩展的应用程序时起着关键作用。本文将深入探讨这两个主题,并提供相关的学习资源。 首先,让我们了解一下Java反射。Java反射机制是Java语言的...
**Spring 的 IoC 容器** IoC(Inversion of Control)即控制反转,是 Spring 的核心特性之一。在传统的编程模式中,对象之间存在依赖关系,程序员需要手动创建和管理这些对象。而在 Spring 中,IoC 容器负责管理和...
#### 二、IoC容器概述 在传统的Java应用程序中,对象的创建和管理通常由程序员来完成。这种方式会导致代码之间存在高度耦合,难以维护。而Spring通过其IoC容器实现了对对象的创建、配置和管理过程的解耦,使得开发...