Broadcom Wireless LAN Driver: ftp://ftp.hp.com/pub/softpaq/sp36501-37000/sp36684.exe
HP Wireless Assistant: ftp://ftp.hp.com/pub/softpaq/sp35501-36000/sp35903.exe
HP Update and HP Software Update – Critical Security Update: ftp://ftp.hp.com/pub/softpaq/sp38001-38500/sp38202.exe
HP Quick Launch Buttons Critical Security Update: ftp://ftp.hp.com/pub/softpaq/sp38001-38500/sp38166.exe
HP Software Update: ftp://ftp.hp.com/pub/softpaq/sp36001-36500/sp36292.exe
LightScribe Host Software: ftp://ftp.hp.com/pub/softpaq/sp38001-38500/sp38081.exe
LightScribe Host Software(1): ftp://ftp.hp.com/pub/softpaq/sp36001-36500/sp36168.exe
audio uaa
点此下载
audio
点此下载
modem
点此下载
qlb
点此下载
card reader
点此下载
wifi assistant
点此下载
quickplay
点此下载
bluetooth
点此下载
wifi
点此下载
cpu
点此下载
点此下载
点此下载
chipset
点此下载
graphics
点此下载
hp DV2000 XP的指纹识别驱动.
索引有哪些优点?
索引有哪些优点?
1、 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。
2、 可以大大加快数据的检索速度,这也是创建索引的最主要原因。
3、 可以加速表和表之间的连接,这在实现数据的参考完整性方面特别有意义。
4、 在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。
索引有哪些缺点?
1、 创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。
2、 除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,需要的空间就会更大。
3、 当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。
索引有哪些类型?
1、 普通索引
这是最基本的索引类型,而且它没有唯一性之类的限制。
2、 唯一性索引
这种索引和前面的“普通索引”基本相同,但有一个区别:索引列的所有值都只能出现一次,即必须唯一。
3、主键
它是一种特殊的唯一索引,不允许有空值。
4、全文索引
MySQL从3.23.23版开始支持全文索引和全文检索。
单列索引和组合索引:
单列索引就是把索引单独建立在一个字段上。
组合索引复合索引就是一个索引创建在两个列或者多个列上。在搜索时,当两个或者多个列作为一个关键值时,最好在这些列上创建复合索引。
建立和使用索引有哪些注意事项:
1、 索引要建立在经常进行select操作的字段上。这是因为,如果这些列很少用到,那么有无索引并不能明显改变查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。
2、 索引要建立在值比较唯一的字段上。这样做才是发挥索引的最大效果。,比如主键的id字段,唯一的名字name字段等等。如果索引建立在唯一值比较少的字段,比如性别gender字段,寥寥无几的类别字段等,刚索引几乎没有任何意义。
3、 对于那些定义为text、 image和bit数据类型的列不应该增加索引。因为这些列的数据量要么相当大,要么取值很少。
4、 当修改性能远远大于检索性能时,不应该创建索引。修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。
5、 在WHERE和JOIN中出现的列需要建立索引。
6、 在以通配符 % 和 _ 开头作查询时,MySQL索引是无效的。但是这样索引是有效的:select * from tbl1 where name like ‘xxx%’,所以谨慎的写你的SQL是很重要的。
shell 比较两个字符串
resin-pro-3.1.5 full cracked.
虽然resin-pro-3.1.5早在2月26号就发布了,但一直标记为dev,今天发现已经不是dev了,赶紧下载回来破解。
此次破解的跟上次的3.1.3一样,功能上完全没有任何限制了,可以使用session持久化、cache等,只需要做好相关的配置即可。
3.1.5的Change Log请看官方文档:Resin Change Log,同时可以看到3.1.6 snapshot了。 我会及时破解Resin的最新版本!
文章来源:http://www.dingl.com/blog/archives/28
mysql ip address convert (ip2bigint,bigint2ip)
Convert IP address to bigint
CREATE FUNCTION `F_Ip2Int`(ip varchar(15)) RETURNS bigint(20) BEGIN declare tmp bigint default 0; while instr(ip,’.’)>0 do set tmp = tmp*256+ left(ip,instr(ip,’.’)-1); set ip = right(ip,length(ip)-instr(ip,’.’)); end while; set tmp = tmp*256+ip; return tmp; END |
Convert bigint to IP Address
CREATE FUNCTION `F_Int2Ip`(iip bigint) RETURNS varchar(15) BEGIN return concat((iip & 0xFF000000)>>24, ‘.’, (iip & 0x00FF0000)>>16, ‘.’, (iip & 0x0000FF00)>>8, ‘.’, iip & 0x000000FF); END |
proxool.FatalSqlExceptionHelper.testException()
我终于找到了出问题的线程了。
通过thread dump 我发现如下线程一直在运行:
“resin-tcp-connection-*:80-6075” daemon prio=1 tid=0x0857aac8 nid=0x7fb0 runnable [0x82dfe000..0x82dff19c]
at org.logicalcobwebs.proxool.FatalSqlExceptionHelper.testException(FatalSqlExceptionHelper.java:116)
at org.logicalcobwebs.proxool.FatalSqlExceptionHelper.testException(FatalSqlExceptionHelper.java:103)
at org.logicalcobwebs.proxool.AbstractProxyStatement.testException(AbstractProxyStatement.java:65)
at org.logicalcobwebs.proxool.ProxyStatement.invoke(ProxyStatement.java:146)
at org.logicalcobwebs.proxool.ProxyStatement.intercept(ProxyStatement.java:57)
at $java.sql.Statement$$EnhancerByCGLIB$$1a91e2dc.close()
at com.tag.db.doEndTag(valuetag.java:438)
at _jsp._rst._eng_0aa__jsp._jspService(_products_0viewinfo__jsp.java:75)
at com.caucho.jsp.JavaPage.service(JavaPage.java:60)
at com.caucho.jsp.Page.pageservice(Page.java:570)
at com.caucho.server.dispatch.PageFilterChain.doFilter(PageFilterChain.java:159)
at com.kenfor.exutil.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:152)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)
at com.kenfor.exutil.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:152)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)
at com.caucho.server.webapp.WebAppFilterChain.doFilter(WebAppFilterChain.java:178)
at com.caucho.server.dispatch.ServletInvocation.service(ServletInvocation.java:229)
at com.caucho.server.http.HttpRequest.handleRequest(HttpRequest.java:267)
at com.caucho.server.port.TcpConnection.run(TcpConnection.java:388)
– locked <0x5c472008> (a java.lang.Object)
at com.caucho.util.ThreadPool.runTasks(ThreadPool.java:490)
at com.caucho.util.ThreadPool.run(ThreadPool.java:423)
at java.lang.Thread.run(Thread.java:595)
然后我又查看了顶级的代码调用
at org.logicalcobwebs.proxool.FatalSqlExceptionHelper.testException(FatalSqlExceptionHelper.java:116)
也就是testException这个方法一直在执行,我不清楚为什么为会出现如此死循环。
我想问问大家,什么样的代码会导致proxool的testException一直运行着。
——————————————————————————–
不知道是分数不够,还是人才稀少,怎么就没人回答呢。郁闷
——————————————————————————–
为什么会重复出现:
at com.kenfor.exutil.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:152)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)
at com.kenfor.exutil.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:152)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:70)
谁能告诉我啊。
——————————————————————————–
本来proxool是很有口碑的连接池 ,怎么会导致
at org.logicalcobwebs.proxool.FatalSqlExceptionHelper.testException(FatalSqlExceptionHelper.java:116)中testException运行没完没了呢。
——————————————————————————–
努力接分升级中…帮你up!
——————————————————————————–
filter 死循环调用?
——————————————————————————–
回复:iihero(阿黑哥)
应该不是filter的引起的,如果是filter的话,那所有的页面都会很容易进入死循环。
——————————————————————————–
下面就是这个永远不结束的方法,我看了一下源代码,虽然有循环部分,但也不导致死循环,
大伙帮我分析一下,具体是什么原因会导致下面的代码一直执行?
/**
* Test to see if an exception is a fatal one
* @param cpd the definition so we can find out what a fatal exception looks like
* @param t the exception to test
* @param level the recursion level (max 20)
* @return true if it is fatal
*/
protected static boolean testException(ConnectionPoolDefinitionIF cpd, Throwable t, int level) {
boolean fatalSqlExceptionDetected = false;
Iterator i = cpd.getFatalSqlExceptions().iterator();
while (i.hasNext()) {
if (t.getMessage() != null && t.getMessage().indexOf((String) i.next()) > -1) {
// This SQL exception indicates a fatal problem with this connection.
fatalSqlExceptionDetected = true;
}
}
// If it isn’t fatal, then try testing the contained exception
if (!fatalSqlExceptionDetected && level < 20) {
Throwable cause = getCause(t);
if (cause != null) {
fatalSqlExceptionDetected = testException(cpd, cause, level + 1);
}
}
return fatalSqlExceptionDetected;
}
——————————————————————————–
while (i.hasNext()) {
if (t.getMessage() != null && t.getMessage().indexOf((String) i.next()) > -1) {
// This SQL exception indicates a fatal problem with this connection.
fatalSqlExceptionDetected = true;
}
}
t.getMessage() != null这句话不成立的话,就没机会调用i.next()
就死循环了。
——————————————————————————–
在网上大家都对proxool赞赏有加,但是我们的项目出现如此严重的错误,实属不应该,
请兄弟们帮我查明此原因,不让我再去怀疑proxool的过错了,把清白留proxool。
——————————————————————————–
回复:zhmt(不爽你就用分砸我!!!)
t.getMessage() != null不成立,也应该会再次调用i.hasNext()吧
——————————————————————————–
请大伙帮我把铁顶起来,都快两天了,还是没找到答案。
——————————————————————————–
你说的错了,&& 运算是从左到右,左边的不成立,直接就返回false了,不再计算右边的。所以不调用i.next()。
楼主要加强基础。
——————————————————————————–
你可以写个小例子测试一下。
——————————————————————————–
当 t.getMessage() != null不成立时,是“t.getMessage().indexOf((String) i.next()) > -1”没机会执行。不是i.hasNext
——————————————————————————–
回复: zhmt(不爽你就用分砸我!!!)
我还是不明白,t.getMessage() != null这句话不成立的话,就会导致死循环。
——————————————————————————–
就算“t.getMessage().indexOf((String) i.next()) > -1不知道,也不会导致死循环啊。
——————————————————————————–
我上面的那段代码是从proxool中取出来的,如果这么容易就死循环了,那我就要怀疑这个东西的安全性啦。
——————————————————————————–
你的问题的背景是什么啊?
不能光看这一点。
——————————————————————————–
resin-tcp-connection-*:80-6075″ daemon prio=1 tid=0x0857aac8 nid=0x7fb0 runnable
这是个守护线程,(daemon),一直运行的话,是很正常的。可能问题不在这里,你的是什么性能问题啊?
——————————————————————————–
好,那我就说说背景 :
我维护的是个网站项目,网站经常服务器cpu 99%,并且上去了就不下来了,开始我就确定是
死循环的问题,但是找不到根据,前两天我用kill -3 pid,每隔5分钟Thread Dump一下,发现
上面的线程一直在虚拟机(JVM)里面运行者。那只有死循环才不会退出的。
我不知道我讲清楚没?
——————————————————————————–
daemon是守护进程,但是不应该不结束。
——————————————————————————–
你确信是这个线程启动后cpu才到100%的吗?
——————————————————————————–
是的。在平时,我找不到这样的线程。
——————————————————————————–
我查了一下它的源码,这个类是用来检查一个异常是否是严重异常,它能一直运行说明你的应用导致了很多sql异常。如果这个pool是经过大家的检验的话,可能你的应用中,哪一部分的sql调用很有问题。
——————————————————————————–
是的,但是很多异常也会有个数量限制啊,可能处理校验的速度慢啊,而不会出现,死循环啊。
在页面上传入的sql语句难免有些问题,我测试过,一般情况下,系统会自动处理的,但是我想在就不明白,什么情况下,什么样的SQL语句会导致死循环。
——————————————————————————–
你看了有多少个这样线程了吗?
可能不是死循环,而是线程结束后又被启动起来。或者是启动了多个这样的线程。
如果不是我感才说的那个死循环的,就不可能出现死循环了(next和hasNext要成对使用才不会死在那,如果只使用hasNext而不使用next,那么iterator是不往下走的,就会死了。)。
另外它的递归调用也不会超过20层,所以也不会死。
——————————————————————————–
我觉得从自己的应用上来改进应该更好。
——————————————————————————–
回复:zhmt(不爽你就用分砸我!!!)
你说的有道理,如果 t.getMessage() ==null的话,就会陷入死循环。
但是我看我们的代码都是按照JDBC规范来写的啊。
下面我贴些原码,帮我看看有什么问题。
——————————————————————————–
public HashMap getdbValue(PoolBean pool) throws Exception
{
if(pool.getLog().isDebugEnabled())
pool.getLog().debug(“star getdbValue”);
String system_name = pool.getDatabaseInfo().getSystemName();
HashMap result = null;
String temp_sql = createSql();
if(temp_sql == null)
throw new SQLException(“not sql statement”);
Statement stmt = null;
ResultSet rs = null;
Connection con = null;
try
{
con = pool.getNoInfoConnection();// .getConnection();
con.setReadOnly(true);
stmt = con.createStatement();
rs = stmt.executeQuery(temp_sql);
// rs = stmt.executeQuery(sql);
if (rs != null) {
ResultSetMetaData rsmd = rs.getMetaData();
int colCount = rsmd.getColumnCount();
if (rs.next()) {
result = new HashMap();
for (int i = 1; i <= colCount; i++) {
String name = rsmd.getColumnName(i);
name = name.toLowerCase();
String type_name = rsmd.getColumnTypeName(i).toLowerCase();
// System.out.println(“field name : ” + name + ” , type_anme : ” + type_name);
if (“text”.equals(type_name)) {
//当字段类型为text时,如果直接用rs.getObject(i)取数据,在jtds1.0版本中不能直接取出,改为以下方式即可 2005-07-22 张贵平
String tt_str = rs.getString(i);
// System.out.println(“text — “+tt_str);
if (tt_str == null)
tt_str = “”;
else
tt_str = tt_str.trim();
result.put(name.trim(), tt_str);
}
else {
Object obj_value = rs.getObject(i);
if (obj_value instanceof java.lang.String) {
String t_str = null;
if (obj_value == null)
t_str = “”;
else
t_str = String.valueOf(obj_value).trim();
result.put(name.trim(), t_str);
}
else {
result.put(name.trim(), obj_value);
}
}
}
}
rsmd = null;
}
rs.close();
stmt.close();
con.setReadOnly(false);
con.close();
}
catch(SQLException e)
{
//CloseCon.Close(con);
pool.getLog().error(system_name+”,”+e.getMessage()+”,sql:”+temp_sql);
throw new SQLException(“database perform error : ” + e.getMessage());
}
finally
{
CloseCon.Close(con);
}
return result;
}
从线程堆栈上看$java.sql.Statement$$EnhancerByCGLIB$$1a91e2dc.close()
,是从stmt.close()进去的。
——————————————————————————–
觉得不规范
rs.close();
stmt.close();
con.setReadOnly(false);
con.close();
以上这些东西都要放在finnally块中的。
我没用过PoolBean,不知道怎么用,觉得数据库的操作好像没多大问题。你倒网上搜索资料看看吧。
——————————————————————————–
你看下Filter里面的跳转是不是错了。
——————————————————————————–
回复:zhmt(不爽你就用分砸我!!!)
PoolBean 是我们自己写的一个类,主要是做跟连接池的衔接工作。
是的,不是很规范,但是这样也应该不会导致proxool死循环。
——————————————————————————–
我们自己的Filter类,看看有什么问题。
public class SetCharacterEncodingFilter implements Filter {
Log log = LogFactory.getLog(this.getClass().getName());
// —————————————————– Instance Variables
/**
* The default character encoding to set for requests that pass through
* this filter.
*/
protected String encoding = null;
/**
* The filter configuration object we are associated with. If this value
* is null, this filter instance is not currently configured.
*/
protected FilterConfig filterConfig = null;
/**
* 上传文件的最大大小
*/
protected int fileMaxLength = 200*1024; //200K
/**
* Should a character encoding specified by the client be ignored?
*/
protected boolean ignore = true;
/**
* Take this filter out of service.
*/
public void destroy() {
this.encoding = null;
this.filterConfig = null;
}
/**
* Select and set (if specified) the character encoding to be used to
* interpret request parameters for this request.
*
* @param request The servlet request we are processing
* @param result The servlet response we are creating
* @param chain The filter chain we are processing
*
* @exception IOException if an input/output error occurs
* @exception ServletException if a servlet error occurs
*/
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
// Conditionally select and set the character encoding to be used
HttpServletRequest t_re = (HttpServletRequest) request;
String re_uri = trimString(t_re.getRequestURI());
String re_host = trimString(t_re.getServerName());
String qu_str = trimString(t_re.getQueryString());
if (re_uri.indexOf(“.do”) > 0)
{
if (log.isInfoEnabled())
log.info(re_host + re_uri + “?” + qu_str);
try
{
if (ignore || (request.getCharacterEncoding() == null)) {
String encoding = selectEncoding(request);
if (encoding != null)
request.setCharacterEncoding(encoding);
}
// Pass control on to the next filter
chain.doFilter(request, response);
}
catch(Exception e)
{
// e.printStackTrace();
String error_mes = e.getMessage();
String strServerName = null;
String strQueryString = null;
String requestUrl = null;
String remoteAddr = null;
String referer = “”;
if(error_mes.indexOf(“reset”)<0 )
{
try {
strServerName = t_re.getServerName();
strQueryString = t_re.getQueryString();
requestUrl = t_re.getRequestURI();
// strQueryString = CodeTransfer.ISOToUnicode(strQueryString);
referer = t_re.getHeader(“referer”);
remoteAddr = t_re.getRemoteAddr();
}
catch (Exception e1) {}
if (error_mes != null && !”null”.equals(error_mes)&& error_mes.length() > 0) {
log.error(“,exception:” +
error_mes + strServerName + ” , ” + strQueryString + ” , ” +
requestUrl + ” , ” + referer);
// System.out.println(“exception at filter:” +
// error_mes);
}
}
if(log.isInfoEnabled())
log.info(strServerName + ” , ” + strQueryString+ ” , ” + requestUrl + ” , ” + referer);
}
}
/**
* Place this filter into service.
*
* @param filterConfig The filter configuration object
*/
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
this.encoding = filterConfig.getInitParameter(“encoding”);
String value = filterConfig.getInitParameter(“ignore”);
String file_max_length = filterConfig.getInitParameter(“file_max_length”);
if(file_max_length!=null && file_max_length.length() >0)
{
fileMaxLength = com.kenfor.util.MyUtil.getStringToInt(file_max_length,200)*1024;
}
if (value == null)
this.ignore = true;
else if (value.equalsIgnoreCase(“true”))
this.ignore = true;
else if (value.equalsIgnoreCase(“yes”))
this.ignore = true;
else
this.ignore = false;
}
/**
* Select an appropriate character encoding to be used, based on the
* characteristics of the current request and/or filter initialization
* parameters. If no character encoding should be set, return
* null.
*
* The default implementation unconditionally returns the value configured
* by the encoding initialization parameter for this
* filter.
*
* @param request The servlet request we are processing
*/
protected String selectEncoding(ServletRequest request) {
return (this.encoding);
}
private String trimString(String value)
{
String result = “”;
if(value !=null)
result = value.trim();
return result;
}
}
——————————————————————————–
如果真的是proxool,那我应该感到欣慰,如果是我们写的代码不当引起的,但我就真的无地之容了。
——————————————————————————–
呵呵,这个我也搞不清楚,楼主最好把你们的那个poolBean自己测试一下。
能找到那种情况下出那个错误是最好的。
看看循环使用的时候是否也抛出这个异常,如果这样的话就查查哪的问题吧。如果不出错,可能就是sql写的有问题了。
Java on Guice
Java on Guice
Guice 1.0 User’s Guide
Guice (pronounced “juice”) is an ultra-lightweight, next-generation dependency injection container for Java 5 and later.
Introduction
The enterprise Java community exerts a lot of effort toward wiring objects together. How does your web application get access to a middle tier service, or your service to the logged in user or transaction manager? You’ll find many general and specific solutions to this problem. Some rely on patterns. Others use frameworks. All result in varying degrees of testability and some amount of boilerplate code. You’ll soon see that Guice enables the best of all worlds: easy unit testing, maximal flexibility and maintainability, and minimal repetition.
We’ll use an unrealistically simple example to illustrate the benefits of Guice over some classic approaches which you’re probably already familiar with. The following example is so simple in fact that, even though it will show immediate benefits, we won’t actually do Guice justice. We hope you’ll see that as your application grows, Guice’s benefits accelerate.
In this example, a client depends on a service interface. This could be any arbitrary service. We’ll just call it Service.
public interface Service {
void go();
}
We have a default implementation of this service which the client should not depend directly on. If we decide to use a different service implementation in the future, we don’t want to go around and change all of our clients.
public class ServiceImpl implements Service {
public void go() {
…
}
}
We also have a mock service which we can use in unit tests.
public class MockService implements Service {
private boolean gone = false;
public void go() {
gone = true;
}
public boolean isGone() {
return gone;
}
}
Plain Old Factories
private ServiceFactory() {}
private static Service instance = new ServiceImpl();
public static Service getInstance() {
return instance;
}
public static void setInstance(Service service) {
instance = service;
}
}
Our client goes directly to the factory every time it needs a service.
public void go() {
Service service = ServiceFactory.getInstance();
service.go();
}
}
The client is simple enough, but the unit test for the client has to pass in a mock service and then remember to clean up afterwards. This isn’t such a big deal in our simple example, but as you add more clients and services, all this mocking and cleaning up creates friction for unit test writing. Also, if you forget to clean up after your test, other tests may succeed or fail when they shouldn’t. Even worse, tests may fail depending on which order you run them in.
public void testClient() {
Service previous = ServiceFactory.getInstance();
try {
final MockService mock = new MockService();
ServiceFactory.setInstance(mock);
Client client = new Client();
client.go();
assertTrue(mock.isGone());
}
finally {
ServiceFactory.setInstance(previous);
}
}
Finally, note that the service factory’s API ties us to a singleton approach. Even if getInstance() could return multiple instances, setInstance() ties our hands. Moving to a non-singleton implementation would mean switching to a more complex API.
Dependency Injection By Hand
While the client asked the factory for a service in our previous example, with dependency injection, the client expects to have its dependency passed in. Don’t call me, I’ll call you, so to speak.
private final Service service;
public Client(Service service) {
this.service = service;
}
public void go() {
service.go();
}
}
MockService mock = new MockService();
Client client = new Client(mock);
client.go();
assertTrue(mock.isGone());
}
Now, how do we connect the client with a service? When implementing dependency injection by hand, we can move all dependency logic into factory classes. This means we need a factory for our client, too.
private ClientFactory() {}
public static Client getInstance() {
Service service = ServiceFactory.getInstance();
return new Client(service);
}
}
Dependency Injection with Guice
Guice aims to eliminate all of this boilerplate without sacrificing maintainability.
With Guice, you implement modules. Guice passes a binder to your module, and your module uses the binder to map interfaces to implementations. The following module tells Guice to map Service to ServiceImpl in singleton scope:
public void configure(Binder binder) {
binder.bind(Service.class)
.to(ServiceImpl.class)
.in(Scopes.SINGLETON);
}
}
private final Service service;
@Inject
public Client(Service service) {
this.service = service;
}
public void go() {
service.go();
}
}
For Guice to inject Client, we must either directly ask Guice to create a Client instance for us, or some other class must have Client injected into it.
Guice vs. Dependency Injection By Hand
Guice enables you to specify scopes declaratively. For example, you don’t have to write the same code to store an object in the HttpSession over and over.
In the real world, you often don’t know an implementation class until runtime. You need meta factories or service locators for your factories. Guice addresses these problems with minimal effort.
When injecting dependencies by hand, you can easily slip back into old habits and introduce direct dependencies, especially if you’re new to the concept of dependency injection. Using Guice turns the tables and makes doing the right thing easier. Guice helps keep you on track.
More Annotations
public interface Service {
void go();
}
By default, Guice injects a new instance every time. If you want to specify a different scope, you can annotate the implementation class, too.
public class ServiceImpl implements Service {
public void go() {
…
}
}
Architectural Overview
Startup
public void configure(Binder binder) {
// Bind Foo to FooImpl. Guice will create a new
// instance of FooImpl for every injection.
binder.bind(Foo.class).to(FooImpl.class);
// Bind Bar to an instance of Bar.
Bar bar = new Bar();
binder.bind(Bar.class).toInstance(bar);
}
}
Creating an Injector entails the following steps:
- First, create an instance of your module and pass it to Guice.createInjector().
- Guice creates a Binder and passes it to your module.
- Your module uses the binder to define bindings.
- Based on the bindings you specified, Guice creates an Injector and returns it to you.
- You use the injector to inject an object.
Runtime
Each binding has a provider which provides instances of the necessary type. You can provide a class, and Guice will create instances of it for you. You can give Guice an instance of the type you’re binding to. You can implement your own provider, and Guice can inject dependencies into it.
Each binding also has an optional scope. Bindings have no scope by default, and Guice creates a new instance for every injection. A custom scope enables you to control whether or not Guice creates a new instance. For example, you can create one instance per HttpSession.
Bootstrapping Your Application
Your code should deal directly with the Injector as little as possible. Instead, you want to bootstrap your application by injecting one root object. The container can further inject dependencies into the root object’s dependencies, and so on recursively. In the end, your application should ideally have one class (if that many) which knows about the Injector, and every other class should expect to have dependencies injected.
For example, a web application framework such as Struts 2 bootstraps your application by injecting all of your actions. You might bootstrap a web service framework by injecting your service implementation classes.
Dependency injection is viral. If you’re refactoring an existing code base with a lot of static methods, you may start to feel like you’re pulling a never-ending thread. This is a Good Thing. It means dependency injection is making your code more flexible and testable.
If you get in over your head, rather than try to refactor an entire code base all in one shot, you might temporarily store a reference to the Injector in a static field somewhere or use static injection. Name the field’s class clearly though: InjectorHack and GodKillsAKittenEveryTimeYouUseMe come to mind. Keep in mind that you you’ll have to mock this class, and your unit tests will have to install an Injector here by hand, and remember to clean up afterwards.
Binding Dependencies
When injecting a dependency, Guice first looks for an explicit binding, a binding which you specified using the Binder. The Binder API uses the builder pattern to create a domain-specific expression language. Different methods return different objects depending on the context limiting you to appropriate methods.
For example, to bind an interface Service to a concrete implementation ServiceImpl, call:
void injectService(Service service) {
…
}
Note: In contrast to some other frameworks, Guice gives no special treatment to “setter” methods. Guice will inject any method with any number of parameters so long as the method has an @Inject annotation, even if the method is in a superclass.
DRY (Don’t Repeat Yourself)
We’ll use this syntax throughout the rest of the guide.
Annotating Bindings
.annotatedWith(Blue.class)
.to(BlueService.class);
void injectService(@Blue Service service) {
…
}
Creating Binding Annotations
Where did this @Blue annotation just mentioned come from? You can create such an annotation easily, although the standard incantation you have to use is unfortunately a little complex:
* Indicates we want the blue version of a binding.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER})
@BindingAnnotation
public @interface Blue {}
Luckily, we don’t really have to understand it all just to use it. But for the curious, here’s what all this boilerplate means:
- @Retention(RUNTIME) allows your annotation to be visible at runtime.
- @Target({FIELD, PARAMETER}) is a courtesy to your users; it prevents @Blue from being applied to methods, types, local variables, and other annotations, where it would serve no purpose.
- @BindingAnnotation is a Guice-specific signal that you wish your annotation to be used in this way. Guice will produce an error whenever user applies more than one binding annotation to the same injectable element.
Annotations With Attributes
You can also bind to annotation instances, i.e. you can have multiple bindings with the same type and annotation type, but with different annotation attribute values. If Guice can’t find a binding to an annotation instance with the necessary attribute values, it will look for a binding to the annotation type instead.
Say for example we have a binding annotation @Named with a single string attribute value.
@Retention(RUNTIME)
@Target({ FIELD, PARAMETER })
@BindingAnnotation
public @interface Named {
String value();
}
class NamedAnnotation implements Named {Now we can use this annotation implementation to create bindings to @Named.
final String value;
public NamedAnnotation(String value) {
this.value = value;
}
public String value() {
return this.value;
}
public int hashCode() {
// This is specified in java.lang.Annotation.
return 127 * “value”.hashCode() ^ value.hashCode();
}
public boolean equals(Object o) {
if (!(o instanceof Named))
return false;
Named other = (Named) o;
return value.equals(other.value());
}
public String toString() {
return “@” + Named.class.getName() + “(value=” + value + “)”;
}
public Class<? extends Annotation> annotationType() {
return Named.class;
}
}
.annotatedWith(new NamedAnnotation(“Bob”))
.to(Bob.class);
Since identifying a binding by name is such a common use case, Guice provides a production-worthy implementation of @Named in com.google.inject.name.
Implicit Bindings
@Inject
Mixer(Concrete concrete) {
…
}
}
Injecting Providers
void injectAtm(Provider<Money> atm) {
Money one = atm.get();
Money two = atm.get();
…
}
As you can see, the Provider interface couldn’t get much simpler so it doesn’t get in the way of easy unit testing.
Injecting Constant Values
- Primitive types (int, char, …)
- Primitive wrapper types (Integer, Character, …)
- Strings
- Enums
- Classes
First, when binding to constant values of these types, you needn’t specify the type you’re binding to. Guice can figure it out from the value. For example, given a binding annotation named TheAnswer:
Converting Strings
If Guice still can’t find an explicit binding for one of the above types, it will look for a constant String binding with the same binding annotation and try to convert its value. For example:
Custom Providers
final Service service;
@Inject
WidgetProvider(Service service) {
this.service = service;
}
public Widget get() {
return new Widget(service);
}
}
Example: Integrating With JNDI
import com.google.inject.*;
import javax.naming.*;
class JndiProvider<T> implements Provider<T> {
@Inject Context context;
final String name;
final Class<T> type;
JndiProvider(Class<T> type, String name) {
this.name = name;
this.type = type;
}
public T get() {
try {
return type.cast(context.lookup(name));
}
catch (NamingException e) {
throw new RuntimeException(e);
}
}
/**
* Creates a JNDI provider for the given
* type and name.
*/
static <T> Provider<T> fromJndi(
Class<T> type, String name) {
return new JndiProvider<T>(type, name);
}
}
We can use our custom JndiProvider to bind DataSource to an object from JNDI:
import static mypackage.JndiProvider.fromJndi;
import javax.naming.*;
import javax.sql.DataSource;
…
// Bind Context to the default InitialContext.
bind(Context.class).to(InitialContext.class);
// Bind to DataSource from JNDI.
bind(DataSource.class)
.toProvider(fromJndi(DataSource.class, “…”));
Scoping Bindings
class MySingleton {
…
}
Specify annotations for custom scopes using Binder.bindScope(). For example, given an annotation @SessionScoped and a Scope implementation ServletScopes.SESSION:
Creating Scope Annotations
- Have a @Retention(RUNTIME) annotation so we can see the annotation at runtime.
- Have a @Target({TYPE}) annotation. Scope annotations only apply to implementation classes..
- Have a @ScopeAnnotation meta-annotation. Only one such annotation can apply to a given class.
For example:
* Scopes bindings to the current transaction.
*/
@Retention(RUNTIME)
@Target({TYPE})
@ScopeAnnotation
public @interface TransactionScoped {}
Eagerly Loading Bindings
Injecting Between Scopes
Development Stages
During development, Guice will load singleton objects on demand. This way, your application starts up fast and only loads the parts you’re testing.
In production, Guice will load all your singleton objects at startup. This helps catch errors early and takes any performance hits up front.
Your modules can also apply method interceptors and other bindings based on the current stage. For example, an interceptor might verify that you don’t use your objects out of scope during development.
Intercepting Methods
…
binder.bindInterceptor(
any(), // Match classes.
annotatedWith(Transactional.class), // Match methods.
new TransactionInterceptor() // The interceptor.
);
Try to shoulder as much of the filtering as is possible on the matchers rather than in the interceptor’s body as the matching code runs only once at startup.
Static Injection
For these situations, Guice supports injecting less accessible static members. For example, HTTP session objects often need to be serializable to support replication, but what if your session object depends on a container-scoped object? We can keep a transient reference to the object, but how do we look it up again upon deserialization?
We’ve found the most pragmatic solution to be static injection:
class User {
@Inject
static AuthorizationService authorizationService;
…
}
Optional Injection
If someone creates a binding for Formatter, Guice will inject an instance from that binding. Otherwise, assuming Formatter isn’t injectable itself (see Implicit Bindings), Guice will skip the optional member.
Optional injection applies only to fields and methods, not constructors. In the case of methods, if a binding for one parameter is missing, Guice won’t inject the method at all, even if bindings to other parameters are available.
Binding to Strings
…
bind(named(“bob”)).to(10);
Struts 2 Support
A Counting Example
public class Counter {
int count = 0;
/** Increments the count and returns the new value. */
public synchronized int increment() {
return count++;
}
}
final Counter counter;
@Inject
public Count(Counter counter) {
this.counter = counter;
}
public String execute() {
return SUCCESS;
}
public int getCount() {
return counter.increment();
}
}
class=”mypackage.Count”>
<result>/WEB-INF/Counter.jsp</result>
</action>
<html>
<body>
<h1>Counter Example</h1>
<h3><b>Hits in this session:</b>
<s:property value=”count”/></h3>
</body>
</html>
JMX Integration
See com.google.inject.tools.jmx.
Appendix: How the Injector resolves injection requests
The injector’s process of resolving an injection request depends on the bindings that have been made and the annotations found on the types involved. Here is a summary of how an injection request is resolved:
- Observe the Java type and the optional “binding annotation” of the element to be injected. If the type is com.google.inject.Provider<T>, perform resolution for the type indicated by T instead. Find a binding for this (type, annotation) pair. If none, skip to #4.
- Follow transitive bindings. If this binding links to another binding, follow this edge and check again, repeating until we reach a binding which does not link to any other binding. We are now at the most specific explicit binding for this injection request.
- If this binding specifies an instance or a Provider instance, we’re done; use this to fulfill the request.
- If, at this point, the injection request used an annotation type or value, we have failed and we produce an error.
- Otherwise examine the Java type for this binding; if an @ImplementedBy annotation is found, instantiate the referenced type. If a @ProvidedBy annotation is found, instantiate the referenced provider and use it to obtain the desired object. Otherwise attempt to instantiate the type itself.
2008年最值得学习的5个Java技术
Carlos Perez发表了2008年最值得学习的5个Java技术:
1.OSGi(特别是Java动态模型方面)
OSGi service platform是一个基于Java的platform,OSGi service platform是一个开放并且提供统一接口标准的体系框架,基于这个体系框架,服务提供商,程序开发人员,软件提供商,服务网管运营商,设备提供商能够协调地联合起来开发,部署以及管理向用户提供的各种服务。
2.JCP JAVA内容仓库(Java Content Repository) 2002年一月发布
3.GWT (Google Web Toolkit ) 2006年5月发布,Google 推出的一个开发 Ajax 应用的框架,它支持用 Java 开发和调试 Ajax 应用。
4.Groovy 2004年5月发布,Groovy是一种基于JVM的敏捷开发语言,它结合了Python、Ruby和Smalltalk的许多强大的特性。Java开发者可以使用类似Java的语法来获得这些特性的支持。
5.Cloud computing 云计算(虚拟服务器设计,不使用EJB的分布式运算)
这是一个很有意思的名单,因为以上技术都算比较“老”的技术了,你认为2008最应该值得学习的java技术是什么?
附:什么是JCP JAVA内容仓库(Java Content Repository)?
JSR -170把自己定义为一个能与内容仓库互相访问的,独立的,标准的方式。同时它也对内容仓库做出了自己的定义,它认为内容仓库是一个高级的信息管理系统,该系统是是传统的数据仓库的扩展,它提供了诸如版本控制、全文检索,访问控制,内容分类、访问控制、内容事件监视等内容服务。
Java Content Repository API(JSR-170)试图建立一套标准的API去访问内容仓库。如果你对内容管理系统(CMS)不熟悉的话,你一定会对内容仓库是什么感到疑惑。你可以这样去理解,把内容仓库理解为一个用来存储文本和二进制数据(图片,word文档,PDF等等)的数据存储应用程序。一个显著的特点是你不用关心你真正的数据到底存储在什么地方,是关系数据库?是文件系统?还是XML?不仅仅是数据的存储和读取,大多数的内容仓库还提供了更加高级的功能,例如访问控制,查找,版本控制,锁定内容等等。
一段时间以来市场上出现了各个厂家开发的不同的CMS系统,这些系统都建立在他们各自的内容仓库之上。
问题出现了,每个CMS开发商都提供了他们自己的API来访问内容仓库。这对应用程序的开发者带来了困扰,因为他们要学习不同的开发商提供的API,同时,他们的代码也与这些特定的API产生了绑定。
JSR-170正是为解决这一问题而出现的,它提供了一套标准的API来访问任何数据仓库。通过JSR-170,你开发代码只需要引用 javax.jcr.* 这些类和接口。它适用于任何兼容JSR-170规范的内容仓库。
我们将通过一个例子来逐步了解JSR-170。
为什么需要 Java Content Repository API
随着各个厂家各自的内容仓库实现数量的增长,人们越来越需要一组通用的编程接口来使用这些内容仓库,这就是JSR-170所要做的东西。它提供一组通用的编程接口来连接内容仓库。你可以把JSR-170理解为和JDBC类似的API,这样你可以不依赖任何具体的内容仓库实现来开发你的程序。你可以直接使用支持JSR-170的内容仓库;或者如果一些厂家的内容仓库不支持JSR-170则可以通过这些厂家提供的JSR-170驱动来完成从JSR-170与厂家特定的内容仓库的转换。
下面这张图描述了使用JSR-170开发的应用系统的结构。在该系统运行的时候,它可以操作内容仓库1,2,3中的任意一个。在这些内容仓库当中,只有2 是直接支持JSR-170的,剩下的两个都需要JSR-170驱动来和应用系统交互。注意:你的应用系统完全不用关心你的数据是如何存储的。1可能使用了关系数据库来存储,而2使用了文件系统,至于上,它甚至更前卫的使用了XML。
JSR-170 API对不同的人员提供了不同的好处。
●对于开发者无需了解厂家的仓库特定的API,只要兼容JSR-170就可以通过JSR-170访问其仓库。
●对于使用CMS的公司则无需花费资金用于在不同种类CMS的内容仓库之间进行转换。
●对于CMS厂家,无需自己开发内容仓库,而专注于开发CMS应用。
Googlipse-不错的GWT Eclipse插件
最近发现一个很不错的用于在Eclipse IDE下应用GWT开发AJAX的插件,叫Googlipse,名字还很好记,呵呵.
它的最近发布版本是0.5.4版,可以支持GWT1.4.60,不过在sourceforge.net里的邮件列表里发现原来这个插件已经停止开发与BUG修复了,真是可惜.现在把安装与使用方法简单翻译一下,以防自己以后忘记,也方便大家学习.不过,本人E文也一般,大致上给翻译一下, 翻译的很生硬,不过主要的信息还是体现出来了,大家将就一下
准备:
1) 下载:http://sourceforge.net/projects/googlipse
2) 安装前提:
a) Eclipse 3.2 with WebTools Platform 1.5(一定要装,)
b) 已经安装了JDK 1.5以上
c) 还需要下载 Google Web Toolkit , 网址是: http://code.google.com/webtoolkit/
安装插件到制作实例的全过程(英文是从官方网站上COPY的)
(*) Drop the com.googlipse.gwt_<version>.jar file in your eclipse\plugins folder
将com.googlipse.gwt_<version>.jar文件放到你的Eclipse安装文件夹中的plugins文件夹下 (译者注: 我这里用的的com.googlipse.gwt_0.5.4.jar)
(*) Open Eclipse. Select Window->Preferences->Googlipse and set GWT home to the directory where you have installed the Google Web Toolkit.
打开Eclipse, 选择Window->Preferences->Googlipse , 设置GWT安装目录
(*) You are all set to code.
(此句不知该怎么翻译..-_-!)
Adding Googlipse to your project:
Googlipse is implemented as a WTP Facet. When creating a new Dynamic Web Project, select Googlipse in the Project Facets page. If you already have a Dynamic Web Project, you can add Googlipse facet by selecting Project->Properties->Project Facets(Please make sure you don’t have gwt-user.jar in your classpath). In case you didn’t like Googlipse, you can remove the facet.
添加Googlipse到你的工程:
Googlipse是一个实现了WTP的插件(Facet这个单词不知道具体要怎么翻译,暂且翻译成”插件”). 当新建一个的动态WEB工程时,可在工程模块页面中选择Googlipse.如果已经有一个动态WEB工程时,可以通过 Project->Properties->Project Facets 添加Googlipse插件(请确认gwt-user.jar在不在你的classpath中). 假使你不喜欢Googlipse,你也可以移除它.
Creating a Module:
Once you have a Dynamic Web Project with Googlipse facet, you can add a new module by File->New->Other->Googlipse->Gwt Module. Modules can be created only in valid java packages (default package is not allowed). Either you can type in the package (with project & source folder) in the location field or you can select it by clicking Browse button. You can also click the Create button to create a new package. Next type in the name of the module. Click Finish, you will have all the artifacts for the module generated.
新建一个模块:
当有了一个包含Googlipse插件的动态WEB工程后,你可以通过 File->New->Other->Googlipse->Gwt Module 添加一个新的模块. 这些模块只能被创建到一个有效的包中(默认包名不允许使用),
你可以指定包名(包含工程名和源文件夹名)或通过点击Browse按钮选择包. 你也可以自己新建一个包. 然后输入模块名称,点击Finish, 就可以得到这个模块生成的组件.
Adding a Remote Service;
Note :A Remote Service will be created only in a module. So if you don’t have a module, you need to create one using the New Module wizard, before this step.
You can select File->New->Other->Googlipse->Gwt Remote Service. Click the Browse button and select the module (the gwt.xml file). Type the name and uri for the service and click Finish. Now the artifacts for the remote service will be generated. (You have to add an entry in the gwt.xml file manually. Googlipse doesn’t add it. This feature will be implemented in future versions)
添加远程服务:
提示: 一个模块中只能创建一个远程服务. 在这一步之前, 如果你没有模块, 你需要使用New Module向导创建一个新模块
选择: File->New->Other->Googlipse->Gwt Remote Service , 点击Browse按钮,选择当前模块(即gwt.xml文件),输入该服务的名程和uri地址,然后点击Finish. 现在这个远程服务的组件就已经生成了.(你必须手动地在gwt.xml文件中添加配置. Googlipse并不自动添加, 在以后的版本中将支持该功能)
Adding a Remote Service method:
You can open the RemoteService interface and add/change methods in it. You need to provide the implementation of those methods in RemoteServiceImpl class, but thanks to Googlipse, you don’t have to do anything in RemoteServiceAsync. Googlipse will automatically update the corresponding Async file whenever a RemoteService interface is changed.
添加一个远程服务的方法:
你可以打开RemoteService接口并添加/修改其中的方法. 你需要在RemoteServiceImpl类中提供这些方法的实现, 不过有了Googlipse, 你不需要做任何事情,当RemoteService接口改变时Googlipse会自动更新相应的文件
Calling a method using Remote Service:
The utility class in the Remote service should help you in making the remote call.
MyRemoteServiceAsync async = MyRemoteService.Util.getInstance();
async.makeRemoteCall(param1, param2, callback);
在远程服务中调用一个方法:
在远程服务的实体类会帮你产生相应的远程调用.
MyRemoteServiceAsync async = MyRemoteService.Util.getInstance();
async.makeRemoteCall(param1, param2, callback);
Running/Debugging a Gwt Application:
Select Run->Run/Debug to activate the Lauch configuration dialog box. Double Click “Gwt Application”. In the main page, you can select the Project & Module you want to run. In the parameters page you can select the parameters such as port and log level. Click Run to execute the GwtShell & bring up your application. The laucher will add the jar files & all the source folders in the project to your application.
运行/调试:
选择 Run->Run/Debug 显示Lauch configuration对话框, 双击”Gwt Application”. 在main页面中,选择要运行的工程和模块.在parameters页面中选择参数,如端口和日志级别. 点击Run,即可执行GwtShell并加载你的应用程序, GwtShell将添加工程中的jar包和所有的源文件夹到你的应用程序中