Spring框架 之 Spring容器初始化

Spring容器(Core Container)支持三种配置方式

一、基于XML配置文件:在XML文件中使用Spring命名空间所支持的标签与属性来配置Spring容器。

在XML配置文件中,我们使用<bean>标签来制定创建对象的类,并根据XML配置文件完成Springr的初始化。例如:    

<pre class="html" style="box-sizing: border-box; margin: 0px 0px 24px; padding: 0px 16px; overflow-x: auto; background-color: rgb(240, 240, 240); font-family: Consolas, Inconsolata, Courier, monospace; font-size: 12px; line-height: 20px; color: rgb(0, 0, 0); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.3.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.3.xsd
http://www.springframework.org/schema/data/jpa
http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd">

<!-- 使用bean标签创建实例  
    1.id:该实例在容器中的名称,容器中唯一  
    2.class:实例的类路径  
    3.scope:作用域  
    4.init-method:初始化方法的名称,在创建该实例后,会Spring容器会调用该方法  
    5.destroy-method:在Spring容器释放资源时,销毁该实例前会调用此方法  
    6.lazy-init:是否开启懒加载,bean标签中的懒加载优先级高于beans标签中的default-lazy-init属性  
 -->  
<bean   
id="test"   

<span style="white-space:pre;"> </span>class="beans.Test"
<span style="white-space:pre;"> </span>scope="singleton"
<span style="white-space:pre;"> </span>init-method="doInit"
<span style="white-space:pre;"> </span>destroy-method="doDestroy"
<span style="white-space:pre;"> </span>lazy-init="false"/>

</beans> </pre>

获取对象的方式:

<pre class="java" style="box-sizing: border-box; margin: 0px 0px 24px; padding: 0px 16px; overflow-x: auto; background-color: rgb(240, 240, 240); font-family: Consolas, Inconsolata, Courier, monospace; font-size: 12px; line-height: 20px; color: rgb(0, 0, 0); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">package beans;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
public static void main(String[] args) {
//通过XML配置文件初始化Spring容器,“test.xml”为配置文件的文件名与路径
ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("test.xml");
//通过上下文对象获取类的实例,“test”为bean对象的id
Test test=ctx.getBean("test", Test.class);
//使用实例
test.testMethod();
//释放资源
ctx.close();
}
}</pre>

//构造方法

public Test() {super();System.out.println("Test.Test()");}

//初始化方法

public void doInit() {System.out.println("Test.doInit()");}

//释放资源的方法

public void doDestroy() {System.out.println("Test.doDestroy()");}

//业务方法

public void testMethod() {System.out.println("Test.testMethod()");}}

输出结果:

image

二、基于注解:使用Spring提供的注解修饰特定的类,初始化Spring容器时基于注解创建对象完成初始化。

在Spring中,可以使用@Service(业务层对象)、@Controller(控制层对象)、@Repository(持久层对象)、@Component(其他一般类)注解来修饰要创建对象的类,并使用<centext:component-scan>标签或者@ComponentScan注解来指明要创建实例的包的路径(base-package或basePackages)。例如:

<pre class="java" style="box-sizing: border-box; margin: 0px 0px 24px; padding: 0px 16px; overflow-x: auto; background-color: rgb(240, 240, 240); font-family: Consolas, Inconsolata, Courier, monospace; font-size: 12px; line-height: 20px; color: rgb(0, 0, 0); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">@Service//表示这是一个业务层对象
public class Test {
...
} </pre>

获取对象的方式:

可使用纯注解的方式

<pre class="java" style="box-sizing: border-box; margin: 0px 0px 24px; padding: 0px 16px; overflow-x: auto; background-color: rgb(240, 240, 240); font-family: Consolas, Inconsolata, Courier, monospace; font-size: 12px; line-height: 20px; color: rgb(0, 0, 0); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">package beans;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Service;

//开启扫描包创建实例
@ComponentScan("beans")
//表示该类是一个业务层类
@Service(value="test")
public class Test {

public static void main(String[] args) {  
    //通过全注解的形式创建对象,需将被@ComponentScan注解修饰的类的Class对象作为参数传递给Spring容器上下文对象  
    AnnotationConfigApplicationContext ctx=new AnnotationConfigApplicationContext(Test.class);  
    //通过上下文对象获取类的实例,“test”为bean对象的id  
    Test test=ctx.getBean("test", Test.class);  
    //使用实例  
    test.testMethod();  
    //释放资源  
    ctx.close();  
}  

public Test() {  
    super();  
    System.out.println("Test.Test()");  
}  
//定义初始化方法  
@PostConstruct  
public void doInit() {  
    System.out.println("Test.doInit()");  
}  
//定义销毁方法  
@PreDestroy  
public void doDestroy() {  
    System.out.println("Test.doDestroy()");  
}  
//业务方法  
public void testMethod() {  
    System.out.println("Test.testMethod()");  
}  

} </pre>

输出结果与基于XML配置文件的方式相同。

也可以省去@ComponentScan注解,在XML文件中添加<context:component-scan>标签开启包扫描并指定包路径,使用上文提到的@Service、@Component等注解修饰要交由Spring容器创建实例的类,使用ClassPathXmlApplicationContext类加载XML配置文件并获取实例。

