Spring 的核心容器

来源:互联网 发布:网络基础哪本书好 编辑:程序博客网 时间:2024/05/21 06:35

spring的核心容器实现了IOC,其目的是提供一种无侵入的框架。

一,什么为spring的控制反转特性提供了基础?
spirng中有两个最基础,最重要的包(org.springframework.beans和org.springframework.context),在这两个包中,为了实现一种无侵入的框架,代码中大量引用了java的反射机制,通过动态调用的方式避免了硬编码,为spring的控制反转特性提供了基础。

这两个包中最重要的类是BeanFactory和ApplicationContext
1.BeanFactory提供了一种先进 的配置机制来管理任何种类的Bean
2.ApplicationContext是建立在BeanFactory之上,并增加了其他的功能,例如对于国际化的支持,获取资源,事件传递等。

二,Bean
在Spring的配置文档中,一个Bean只有一个id,这个id在管理Bean的BeanFactory或ApplicationContext中必须是唯一的标识。
因为在代码中通过BeanFactory或ApplicationContext来获取Bean的实例时,都要用它来作为唯一的索引。

指定Bean 的ID的两种方式:
1.是id
这里写图片描述
2.是name
这里写图片描述

id 和 name 的区别:
id属性允许指定一个Bean的id,并且它在XML DTD中作为一个真正的XML元素的ID属性被标记,所以XML解析器能够在其他元素指向他的时候做一些额外的校验。
但是XML规范严格限定了XML ID中合法的字符,如果在开发中有必要使用一些非法的字符,即不符合ID规定的字符,或者要给Bean增加其他的别名,则可以通过使用name属性指定一个或者多个id,当指定多个id时要用逗号(,),或者分号(;)分隔。
但是用id属性指定Bean的id是一种比较好的方式。

说明:一个Bean一般只有一个id,但是如果一个Bean有超过一个id,那么另外的id可以认为是这个Bean的别名。

三,Bean的类
Bean的id属性后面,还有Bean的另外一个属性class。
实例
这里写图片描述
class属性指名了Bean的来源,Bean的实际路径。
注意:class属性必须确保其完整性,要写class=”com.gc.action.HelloWorld”,而不能够写class=”HelloWorld”

四,Singleton(单一)的使用
Bean的两种部署模式:
1.singleton(单一)
如果一个Bean被定义为singleton模式,那么就只有一个共享的实例存在,所有对这个Bean的请求都会返回这个唯一的实例。
2.non-singleton(prototype)
如果一个Bean被定义为non-singleton(prototype)模式,那么对这个Bean的每次请求创建一个新的Bean实例,可以把它当成类似new的操作。
注释:Spring默认为singleton模式。

(1)配置文档id为HelloWorld的Bean被默认为singleton模式的代码如下:
这里写图片描述
(2)配置文档中id为HelloWorld的Bean被显示定义为singleton模式的代码如下:

这里写图片描述
上面的两段实例代码,客户端每次向BeanFactory请求时,只返回一个实例。如果要客户端每次向BeanFactory请求时都创建新的实例,则要把singleton=“true”改为singleton=“false”。
这里写图片描述

五,Bean的属性 使用依赖 depends-on
Bean的属性depends-on可以用来初始化使用这个Bean之前,强制执行一个或多个Bean的初始化。
将id为HelloWorld的Bean的depends-on属性设定为depends-on=“date”,则在初始化HelloWorld之前,会强制化date。
这里写图片描述
有时开发人员想在一个Bean初始化之前强制初始化另外一个或多个Bean,就可以使用依赖depends-on。

六,Bean的生命周期
1.Bean的定义
在Spring中通常是通过配置文档的方式来定义Bean的。
这里写图片描述
在一个配置文档中,可以定义多个Bean,定义多个Bean的config.xml
注意:在一个大的应用中,会有很多的Bean需要在配置文档中定义,这样配置文档就会很大,变得很不好维护,这时就可以把相关的Bean放在一个配置文档中,出现多个配置文档。

2.Bean的初始化
在spring中,Bean的初始化有两种方式:
1.在配置文档中通过指定init-method属性来完成
2.实现org.springframework.beans.factory.InitializingBean接口

