JAVA CDI 学习(2) - Scope 生命周期

上一节中,我们已经知道了如何用@Inject实现基本注入,这一节研究Bean实例注入后的“生命周期”,web application中有几种基本的生命周期(不管哪种编程语言都类似)

1、Application 生命周期

即:web application启动后,处于该生命周期级别的对象/变量,将一直存在,可以被所有web应用的用户共同访问,通常用来做网站计数器,实现流量访问之类。直到web 应用停止或重新启动,该对象才被销毁。简单来说:只要web application处于激活状态,不论你换什么浏览器,不论你是否关闭页面,这个对象都会一直存在。

2、Session 生命周期

每次我们在某种类型的浏览器(比如:IE或Firefox)里,请求web application的某个页面时,就会生成Session,只要浏览器不关闭,Session就能持续有效(哪怕你把当前Tab标签页面给关掉,或者在当前url地址栏,输入一个其它不相关的网址,跳到其它网站,然后再回过来访问web app,只要Session不超时,Session仍有效)。说得更白一点:按F5刷新,该对象/变量不会被自动销毁,除非Session过期。

注:Session是跟浏览器有关的,如果在FireFox里打开web Application的某个url,再到IE里打开同样的url,这二个浏览器里的Session是不同的。

3、Request 生命周期

即只有本次http请求才有效,通俗点讲,如果你定义一个变量的生命周期是Request级别,刷新一次页面后,该变量就被初始化(重新投胎)了。

为了演示上面的几种情况,我们创建一个新的Dynamic Website,仍然用Maven来管理,项目结构如下:

JAVA CDI 学习(2) - Scope 生命周期

model包下,创建了几个类,先来看基类BaseItem

JAVA CDI 学习(2) - Scope 生命周期
 1 package model;
 2 
 3 import java.io.Serializable;
 4 
 5 public class BaseItem implements Serializable {
 6 
 7     private static final long serialVersionUID = -8431052435964580554L;
 8 
 9     private long counter;
10 
11     public void addCounter() {
12         counter++;
13 
14     }
15 
16     public long getCounter() {
17         return counter;
18     }
19 
20     public long getHashCode() {
21         return hashCode();
22     }
23 
24 }
BaseItem

注:SessionScoped使用时,要求Bean实现序列化接口,否则运行会报错,建议要注入的Bean,全都实现Serializable接口。

其它几个类都继承自这个类,只是在类上应用了不同的注解

ApplicationBean

JAVA CDI 学习(2) - Scope 生命周期
 1 package model;
 2 
 3 import javax.enterprise.context.*;
 4 
 5 @ApplicationScoped
 6 public class ApplicationBean extends BaseItem {
 7 
 8     /**
 9      * 
10      */
11     private static final long serialVersionUID = -2434044044797389734L;
12 
13 
14 
15 }
ApplicationScoped

SessionBean

JAVA CDI 学习(2) - Scope 生命周期
 1 package model;
 2 
 3 import javax.enterprise.context.*;
 4 
 5 @SessionScoped
 6 public class SessionBean extends BaseItem {
 7 
 8     /**
 9      * 
10      */
11     private static final long serialVersionUID = -4285276657265507539L;
12 
13 
14 
15 }
SessionBean

RequestBean

JAVA CDI 学习(2) - Scope 生命周期
 1 package model;
 2 
 3 import javax.enterprise.context.*;
 4 
 5 @RequestScoped
 6 public class RequestBean extends BaseItem {
 7 
 8     /**
 9      * 
10      */
11     private static final long serialVersionUID = -2625124180601128375L;
12 
13 
14 
15 }
RequestBean

 SingletonBean

JAVA CDI 学习(2) - Scope 生命周期
 1 package model;
 2 
 3 import javax.inject.Singleton;
 4 
 5 @Singleton
 6 public class SingletonBean extends BaseItem {
 7 
 8     /**
 9      * 
10      */
11     private static final long serialVersionUID = 283705326745708570L;
12 
13 
14 
15 }
SingletonBean

注:@Singleton算是一个“伪”Scope,顾名思义,它将以单例模式注入一个唯一的对象实例。从使用效果上看,这跟@ApplicationScoped类似.

同样,为了跟前端JSF交互,我们再来一个“Controller”

JAVA CDI 学习(2) - Scope 生命周期
 1 package controller;
 2 
 3 import javax.inject.*;
 4 import model.*;
 5 
 6 @Named("Index")
 7 public class IndexController {
 8 
 9     @Inject
10     private ApplicationBean applicationBean;
11 
12     @Inject
13     private SessionBean sessionBean;
14 
15     @Inject
16     private RequestBean requestBean;
17 
18     @Inject
19     private SingletonBean singletonBean;
20 
21     public ApplicationBean getApplicationBean() {
22         applicationBean.addCounter();
23         return applicationBean;
24     }
25     
26 //    public long getApplicationBeanCount(){
27 //        applicationBean.addCounter();
28 //        return applicationBean.getCounter();        
29 //    }
30 
31     public SessionBean getSessionBean() {
32         sessionBean.addCounter();
33         return sessionBean;
34     }
35 
36     public RequestBean getRequestBean() {
37         requestBean.addCounter();
38         return requestBean;
39     }
40 
41     public SingletonBean getSingletonBean() {
42         singletonBean.addCounter();
43         return singletonBean;
44     }
45 
46 }
IndexController

我们注入了上述四种生命周期的Bean,并提供了getter方法,最后准备一个简单的xhtml页面,作为UI展现

JAVA CDI 学习(2) - Scope 生命周期
 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 2 <html xmlns="http://www.w3.org/1999/xhtml"
 3     xmlns:h="http://java.sun.com/jsf/html"
 4     xmlns:f="http://java.sun.com/jsf/core"
 5     xmlns:ui="http://java.sun.com/jsf/facelets">
 6 
 7 <h:head>
 8     <title>cdi scope sample</title>
 9 </h:head>
10 <body>
11     Application Bean:#{Index.applicationBean.counter} ,
12     hashCode:#{Index.applicationBean.hashCode}
13     <br /> Session Bean:#{Index.sessionBean.counter} ,
14     hashCode:#{Index.sessionBean.hashCode}
15     <br /> Request Bean:#{Index.requestBean.counter} ,
16     hashCode:#{Index.requestBean.hashCode}
17     <br /> Singleton Bean:#{Index.singletonBean.counter} ,
18     hashCode:#{Index.singletonBean.hashCode}
19     <br />
20 </body>
21 </html>
index.xhtml

在Jboss里部署后,可以用http://localhost:8080/cdi-scope-sample/index.jsf 访问,下面是运行截图:

JAVA CDI 学习(2) - Scope 生命周期

大家可以F5刷新下看看变化,然后多开几个Tab页,访问同样的网址,F5刷新,然后把浏览器关掉,再重新打开浏览器,访问同样的网址再比较一下

附:示例源码下载 cdi-scope-sample.zip

JAVA CDI 学习(2) - Scope 生命周期

上一篇:C# this关键字


下一篇:《自己动手写操作系统》pmtest2笔记