前言
在applicationContext.xml中配置完bean之后,Bean的声明周期状态有哪些。生命周期的各个阶段可以做什么。在applicationContext.xml配置bean的作用域有哪些。其中各个作用域代表的是什么。适用于什么情况。这篇文章做一个记录。
生命周期
初始化
可以直接查看图片,图片来自Spring Bean Life Cycle
从上图看出,Bean初始化完成包括9个步骤。其中一些步骤包括接口的实现,其中包括BeanNameAware接口,BeanFactoryAware接口。ApplicationContextAware接口。BeanPostProcessor接口,InitializingBean接口。那么这些接口在整个生命周期阶段都起到什么作用?后面我们一一介绍。
实例化前
当Bean全部属性设置完毕后,往往需要执行一些特定的行为,Spring提供了两种方式来实现此功能:
- 使用init-mothod方法
- 实现initializingBean接口
指定初始化方法
如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
package com.model;
public class InitBean {
public static final String NAME = "mark" ;
public static final int AGE = 20 ;
public InitBean() {
// TODO Auto-generated constructor stub
System.out.println( "执行构造方法" );
}
public String name;
public int age ;
public String getName() {
return name;
}
public void setName(String name) {
this .name = name;
}
public int getAge() {
return age;
}
public void setAge( int age) {
this .age = age;
}
public void init(){
System.out.println( "调用init方法进行成员变量的初始化" );
this .name = NAME;
this .age = AGE;
System.out.println( "初始化完成" );
}
}
|
编写加载器
1
2
3
4
5
6
7
8
9
10
|
package com.model;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.service.UserServiceImpl;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext( "initbean.xml" );
InitBean bean = (InitBean) context.getBean( "init" );
}
}
|
配置Bean
注意init-method参数
1
2
3
4
5
6
7
8
|
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="init" class="com.model.InitBean" init-method="init"/>
</beans>
|
执行结果
实现InitializingBean接口
实现InitializingBean接口会实现afterPropertiesSet方法,这个方法会自动调用。但是这个方式是侵入性的。一般情况下,不建议使用。
实现afterPropertiesSet方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
package com.model;
import org.springframework.beans.factory.InitializingBean;
public class InitBean implements InitializingBean {
public static final String NAME = "mark" ;
public static final int AGE = 20 ;
public InitBean() {
// TODO Auto-generated constructor stub
System.out.println( "执行构造方法" );
}
public String name;
public int age ;
public String getName() {
return name;
}
public void setName(String name) {
this .name = name;
}
public int getAge() {
return age;
}
public void setAge( int age) {
this .age = age;
}
public void init(){
System.out.println( "调用init方法进行成员变量的初始化" );
this .name = NAME;
this .age = AGE;
System.out.println( "初始化完成" );
}
@Override
public void afterPropertiesSet() throws Exception {
// TODO Auto-generated method stub
System.out.println( "调用init方法进行成员变量的初始化" );
this .name = NAME;
this .age = AGE;
System.out.println( "初始化完成" );
}
}
|
配置xml
1
2
3
4
5
6
7
8
9
|
<? xml version = "1.0" encoding = "UTF-8" ?>
< beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xmlns:p = "http://www.springframework.org/schema/p"
xmlns:aop = "http://www.springframework.org/schema/aop"
xsi:schemaLocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" >
<!-- <bean id="init" class="com.model.InitBean" init-method="init"/> -->
< bean id = "init" class = "com.model.InitBean" init-method = "init" />
</ beans >
|
结果:
销毁
同样,上图中表示来Bean销毁时候的过程。包括DisposableBean接口。
使用destroy-method方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
package com.model;
import org.springframework.beans.factory.InitializingBean;
public class InitBean implements InitializingBean {
public static final String NAME = "mark" ;
public static final int AGE = 20 ;
public InitBean() {
// TODO Auto-generated constructor stub
System.out.println( "执行构造方法" );
}
public String name;
public int age ;
public String getName() {
return name;
}
public void setName(String name) {
this .name = name;
}
public int getAge() {
return age;
}
public void setAge( int age) {
this .age = age;
}
public void init(){
System.out.println( "调用init方法进行成员变量的初始化" );
this .name = NAME;
this .age = AGE;
System.out.println( "初始化完成" );
}
@Override
public void afterPropertiesSet() throws Exception {
// TODO Auto-generated method stub
System.out.println( "调用init方法进行成员变量的初始化" );
this .name = NAME;
this .age = AGE;
System.out.println( "初始化完成" );
}
public void close(){
System.out.println( "bean被销毁" );
}
}
|
配置Bean
1
2
3
4
5
6
7
8
9
|
<?xml version= "1.0" encoding= "UTF-8" ?>
<beans xmlns= "http://www.springframework.org/schema/beans"
xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
xmlns:p= "http://www.springframework.org/schema/p"
xmlns:aop= "http://www.springframework.org/schema/aop"
xsi:schemaLocation= "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" >
<!-- <bean id= "init" class = "com.model.InitBean" init-method= "init" /> -->
<bean id= "init" class = "com.model.InitBean" destroy-method= "close" />
</beans>
|
配置加载器
1
2
3
4
5
6
7
8
9
10
11
12
|
package com.model;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.service.UserServiceImpl;
public class Main {
public static void main(String[] args) {
AbstractApplicationContext context = new ClassPathXmlApplicationContext( "initbean.xml" );
context.registerShutdownHook();
InitBean bean = (InitBean) context.getBean( "init" );
}
}
|
结果:
实现DisposableBean接口
实现DisposableBean接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
package com.model;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
public class InitBean implements InitializingBean,DisposableBean {
public static final String NAME = "mark" ;
public static final int AGE = 20 ;
public InitBean() {
// TODO Auto-generated constructor stub
System.out.println( "执行构造方法" );
}
public String name;
public int age ;
public String getName() {
return name;
}
public void setName(String name) {
this .name = name;
}
public int getAge() {
return age;
}
public void setAge( int age) {
this .age = age;
}
public void init(){
System.out.println( "调用init方法进行成员变量的初始化" );
this .name = NAME;
this .age = AGE;
System.out.println( "初始化完成" );
}
@Override
public void afterPropertiesSet() throws Exception {
// TODO Auto-generated method stub
System.out.println( "调用init方法进行成员变量的初始化" );
this .name = NAME;
this .age = AGE;
System.out.println( "初始化完成" );
}
public void close(){
System.out.println( "bean被销毁" );
}
@Override
public void destroy() throws Exception {
// TODO Auto-generated method stub
System.out.println( "bean被销毁完成" );
}
}
|
配置文件
1
2
3
4
5
6
7
8
9
10
|
<? xml version = "1.0" encoding = "UTF-8" ?>
< beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xmlns:p = "http://www.springframework.org/schema/p"
xmlns:aop = "http://www.springframework.org/schema/aop"
xsi:schemaLocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" >
<!-- <bean id="init" class="com.model.InitBean" init-method="init"/> -->
<!-- <bean id="init" class="com.model.InitBean" destroy-method="close"/> -->
< bean id = "init" class = "com.model.InitBean" />
</ beans >
|
Spring Bean的作用域
作用域 | 描述 |
singleton | 该作用域将 bean 的定义的限制在每一个 Spring IoC 容器中的一个单一实例(默认)。 |
prototype | 该作用域将单一 bean 的定义限制在任意数量的对象实例。 |
request | 该作用域将 bean 的定义限制为 HTTP 请求。只在 web-aware Spring ApplicationContext 的上下文中有效。 |
session | 该作用域将 bean 的定义限制为 HTTP 会话。 只在web-aware Spring ApplicationContext的上下文中有效。 |
global-session | 该作用域将 bean 的定义限制为全局 HTTP 会话。只在 web-aware Spring ApplicationContext 的上下文中有效。 |
配置示例
1
2
|
<bean id= "..." class = "..." scope= "singleton" >
</bean>
|
使用方法注入协调作用域不同的Bean
正常情况下,如果singleton作用域依赖singleton作用域。即每次获取到的都是一样的对象。同理,prototype作用域依赖prototype作用域,每次获取到的都是新的对象。但是,如果singleton依赖prototype作用域,那么每次获取到的singleton中的prototype都是第一次创建的prototype。如何协调这种关系。保证每次获取到的都是正确的呢。
对于这种情况,Spring提供了lookup方法用来解决这种问题。
首先我们定义一个原型:
1
2
3
4
5
6
|
package com.model;
public class MyHelper {
public void doSomethingHelpful() {
}
}
|
然后通过接口注入:
1
2
3
4
5
|
package com.model;
public interface DemoBean {
MyHelper getHelper();
void somePeration();
}
|
配置一个单例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package com.model;
/**
* 测试类
* @author kevin
*
*/
public abstract class AbstractLookupDemo implements DemoBean {
public abstract MyHelper getMyHelper();
@Override
public MyHelper getHelper() {
// TODO Auto-generated method stub
return getMyHelper();
}
@Override
public void somePeration() {
// TODO Auto-generated method stub
}
}
|
配置文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<? xml version = "1.0" encoding = "UTF-8" ?>
< beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xmlns:p = "http://www.springframework.org/schema/p"
xmlns:aop = "http://www.springframework.org/schema/aop"
xsi:schemaLocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" >
< bean id = "helper" class = "com.model.MyHelper" scope = "prototype" />
< bean id = "standardLookupBean" class = "com.model.StandardLookupDemo" >
< property name = "myHelper" ref = "helper" ></ property >
</ bean >
< bean id = "abstractLookupBean" class = "com.model.AbstractLookupDemo" >
< lookup-method name = "getMyHelper" bean = "helper" ></ lookup-method >
</ bean >
</ beans >
|
加载配置文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
package com.model;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.util.StopWatch;
public class Main {
public static void main(String[] args) {
AbstractApplicationContext context = new ClassPathXmlApplicationContext( "lookBean.xml" );
context.registerShutdownHook();
System.out.println( "传递standardLookupBean" );
test(context, "standardLookupBean" );
System.out.println( "传递AbstractLookupDemo" );
test(context, "abstractLookupBean" );
}
public static void test(AbstractApplicationContext context,String beanName) {
DemoBean bean = (DemoBean) context.getBean(beanName);
MyHelper helper1 = bean.getHelper();
MyHelper helper2 = bean.getHelper();
System.out.println( "测试" +beanName);
System.out.println( "两个helper是否相同?" +(helper1==helper2));
StopWatch stopWatch = new StopWatch();
stopWatch.start( "lookupDemo" );
for ( int i = 0 ; i < 10000 ; i++) {
MyHelper helper = bean.getHelper();
helper.doSomethingHelpful();
}
stopWatch.stop();
System.out.println( "获取10000次花费了" +stopWatch.getTotalTimeMillis()+ "毫秒" );
}
}
|
结果:
从上面的结果图看出,以前的方式生成的对象每次都是相同的。通过lookup方式注入每次是不同的。可以解决这种问题。但是有没有更简单的方式,感觉这种方式优点麻烦。
让Bean感知Spring容器
实现BeanNameAware,自定设置id值。
实现BeanFactoryAware,ApplicationContextAware 感知Spring容器。获取Spring容器。
Spring国际化支持
配置配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<? xml version = "1.0" encoding = "UTF-8" ?>
< beans xmlns = "http://www.springframework.org/schema/beans"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xmlns:p = "http://www.springframework.org/schema/p"
xmlns:aop = "http://www.springframework.org/schema/aop"
xsi:schemaLocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" >
< bean id = "messageSource" class = "org.springframework.context.support.ResourceBundleMessageSource" >
< property name = "basenames" >
< list >
< value >message</ value >
</ list >
</ property >
</ bean >
</ beans >
|
新建中文配置文件
message_zh_CN.properties:
1
2
|
hello=welcome,{0}
now=now is : {0}
|
新建英文配置文件
message_en_US.properties:
1
2
|
hello=\u4F60\u597D,{0}
now=\u73B0\u5728\u7684\u65F6\u95F4\u662F : {0}
|
加载配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package com.model;
import java.util.Date;
import java.util.Locale;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.util.StopWatch;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext( "globalization.xml" );
String[] a = { "读者" };
String hello = context.getMessage( "hello" ,a, Locale.CHINA);
Object[] b = { new Date()};
String now = context.getMessage( "now" ,b, Locale.CHINA);
System.out.println(hello);
System.out.println(now);
hello = context.getMessage( "hello" ,a, Locale.US);
now = context.getMessage( "now" ,b, Locale.US);
System.out.println(hello);
System.out.println(now);
}
}
|
结果
总结
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对服务器之家的支持。