第一种方式通过配置文档中指定init-method属性来完成
实现的思路:首先在HelloWorld.java中增加一个方法init(),用来完成初始化工作,然后修改配置文档config.xml,指定Bean中要初始化的方法,最后编写测试程序TestHelloWorld.java.

具体步骤如下:
(1)在HelloWorld.java中增加一个方法init(),用来完成初始化工作,并去掉构造函数HelloWorld()
/***********HelloWorld.java*************/
package com.gc.action
import java.util.Data;
public class HelloWorld{
//该变量用来存储字符串
private String msg = null;
//改变量用来存储日期
private Date date = null;

//初始化
public void init(){
this.msg = “HelloWorld”;
this.date = new Date();
}
//设定变量msg的set方法
public void setMsg(String msg){
this.msg = msg;
}
//获取变量msg的get方法
public String getMsg(){
return this.msg;
}
//设定变量date的set方法
public void setDate(Date date){
this.date = date;
}
//获取变量date的get方法
public Date getDate(){
return this.date;
}
}
(2)修改配置文档config.xml,指定Bean中要初始化的方法为init(),并且去掉通过setter注入值的方式。
这里写图片描述
这里写图片描述
(3)测试程序不变,运行TestHelloWorld.java

第二种方式实现org.springframework.beans.factory.InitializingBean接口。
实现思路:首先让HelloWorl实现InititlizingBean接口,增加一个方法afterPropertiesSet()用来完成初始化工作,然后修改配置文档config.xml,最后编写测试程序TestHelloWorld.java。

(1)让HelloWorld.java实现IntitializingBean接口,增加一个方法afterPropertiesSet(),用来完成初始化工作。
这里写图片描述
这里写图片描述
(2)修改配置文档config.xml
这里写图片描述
(3)测试程序不变,运行TestHelloWorld.java

3.Bean的使用
在spring中,Bean有三种使用方式。
1.使用BeanWrapper
HelloWorld helloWorld= new HelloWorld();
BeanWrapper bw = new BeanWrapperImpl(helloWorld);
bw.setPropertyValue(“msg”,”HelloWorld”);
System.out.println(bw.getPropertyValue(“msg”));
2.使用BeanFactory
InputStream is = new FileInputStream(“config.xml”);
XmlBeanFactory factory = new XmlBeanFactory(is);
HelloWorld helloWorld = (HelloWorld) factory.getBean(“HelloWorld”);
System.out.println(helloWorld.getMsg());
3.使用ApplicationContext
ApplicationContext actx = new FileSystemXmlApplicationContext(“config.xml”);
HelloWorld HelloWorld = (HelloWorld)actx.getBean(“HelloWorld”);
System.out.println(HelloWorld.getMsg());

4.Bean的销毁
Bean的销毁方式有两种: destroy 销毁 disposable 一次性
第一种,在配置文档中通过指定destroy-mehtod属性来完成
第二种,实现org.springframework.beans.factory.DisposableBean接口

第一种方式,通过配置文档指定的destroy-method属性来完成。
实现思路:首先在HelloWorld.java中增加一个方法cleanup(),用来完成销毁工作,并打印出销毁的内容,然后修改配置文档config.xml,指定Bean中要销毁的方法,最后编写测试程序TestHello.java

(1)在HelloWorld.java中增加一个方法cleanup(),用来完成销毁工作。
/*******************HelloWorld*********************/
package com;

import java.util.Date;

public class HelloWorld {
private String message = null;
private Date date = null;
//初始化
public void init(){
this.message = “李韬”;
this.date = new Date();
}
//销毁
public void cleanup(){
this.message = “”;
this.date = null;
System.out.println(“您销毁了 msg” + this.message +”和date” + this.date);
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}

}
(2)修改配置文档config.xml,指定Bean中的销毁方法为cleanup()
这里写图片描述

(3)测试程序

第二种方式,实现org.springframework.beans.factory.DisposableBean接口。
实现思路:首先让DestroyHelloWorld.java实现DisposableBean接口,增加一个方法destroy()用来完成销毁工作,然后修改配置文档config.xml,最后编写测试程序TestHelloWorld.java.