基于XML文件和基于注解是最常用的两种配置方式,并且可以混合使用。不过需要注意的是,如果XML文件中的bean对象与通过注解创建的对象的id或name相同的话,将只会创建一个对象。

test.xml文件内容:

<pre class="java" style="box-sizing: border-box; margin: 0px 0px 24px; padding: 0px 16px; overflow-x: auto; background-color: rgb(240, 240, 240); font-family: Consolas, Inconsolata, Courier, monospace; font-size: 12px; line-height: 20px; color: rgb(0, 0, 0); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">...

<context:component-scan base-package="beans"/>

<bean   
id="test"   
class="beans.Test"   
scope="singleton"   
init-method="doInit"   
destroy-method="doDestroy"   
lazy-init="false"/>  

... </pre>

Test类内容:

<pre class="java" style="box-sizing: border-box; margin: 0px 0px 24px; padding: 0px 16px; overflow-x: auto; background-color: rgb(240, 240, 240); font-family: Consolas, Inconsolata, Courier, monospace; font-size: 12px; line-height: 20px; color: rgb(0, 0, 0); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">package beans;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Service;

@Service(value="test")
public class Test {
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("test.xml");
Test test=ctx.getBean("test", Test.class);
test.testMethod();
ctx.close();
}
public Test() {
super();
System.out.println("Test.Test()");
}
@PostConstruct
public void doInit() {
System.out.println("Test.doInit()");
}
@PreDestroy
public void doDestroy() {
System.out.println("Test.doDestroy()");
}
public void testMethod() {
System.out.println("Test.testMethod()");
}
} </pre>

输出结果:
image
结果显示Test类构造器只执行了一次,证明虽然在两处都配置了创建实例的语句,但是只创建了一个实例。

三、基于JAVA配置:使用 @Configuration 和 @Bean 注解配合完成Spring容器的配置。

我们也可以使用@Configuration注解修饰一个类,并且在该类中使用@Bean注解修饰该类的方法,被修饰的方法执行后会返回一个对象,该对象在Spring容器中的id为方法名。例如:

<pre class="java" style="box-sizing: border-box; margin: 0px 0px 24px; padding: 0px 16px; overflow-x: auto; background-color: rgb(240, 240, 240); font-family: Consolas, Inconsolata, Courier, monospace; font-size: 12px; line-height: 20px; color: rgb(0, 0, 0); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">@Configuration
public class TestConfig {
@Bean
public MyService myService() {
return new MyServiceImpl();
}
} </pre>

基于JAVA的配置方式与前两种方式类似,相当于把XML文件写在@Configuration修饰的配置类中,在配置类中使用@Bean注解代替XML文件中的<bean>标签。@Bean注解中有各种属性,类似于<bean>标签中的属性,不过作用域与延迟加载要使用单独的注解@Scope或@Lazy来声明。

<pre class="java" style="box-sizing: border-box; margin: 0px 0px 24px; padding: 0px 16px; overflow-x: auto; background-color: rgb(240, 240, 240); font-family: Consolas, Inconsolata, Courier, monospace; font-size: 12px; line-height: 20px; color: rgb(0, 0, 0); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;">package beans;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;

//开启扫描包创建实例
@ComponentScan("beans")
//基于JAVA配置创建对象
@Configuration
public class Test {

public static void main(String[] args) {  
    //通过全注解的形式创建对象,需将被@ComponentScan注解修饰的类的Class对象作为参数传递给Spring容器上下文对象  
    AnnotationConfigApplicationContext ctx=new AnnotationConfigApplicationContext(Test.class);  
    //通过上下文对象获取类的实例,“test”为bean对象的id  
    Test test=ctx.getBean("test00", Test.class);  
    test=ctx.getBean("test01", Test.class);  
    //使用实例  
    test.testMethod();  
    //释放资源  
    ctx.close();  
}  

@Bean(value={"test00","test01"},initMethod="doInit",destroyMethod="doDestroy")  
@Lazy(false)  
@Scope(value="singleton")  
public Test test() {  
    return new Test();  
}  

public Test() {  
    super();  
    System.out.println("Test.Test()");  
}  
//定义初始化方法  
public void doInit() {  
    System.out.println("Test.doInit()");  
}  
//定义销毁方法  
public void doDestroy() {  
    System.out.println("Test.doDestroy()");  
}  
//业务方法  
public void testMethod() {  
    System.out.println("Test.testMethod()");  
}  

} </pre>

输出结果与前两种一致,不过需要注意的是,在根据@Bean修饰的方法创建对象之前,会先为@Configuration修饰的类创建实例,在本例控制台输出中,会有两个“Test.Test()”。

基于JAVA的配置方式可以通过前两种的任意一种方式初始化Spring并且获取对象。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,830评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,992评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,875评论 0 331
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,837评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,734评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,091评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,550评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,217评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,368评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,298评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,350评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,027评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,623评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,706评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,940评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,349评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,936评论 2 341

推荐阅读更多精彩内容