生命周期层在OSGi框架中属于模块层上面的一层,它的运作是建立在模块层的功能之上的。生命周期层一个主要的功能就是让你能够从外部管理应用或者建立能够自我管理的应用(或者两者的结合),并且给了应用本身很大的动态性。
一般来说,程序(或者程序的一部分)都一定服从某种生命周期。软件的生命周期有4个典型的阶段,如下图:
如果你正在创建一个应用,首先你得安装(install)它;然后当这个应用的所有依赖都满足了,我们就可以执行(execute)这个应用;如果这个应用不需要了,我们可以停止(stop)它;过了一段时间,我们可能需要更新(update)这个应用的版本;最后,我们可能会移除(remove)这个应用,因为再也用不着了。
我们通过在外部或者内部对应用进行这些操作,完成对应用的“生命周期管理”过程。对于非模块化应用,这些操作就是以整个应用为对象的;如果是对于模块化应用,那么我们就可以有更细粒度(针对应用中的某个模块)的生命周期管理了。
无论是标准的Java还是servlet,JavaEE,他们都有不同的生命周期管理机制,那么为什么我们都需要生命周期管理应用呢?
2 为什么要管理应用的生命周期上一章我们讲解了如何通过加入metadata来完成应用的模块化定义,但是这些元数据中只有对bunlde静态属性的介绍,而并没有提到一个应用的动态特征,比如某个特定的类或者对象在什么时候被需要和使用。
一般情况下,要想管理应用的生命周期,就得通过框架提供的API来完成。一套清晰明确的生命周期API使得你的应用可以对一段代码进行配置、初始化和维护。而OSGi标准就定义了这样的一套API,使得你能在bundle生命周期的各种阶段对其进行多种外部或内部操作,从而达到对bundle进行功能控制的目的。
由于你构建的应用被模块化为若干个部分,并且有了这些API之后你能对其中任意一个部分的去留和动作进行精确和即时的控制,那么你所构建的这个应用的灵活性就大大的提升了。如果没有生命周期管理,别人给你什么样的应用,你就只能使用什么样的应用,可控制性很低;而一旦有了生命周期管理,无论别人给你什么样的应用,你也能通过生命周期管理对这个已经模块化应用的行为(无论是启动、更新还是停止等等)进行精确控制。把应用每个部分都控制在自己的手中,是不是感觉非常棒?
3 OSGi bundle的生命周期模块层的介绍中我们已经知道如何定义一个bundle,但是要想使用bundle,就得使用生命周期层的API,和OSGi框架的生命周期层进行交互。逐条详细介绍API会显得过于冗长(去看看OSGi标准吧),所以接下来会通过一个例子来大致讲解一下API提供给使用者的一些功能。
需要注意的是,OSGi框架的核心并没有强制使用任何特定的API交互机制(比如命令行,GUI,或者XML配置文件等),只是单纯的Java API而已,所以开发者可以任意创造出自己想要的交互模式,保证了框架的灵活性。
在标准的Java编程中,你会通过将jar包放到classpath中来使用它,而bundle则不是这样。Bundle只有在被安装(install)到一个OSGi框架的运行实例中才能用起来。并且OSGi框架支持对这些bundle完整的生命周期管理,并且支持这些管理操作在应用执行完成,其动态性可见一斑。
3.1 Bundle生命周期的状态转移图
这个图清晰的展现了bundle在生命周期中的各个状态和状态间的转移条件。
我们可以通过Bundle的getState方法来获得bundle的当前状态。
在这里需要说明的是Starting和Stopping状态,这两个状态是暂态,也就是说这两个状态在持续一会以后就会自动转移到下一个状态,不需要转移条件。
生命周期层的API主要是由以下三个核心接口来组成的:BundleActivator,BundleContext和Bundle。
• BundleActivator:让你能够捕捉bundle的start和stop事件,并对这两个事件作出自定义的反应。
• BundleContext
第一种方法:
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head> <title>定时器</title> <script language="javascript" src=/blog_article/"jquery-1.4.2.js"></script>/index.html <script language="javascript"> //使用setInterval间歇调用 (不建议使用该方法) $(function(){ setInterval(function(){ $("#currentTime").text(new Date().toLocaleString()); },1000); }); </script> </head> <body> <div id="currentTime"></div> </body> </html>
第二种方法:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <head> <title>定时器</title> <script language="javascript" src=/blog_article/"jquery-1.4.2.js"></script>/index.html <script language="javascript"> //使用setTimeout超时调用 function startTime(){ $("#currentTime").text(new Date().toLocaleString()); setTimeout('startTime()',1000); } </script> </head> <body onload="startTime()"> <div id="currentTime"></div> </body> </html>
第三种方法:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <head> <title>定时器</title> <script type="text/javascript"> var c=0; var t; function timedCount(){ document.getElementById('txt').value=c; c=c+1; t=setTimeout("timedCount()",1000); } function stopCount(){ clearTimeout(t); } </script> </head> <body> <form> <input type="button" value="开始计时!" onclick="timedCount()"/> <input type="text" id="txt"/> <input type="button" value="停止计时!" onclick="stopCount()"/> </form> </body> </html>
/**
* 发送GET请求
*
* @param url url地址
* @return JSONObject
*/
public static String getAjaxDataFromURLForSMS(String url) {
long begin = System.currentTimeMillis();
LOG.info("request:" + url);
String result = null;
BufferedReader rd = null;
try {
URL u = new URL(/blog_article/url/index.html);
InputStream is = u.openStream();
rd = new BufferedReader(new InputStreamReader(is, "utf-8"));
StringBuffer sb = new StringBuffer();
String line;
while ((line = rd.readLine()) != null) {
sb.append(line);
}
long end = System.currentTimeMillis();
LOG.info("response[" + (end - begin) + "]:" + sb.toString());
result = sb.toString();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (rd != null) {
try {
rd.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
/**
*/
public static Document getXMLDataFromURL(/blog_article/String url/index.html) {
long begin = System.currentTimeMillis();
LOG.info("request:" + url);
SAXBuilder saxBuilder = new SAXBuilder();
Document doc = null;
try {
URL u = new URL(/blog_article/url/index.html);
InputStream in = u.openStream();
doc = saxBuilder.build(in);
} catch (Exception e) {
e.printStackTrace();
}
if (LOG.isInfoEnabled()) {
long end = System.currentTimeMillis();
XMLOutputter outp = new XMLOutputter();
LOG.info("response[" + (end - begin) + "]:" + outp.outputString(doc));
}
return doc;
}
/**
* 发送GET请求*
* @param url
* url地址
* @return JSONObject
*/
public static JSONObject getJSONDataFromURL(/blog_article/String url/index.html) {
long begin = System.currentTimeMillis();
LOG.info("request:" + url);
JSONObject jsonObj = null;
BufferedReader rd = null;
try {
URL u = new URL(/blog_article/url/index.html);
InputStream is = u.openStream();
rd = new BufferedReader(new InputStreamReader(is, "utf-8"));
StringBuffer sb = new StringBuffer();
String line;
while ((line = rd.readLine()) != null) {
sb.append(line);
}
long end = System.currentTimeMillis();
LOG.info("response[" + (end - begin) + "]:" + sb.toString());
jsonObj = new JSONObject(sb.toString());
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally {
if (rd != null) {
try {
rd.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return jsonObj;
}
/**
* 发送POST请求
*
* @param url
* url地址 params 参数
* @return JSONObject
*/
public static JSONObject getJSONDataFromURL(/blog_article/String url, String params/index.html) {
long begin = System.currentTimeMillis();
LOG.info("request:" + url);
JSONObject jsonObj = null;
HttpURLConnection huc = null;
BufferedReader in = null;
InputStreamReader isr = null;
InputStream is = null;
StringBuffer sb = new StringBuffer(333);
try {
URL u = new URL(/blog_article/url/index.html);
huc = (HttpURLConnection) u.openConnection();
huc.setRequestMethod("POST");
huc.setDoOutput(true);
huc.getOutputStream().write(params.getBytes("utf-8"));
huc.getOutputStream().flush();
huc.getOutputStream().close();
is = huc.getInputStream();
isr = new InputStreamReader(is, "utf-8");
in = new BufferedReader(isr);
String line = null;
while ((line = i