(1)让DestroyHelloWorld.java实现DisposableBean接口,增加一个方法destroy(),用来完成销毁工作。
/************DestroyHelloWorld.java**********/
package com;

import java.util.Date;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

public class DestroyHelloWorld implements InitializingBean,DisposableBean{
private String message = null;
private Date date = null;
@Override
public void destroy() throws Exception {
this.message = “”;
this.date = null;
System.out.println(“您销毁了message” + this.message + “和date” + this.date);

}@Overridepublic void afterPropertiesSet() throws Exception {    this.message = "李韬";    this.date = new Date();}public String getMessage() {    return message;}public void setMessage(String message) {    this.message = message;}public Date getDate() {    return date;}public void setDate(Date date) {    this.date = date;}

}

(2)修改配置文档config.xml
这里写图片描述
(3)测试文档

小结:以上两种方式实现的功能是一样的,同Bean的初始化工作一样,但是第一种方式却没有把代码耦合于spring,所以在这里推荐使用第一种方式。

5.ref的属性指定依赖的三种模式
ref的属性指定依赖的三种模式:local,Bean,parent

(1)用local属性指定
如果一个Bean与被参考引用的Bean在同一个XML文件中而且被参考引用的Bean是用id来命名的,那么就可以使用local属性。
注意:local属性的值必须与被参考引用的Bean的id属性一致,如果在同一个XML中没有匹配的元素,XML解析器将会产生一个错误。

XML来配置文档的缺点:
开发人员不能明显的发现XML中的错误。
解决方法:
为了能够尽可能的发现XML中的错误配置信息,如果一个Bean与被参考引用的Bean在同一个XML那么使用local形式将是最好的选择。
这里写图片描述

(2)用Bean属性指定
用ref元素的Bean属性指定被参考引用的Bean是Spring中最常见的形式,它允许指向的Bean可以同在一个XML中,也可以不在同一个XML中。Bean属性的值可以与被参考引用的Bean的id属性相同,也可以与被参考引用的Bean的name属性相同。
这里写图片描述

(3)用parent属性指定 parent 父辈
用parent属性指定被参考引用的Bean时,允许引用当前BeanFactory或ApplicationContext的父BeanFactory或ApplicationContext中的Bean。parent属性的值可以与被参考引用的Bean的id属性相同,也可以与被参考引用Bean的name属性相同。
这里写图片描述

local属性与Bean属性指定依赖的比较(三种模式只有local和Bean属性最常用):
相同之处:两种模式都可以用Bean的id来进行参考引用,都可以对同一XML中的Bean进行参考引用。
不同之处:用Bean属性依赖可以用Bean的name来进行参考引用,还可以对不同XML中的Bean进行参考引用。

6.Bean自动装配的5种模式
1.使用byName模式
2.使用byType模式
3.使用constructor模式
4.使用autodetect模式
5.使用no模式

什么是自动装配?
在spring中自动装配可以指定给每一个单独的Bean,因此可以给一些Bean使用自动装配而其他的Bean不使用自动装配。通过使用自动装配,开发人员可以减少指定属性的需要,从而节省一些属性设定的工作。
使用bean元素的autowire属性来指定Bean定义的自动装配。

(1)使用byName模式
byName模式指的就是通过Bean的属性名字进行自动装配。在Spring的配置文档XML中,查找一个与将要装配的属性同样名字的Bean。

在配置文档中,有一个id为HelloWorld的Bean被设置为通过byName自动装配,HelloWorld.java包含一个date变量,spring就会查找一个叫做date的Bean定义,然后用它来设置date属性。
/***********HelloWorld.java*******/
package com.gc.action
import java.util.Date
public class HelloWorld{
private String msg = null;
private Date date = null;

public void setMsg(String msg){
this.msg = msg;
}

public String getMsg(){
return this.msg;
}

public void setDate(Date date){
this.date = date;
}

public Date getDate(){
return this.date;
}
}

配置文档config.xml的实例代码
这里写图片描述

(2)使用byType模式
byType模式指的是如果XML中正好有一个与属性类型一样的Bean,就自动装配这个属性。如果多于一个这样的Bean,就抛出一个异常,指出可能不能对那个Bean使用byType的自动装配。

在配置文档中,有一个id为HelloWorld的Bean被设置为byType自动装配,HelloWorld.java包含一个date变量,spring就会查找一个类型为date的Bean定义,然后用它来设置date属性。
/*************HelloWorld.java**********/
package com.gc.action;
import java.util.Date;

public class HelloWorld{
private String message = null;
plrivate Date date = nulll;

public String setMessage(String message){
this.message = message;
}

pubic void getMessage(){
return this.message;
}

public Date setDate(Date date){
this.date = date;
}

public void getDate(){
return this.date;
}
}

配置文档config.xml的实例代码如下:
这里写图片描述
如果没有匹配的Bean,则什么都不会发生,属性不会被设置。如果这不是开发人员想要的情况,通过设置dependency-check=“objects”属性值来指定在这种情况下应该抛出错误。

(3)使用constructor模式
constructor模式指的就是根据构造函数的参数进行自动装配。在配置文档中,有一个id为HelloWorld的Bean被设置为通过constructor模式自动装配,HelloWorld包含一个构造函数方法,Spring就会根据构造函数的参数查找合适类型的Bean定义,然后用它来设置构造函数的参数的值。
/*****************HelloWorld.java******/
package com.gc.action;
import java.util.Date;
public class HelloWorld{
private String msg = null;
private Date date = null;

public HelloWorld(Date date){
this.date = date;
}
public void setMsg(String msg){
this.message = msg;
}
public String getMsg(){
return this.msg;
}

public void setDate(Date date){
this.date = date;
}

public Date getDate(){
return this.date;
}
}

配置文档config.xml的示例代码如下:

这里写图片描述

(4)使用autodetect 模式 detect 检测
autodetect模式指的就是通过对Bean检查类的内部来选择constructor或byType。如果先找到constructor就用constructor就用constructor;如果没有constructor,而找到byTe,就用byType。
/***************HelloWorld.java**********************/
package com.gc.action;
import java.util.Date;
public class HelloWordl{
private String msg = null;
private Date date = null;

public HelloWorld(Date date){
this.date = date;
}
public void setMsg(String msg){
this.msg = msg;
}
public String getMsg(){
return this.msg;
}
public void setDate(Date date){
this.date = date;
}
public Date getDate(){
return this.date;
}
}

配置文档config.xml的示例代码如下:这里写图片描述
在上面这个示例中,Bean的属性设定为autowire=”autodetect”。在HelloWorld.java找到了构造函数,则spring会使用constructor模式;如果没有构造函数,则使用byType模式。
注意:autodetect在spring 4.3上面测试不通过,可能是废弃了。

(5)使用no模式
no模式指的就是不使用自动装配。

Bean的引用通过什么元素定义的?
ref定义的,有三种方式:local,Bean,parent

no模式是默认的配置,很多的企业级应用环境中不鼓励使用自动装配模式,因为它对于Bean之间的参考依赖关系不清晰。使用no模式的实例代码如下:
这里写图片描述

对5种模式进行总结:
显示的指定依赖,例如property和constructor元素,总会覆盖自动装配。正如前面提到的,对于大型的应用,不鼓励使用自动装配,因为它去除了参考依赖的透明性,和清晰性。虽然自动装配可以减少开发人员的输入工作,但是却使开发人员很难看出Bean的每个属性是否都设定完成。

7.Bean依赖检查的4种模式
什么是Bean依赖检查?
就像自动装配一样,依赖检查能够分别对每一个Bean应用或取消应用。默认的是不检查依赖关系。使用dependency-check属性来指定Bean定义的依赖检查共有四种模式:simple,object,all,none。

为什么要使用依赖检查?
在自动装配中,因为是隐式的,不像通过ref的属性指定依赖那么直接,所以开发人员很难看出Bean的每个属性是否都设定完成,这时就要借助于依赖检查来实现查看Bean的每个属性是否都设定完成的功能。

(1)使用simple模式 simple 简单
simple模式指的是对基本类型,字符串和集合进行依赖检查。
这里写图片描述
上述代码中由于设定为depend-check=“simple”,则只会对字符串msg进行依赖检查。

0 0
原创粉丝点击