﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-学习笔迹-文章分类-Java</title><link>http://www.blogjava.net/chenlb/category/17116.html</link><description>好记性不如烂笔头!</description><language>zh-cn</language><lastBuildDate>Mon, 17 Mar 2008 14:31:23 GMT</lastBuildDate><pubDate>Mon, 17 Mar 2008 14:31:23 GMT</pubDate><ttl>60</ttl><item><title>必读：彻底明白Java的IO系统---JAVA之精髓IO流！ </title><link>http://www.blogjava.net/chenlb/articles/186758.html</link><dc:creator>流浪汗</dc:creator><author>流浪汗</author><pubDate>Mon, 17 Mar 2008 06:26:00 GMT</pubDate><guid>http://www.blogjava.net/chenlb/articles/186758.html</guid><wfw:comment>http://www.blogjava.net/chenlb/comments/186758.html</wfw:comment><comments>http://www.blogjava.net/chenlb/articles/186758.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/chenlb/comments/commentRss/186758.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/chenlb/services/trackbacks/186758.html</trackback:ping><description><![CDATA[转载：<a href="http://www.cnblogs.com/wjun530/archive/2007/06/14/782898.html">http://www.cnblogs.com/wjun530/archive/2007/06/14/782898.html</a><br />
<br />
彻底明白Java的IO系统 <br />
<br />
一． Input和Output<br />
1. stream代表的是任何有能力产出数据的数据源，或是任何有能力接收数据的接收源。在Java的IO中，所有的stream（包括Input和Out stream）都包括两种类型：<br />
1.1 以字节为导向的stream<br />
以字节为导向的stream，表示以字节为单位从stream中读取或往stream中写入信息。以字节为导向的stream包括下面几种类型：<br />
1) input　stream：<br />
1) ByteArrayInputStream：把内存中的一个缓冲区作为InputStream使用<br />
2) StringBufferInputStream：把一个String对象作为InputStream<br />
3) FileInputStream：把一个文件作为InputStream，实现对文件的读取操作<br />
4) PipedInputStream：实现了pipe的概念，主要在线程中使用<br />
5) SequenceInputStream：把多个InputStream合并为一个InputStream<br />
2) Out　stream<br />
1) ByteArrayOutputStream：把信息存入内存中的一个缓冲区中<br />
2) FileOutputStream：把信息存入文件中<br />
3) PipedOutputStream：实现了pipe的概念，主要在线程中使用<br />
4) SequenceOutputStream：把多个OutStream合并为一个OutStream<br />
1.2 以Unicode字符为导向的stream<br />
以Unicode字符为导向的stream，表示以Unicode字符为单位从stream中读取或往stream中写入信息。以Unicode字符为导向的stream包括下面几种类型：<br />
1) Input　Stream<br />
1) CharArrayReader：与ByteArrayInputStream对应<br />
2) StringReader：与StringBufferInputStream对应<br />
3) FileReader：与FileInputStream对应<br />
4) PipedReader：与PipedInputStream对应<br />
2) Out　Stream<br />
1) CharArrayWrite：与ByteArrayOutputStream对应<br />
2) StringWrite：无与之对应的以字节为导向的stream<br />
3) FileWrite：与FileOutputStream对应<br />
4) PipedWrite：与PipedOutputStream对应<br />
以字符为导向的stream基本上对有与之相对应的以字节为导向的stream。两个对应类实现的功能相同，字是在操作时的导向不同。如CharArrayReader：和ByteArrayInputStream的作用都是把内存中的一个缓冲区作为InputStream使用，所不同的是前者每次从内存中读取一个字节的信息，而后者每次从内存中读取一个字符。<br />
1.3 两种不现导向的stream之间的转换<br />
InputStreamReader和OutputStreamReader：把一个以字节为导向的stream转换成一个以字符为导向的stream。<br />
2. stream添加属性<br />
2.1 &#8220;为stream添加属性&#8221;的作用<br />
运用上面介绍的Java中操作IO的API，我们就可完成我们想完成的任何操作了。但通过FilterInputStream和FilterOutStream的子类，我们可以为stream添加属性。下面以一个例子来说明这种功能的作用。<br />
如果我们要往一个文件中写入数据，我们可以这样操作：<br />
FileOutStream fs = new FileOutStream(&#8220;test.txt&#8221;);<br />
然后就可以通过产生的fs对象调用write()函数来往test.txt文件中写入数据了。但是，如果我们想实现&#8220;先把要写入文件的数据先缓存到内存中，再把缓存中的数据写入文件中&#8221;的功能时，上面的API就没有一个能满足我们的需求了。但是通过FilterInputStream和FilterOutStream的子类，为FileOutStream添加我们所需要的功能。<br />
2.2 FilterInputStream的各种类型<br />
2.2.1 用于封装以字节为导向的InputStream<br />
1) DataInputStream：从stream中读取基本类型（int、char等）数据。<br />
2) BufferedInputStream：使用缓冲区<br />
3) LineNumberInputStream：会记录input stream内的行数，然后可以调用getLineNumber()和setLineNumber(int)<br />
4) PushbackInputStream：很少用到，一般用于编译器开发<br />
2.2.2 用于封装以字符为导向的InputStream<br />
1) 没有与DataInputStream对应的类。除非在要使用readLine()时改用BufferedReader，否则使用DataInputStream<br />
2) BufferedReader：与BufferedInputStream对应<br />
3) LineNumberReader：与LineNumberInputStream对应<br />
4) PushBackReader：与PushbackInputStream对应<br />
2.3 FilterOutStream的各种类型<br />
2.2.3 用于封装以字节为导向的OutputStream<br />
1) DataIOutStream：往stream中输出基本类型（int、char等）数据。<br />
2) BufferedOutStream：使用缓冲区<br />
3) PrintStream：产生格式化输出<br />
2.2.4 用于封装以字符为导向的OutputStream<br />
1) BufferedWrite：与对应<br />
2) PrintWrite：与对应<br />
3. RandomAccessFile<br />
1) 可通过RandomAccessFile对象完成对文件的读写操作<br />
2) 在产生一个对象时，可指明要打开的文件的性质：r，只读；w，只写；rw可读写<br />
3) 可以直接跳到文件中指定的位置<br />
4. I/O应用的一个例子<br />
import java.io.*;<br />
public class TestIO{<br />
public static void main(String[] args)<br />
throws IOException{<br />
//1.以行为单位从一个文件读取数据<br />
BufferedReader in = <br />
new BufferedReader(<br />
new FileReader("F:\\nepalon\\TestIO.java"));<br />
String s, s2 = new String();<br />
while((s = in.readLine()) != null)<br />
s2 += s + "\n";<br />
in.close();<br />
<br />
//1b. 接收键盘的输入<br />
BufferedReader stdin = <br />
new BufferedReader(<br />
new InputStreamReader(System.in));<br />
System.out.println("Enter a line:");<br />
System.out.println(stdin.readLine());<br />
<br />
//2. 从一个String对象中读取数据<br />
StringReader in2 = new StringReader(s2);<br />
int c;<br />
while((c = in2.read()) != -1)<br />
System.out.println((char)c);<br />
in2.close();<br />
<br />
//3. 从内存取出格式化输入<br />
try{<br />
DataInputStream in3 = <br />
new DataInputStream(<br />
new ByteArrayInputStream(s2.getBytes()));<br />
while(true)<br />
System.out.println((char)in3.readByte()); <br />
}<br />
catch(EOFException e){<br />
System.out.println("End of stream");<br />
}<br />
<br />
//4. 输出到文件<br />
try{<br />
BufferedReader in4 =<br />
new BufferedReader(<br />
new StringReader(s2));<br />
PrintWriter out1 =<br />
new PrintWriter(<br />
new BufferedWriter(<br />
new FileWriter("F:\\nepalon\\ TestIO.out")));<br />
int lineCount = 1;<br />
while((s = in4.readLine()) != null)<br />
out1.println(lineCount++ + "：" + s);<br />
out1.close();<br />
in4.close();<br />
}<br />
catch(EOFException ex){<br />
System.out.println("End of stream");<br />
}<br />
<br />
//5. 数据的存储和恢复<br />
try{<br />
DataOutputStream out2 = <br />
new DataOutputStream(<br />
new BufferedOutputStream(<br />
new FileOutputStream("F:\\nepalon\\ Data.txt")));<br />
out2.writeDouble(3.1415926);<br />
out2.writeChars("\nThas was pi:writeChars\n");<br />
out2.writeBytes("Thas was pi:writeByte\n");<br />
out2.close();<br />
DataInputStream in5 =<br />
new DataInputStream(<br />
new BufferedInputStream(<br />
new FileInputStream("F:\\nepalon\\ Data.txt")));<br />
BufferedReader in5br =<br />
new BufferedReader(<br />
new InputStreamReader(in5));<br />
System.out.println(in5.readDouble());<br />
System.out.println(in5br.readLine());<br />
System.out.println(in5br.readLine());<br />
}<br />
catch(EOFException e){<br />
System.out.println("End of stream");<br />
}<br />
<br />
//6. 通过RandomAccessFile操作文件<br />
RandomAccessFile rf =<br />
new RandomAccessFile("F:\\nepalon\\ rtest.dat", "rw");<br />
for(int i=0; i&lt;10; i++)<br />
rf.writeDouble(i*1.414);<br />
rf.close();<br />
<br />
rf = new RandomAccessFile("F:\\nepalon\\ rtest.dat", "r");<br />
for(int i=0; i&lt;10; i++)<br />
System.out.println("Value " + i + "：" + rf.readDouble());<br />
rf.close();<br />
<br />
rf = new RandomAccessFile("F:\\nepalon\\ rtest.dat", "rw");<br />
rf.seek(5*8);<br />
rf.writeDouble(47.0001);<br />
rf.close();<br />
<br />
rf = new RandomAccessFile("F:\\nepalon\\ rtest.dat", "r");<br />
for(int i=0; i&lt;10; i++)<br />
System.out.println("Value " + i + "：" + rf.readDouble());<br />
rf.close();<br />
}<br />
}<br />
关于代码的解释（以区为单位）：<br />
1区中，当读取文件时，先把文件内容读到缓存中，当调用in.readLine()时，再从缓存中以字符的方式读取数据（以下简称&#8220;缓存字节读取方式&#8221;）。<br />
1b区中，由于想以缓存字节读取方式从标准IO（键盘）中读取数据，所以要先把标准IO（System.in）转换成字符导向的stream，再进行BufferedReader封装。<br />
2区中，要以字符的形式从一个String对象中读取数据，所以要产生一个StringReader类型的stream。<br />
4区中，对String对象s2读取数据时，先把对象中的数据存入缓存中，再从缓冲中进行读取；对TestIO.out文件进行操作时，先把格式化后的信息输出到缓存中，再把缓存中的信息输出到文件中。<br />
5区中，对Data.txt文件进行输出时，是先把基本类型的数据输出屋缓存中，再把缓存中的数据输出到文件中；对文件进行读取操作时，先把文件中的数据读取到缓存中，再从缓存中以基本类型的形式进行读取。注意in5.readDouble()这一行。因为写入第一个writeDouble()，所以为了正确显示。也要以基本类型的形式进行读取。<br />
6区是通过RandomAccessFile类对文件进行操作。<br />
<br />
----<br />
<br />
重要提示：<br />
<br />
LineNumberInputStream，StringBufferInputStream已经废除！大家不要再用！<br />
<br />
StringBufferInputStream，This class does not properly convert characters into bytes！<br />
<br />
StringBufferInputStream，Deprecated. This class incorrectly assumes that bytes adequately represent characters！<br />
<br />
<br />
----------------关心IO，就是关心你的JAVA前途之路！-----------------------<br />
<p>DataInputStream流中已经没有readLine()整个方法！<br />
<br />
替换为： BufferedReader d=new BufferedReader(new InputStreamReader(in));<br />
<br />
--------把字节流转换为字符流接入缓存读取字符流中，再进行处理！<br />
这个方法很大的优势！<br />
<br />
----------------------<br />
-----------------Why use character streams?------------------<br />
The primary advantage of character streams is that they make it easy to write programs that are not dependent upon a specific character encoding, and are therefore easy to internationalize. <br />
Java stores strings in Unicode, an international standard character encoding that is capable of representing most of the world's written languages. Typical user-readable text files, however, use encodings that are not necessarily related to Unicode, or even to ASCII, and there are many such encodings. Character streams hide the complexity of dealing with these encodings by providing two classes that serve as bridges between byte streams and character streams. The InputStreamReader class implements a character-input stream that reads bytes from a byte-input stream and converts them to characters according to a specified encoding. Similarly, the OutputStreamWriter class implements a character-output stream that converts characters into bytes according a specified encoding and writes them to a byte-output stream. <br />
<br />
A second advantage of character streams is that they are potentially much more efficient than byte streams. The implementations of many of Java's original byte streams are oriented around byte-at-a-time read and write operations. The character-stream classes, in contrast, are oriented around buffer-at-a-time read and write operations. This difference, in combination with a more efficient locking scheme, allows the character stream classes to make up for the added overhead of encoding conversion in many cases. <br />
<br />
----------标准设备System.in读取数据------------------<br />
-----------------------------------------------------<br />
读取字节：BufferedInputStream<br />
读取字符：BufferedReader + InputStreamReader<br />
----------------------------------------------<br />
import java.io.*;<br />
<br />
public class systemin<br />
{<br />
public static void main(String args[])<br />
{ try{ //流转换！<br />
BufferedReader is=new BufferedReader(new InputStreamReader(System.in))<br />
String inputline=null;<br />
while((inputline=is.readLine())!=null)<br />
System.out.println(inputline);<br />
is.close(); <br />
}<br />
catch(IOException e)<br />
{ System,out.println("IOXE: "+e);<br />
}<br />
}<br />
} <br />
--------------------------------------------------------------------------------<br />
<br />
-----------------标准输出System.out是一个打印流PrintStream---------------------<br />
import java.io.*;<br />
<br />
<br />
public class PrintStandardOutput {<br />
<br />
public static void main(String[] args) {<br />
String myAnswer = "No, and that's final,";<br />
System.out.println("Hello World of Java");<br />
System.out.println("The answer is " + myAnswer + " at this time."); <br />
<br />
PrintWriter pw = new PrintWriter(System.out);<br />
pw.println("The answer is " + myAnswer + " at this time."); <br />
<br />
<br />
int i = 42;<br />
pw.println(i + '=' + " the answer."); <br />
pw.println("Note: " + i + '=' + " the answer."); <br />
pw.println(i + "=" + " the answer.");<br />
pw.println(i + ('=' + " the answer.")); <br />
<br />
pw.close(); <br />
}<br />
}<br />
-----------------------------------------------------------------------------------<br />
-----------------------要读取(输出到—）一个文本文件-----------------------------<br />
<br />
<br />
BufferedReader is=new BufferedReader(new FileReader("xxxx.text"));读取<br />
BufferedOutputStream byteout=new BufferedOutputStream(new FileOutputStream("XX.dat"));<br />
// 写出到文本！<br />
<br />
-----------------------------------------------<br />
<br />
---------------利用 BufferedReader--FileReader读取文本文件！-----------<br />
<br />
---------------在IO中始终要注意是字节流还是字符流----------------------<br />
-----------------------------------------------------------------------<br />
import java.io.*;<br />
import java.awt.*;<br />
import javax.swing.*;<br />
import java.awt.event.*;<br />
<br />
class filewindow extends JFrame implements ActionListener<br />
{<br />
JTextArea text;<br />
BufferedReader in;<br />
JButton button;<br />
FileReader file;<br />
filewindow()<br />
{<br />
super("文件字符流");<br />
Container con=getContentPane();<br />
text=new JTextArea(50,50);<br />
text.setBackground(Color.blue);<br />
try{<br />
File f=new File("E:\\a.txt");<br />
file=new FileReader(f);<br />
in=new BufferedReader(file);<br />
/**BufferedReader（Reader in)构造函数，<br />
*文件自字符读取流FileReader接入BufferedReader<br />
*流中，以便用BufferedReader的对象方法readLine()高效成行读取！<br />
*/<br />
<br />
}<br />
catch(FileNotFoundException e){} <br />
catch(IOException e){}<br />
button=new JButton("读取");<br />
button.addActionListener(this);<br />
con.setLayout(new BorderLayout());<br />
setSize(300,200);<br />
setVisible(true);<br />
<br />
con.add(text,"Center");<br />
con.add(button,"South");<br />
addWindowListener(new WindowAdapter()<br />
{public void windowClosing(WindowEvent e)<br />
{setVisible(false);System.exit(0);}});<br />
<br />
}<br />
public void actionPerformed(ActionEvent e)<br />
{<br />
String s;<br />
if(e.getSource()==button)<br />
try{<br />
while((s=in.readLine())!=null)<br />
text.append(s+'\n');<br />
//在这里大家还可以用BufferString来暂时保存读取的字符数据！<br />
}<br />
catch(IOException e1){}<br />
}<br />
//---------main()----------<br />
public static void main(String args[])<br />
{<br />
filewindow win=new filewindow();<br />
win.pack();<br />
}<br />
}<br />
<br />
<br />
-------------------RandomAccessFile随机读取文件---------------<br />
import java.io.*;<br />
<br />
<br />
public class RandomRead<br />
{<br />
final static String FILENAME="E:\\a.txt";<br />
protected String fileName;<br />
protected RandomAccessFile seeker;<br />
<br />
public static void main(String[] argv) throws IOException {<br />
RandomRead r = new RandomRead(FILENAME);<br />
<br />
System.out.println("Offset is " + r.readOffset());<br />
System.out.println("Message is \"" + r.readMessage() + "\".");<br />
}<br />
<br />
/** Constructor: save filename, construct RandomAccessFile */<br />
public RandomRead(String fname) throws IOException {<br />
fileName = fname;<br />
seeker = new RandomAccessFile(fname, "rw");<br />
}<br />
<br />
/** Read the Offset field, defined to be at location 0 in the file. */<br />
public int readOffset() throws IOException {<br />
seeker.seek(0);<br />
seeker.writeChars(FILENAME); // move to very beginning<br />
return seeker.readInt(); // and read the offset<br />
}<br />
<br />
/** Read the message at the given offset */<br />
public String readMessage() throws IOException {<br />
seeker.seek(120); // move to where<br />
return seeker.readLine(); // and read the String<br />
}<br />
}<br />
<br />
写得很辛苦,我本来不想再说什么了,但本着对技术负责的精神还是说出来.<br />
<br />
对于I/O的理解属于3级水平(如果java IO有十级的话)<br />
错误太多.<br />
对于I/O层次不熟悉<br />
java IO主要包括<br />
java.io包和java.nio包.<br />
<br />
java.io主要从四个接口延伸:<br />
字节:<br />
InputStream/OutputStream,其下为封装,过滤,特定对象处理的具体实现类.<br />
字符:<br />
Reader/Writer(原文中连Writer接口全都写成Write,足以说明根本不了解这了接口,如果你经常使用Writer接口怎么会连Writer和Write都分不清,不是一处失误,而是全部都是Write)<br />
<br />
以上四个接口中,底层全部是操作字节的阻塞方式流.<br />
<br />
java.nio主要以块操作块(Buffer)为主,通过可以设定的阻塞和非阴塞模式,极大地提过了数据输出输<br />
入的性能,而且将Channel通过选选择器模式的控制,可以实现在同一输出输入通道上多用户并发进行数据传输入.比如一个Socket端口可以同时被无限多(理论上不受限制)个客户端并发访问.就是经典的I/O多路复用技术.<br />
<br />
</p>
<img src ="http://www.blogjava.net/chenlb/aggbug/186758.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/chenlb/" target="_blank">流浪汗</a> 2008-03-17 14:26 <a href="http://www.blogjava.net/chenlb/articles/186758.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]Spring2.5的新特性</title><link>http://www.blogjava.net/chenlb/articles/179940.html</link><dc:creator>流浪汗</dc:creator><author>流浪汗</author><pubDate>Thu, 14 Feb 2008 07:40:00 GMT</pubDate><guid>http://www.blogjava.net/chenlb/articles/179940.html</guid><wfw:comment>http://www.blogjava.net/chenlb/comments/179940.html</wfw:comment><comments>http://www.blogjava.net/chenlb/articles/179940.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/chenlb/comments/commentRss/179940.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/chenlb/services/trackbacks/179940.html</trackback:ping><description><![CDATA[<br />
<p>从诞生之初，Spring框架就坚守它的宗旨：简化企业级应用开发，同时给复杂问题提供强大的、非侵入性解决方案。一年前发布的Spring2.0就把这些主题推到了一个新的高度。XML Schema的支持和自定义命名空间的使用大大减少了基于XML的配置。使用Java5及更新版本java的开发人员如今可以利用植入了像泛型（generic）和注解等新语言特性的Spring库。最近，和AspectJ表达式语言的紧密集成，使得以非侵入方式添加跨越定义良好的Spring管理对象分组的行为成为可能。</p>
<p>新发布的Spring2.5继续坚持了这个发展趋向，特别是为那些使用Java 5或更新版本java的开发人员提供了进一步简化而强大的新特性。这些新特性包括：注解驱动的依赖性注入（annotation-driven dependency injection），使用注解而非XML元数据来自动侦测classpath上的Spring组件，注解对生命周期方法的支持，一个新的web控制器模型将请求映射到加注解的方法上，在测试框架中支持Junit4，Spring XML命名空间的新增内容，等等。</p>
<p>本文是探讨这些新特性的3篇系列文章中的第一篇。本文将主要关注于简化的配置和在Spring应用程序上下文（application context）核心新增的基于注解的功能；第二篇文章将涵盖web层可用的新特性；最后一篇文章将着重介绍集成和测试的新增性能。这一系列的三篇文章中引用的例子都基于Spring PetClinic应用程序范例。此范例最近被重构以用于展示Spring最新功能，并被包含于Spring 2.5的发布下载包中，可以从Spring Framework <a href="http://www.springframework.org/download">下载网页</a>下载。查看"samples/petclinic"目录下的"readme.txt"文件可以得知关于如何构建和部署PetClinic应用程序，掌握本文提到的新技术的最佳方法也许就是对PetClinic应用程序中所展示的特性进行试验。</p>
<h2>Spring支持JSR-250注解</h2>
<p>Java EE5中引入了&#8220;Java平台的公共注解（Common Annotations for the Java Platform）&#8221;，而且该公共注解从Java SE 6一开始就被包含其中。 2006年5月，BEA系统宣布了他们在一个名为<a href="http://www.springsource.com/web/guest/pitchfork">Pitchfork</a>的项目上与Interface21的<a href="http://www.bea.com/framework.jsp?CNT=pr01660.htm&amp;FP=/content/news_events/press_releases/2006">合作</a>，该项目提供了基于Spring的Java EE 5编程模型的实现，包括支持用于注入（injection）、拦截（ interception）和事务处理（transactions）的JSR-250注解和EJB 3注解(JSR-220)。 在2.5版本中，Spring框架的<strong>核心（core）</strong>现在支持以下JSR-250注解：</p>
<ul>
    <li>@Resource
    <li>@PostConstruct
    <li>@PreDestroy </li>
</ul>
<p>结合Spring，这些注解在任何开发环境下都可以使用——无论是否有应用程序服务器——甚至是集成测试环境都可以。激活这样的支持仅仅是注册一个单独的Spring post-processor的事情：</p>
<pre><font color="#3f7f7f">&lt;bean</font> <font color="#7f007f">class</font>=<font color="#2a00ff">"org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"</font><font color="#3f7f7f">/&gt;</font> <br />
</pre>
<h3>@Resource注解</h3>
<p><strong>@Resource</strong> 注解被用来激活一个命名资源（named resource）的依赖注入，在JavaEE应用程序中，该注解被典型地转换为绑定于JNDI context中的一个对象。 Spring确实支持使用<strong>@Resource</strong>通过JNDI lookup来解析对象，默认地，拥有与<strong>@Resource</strong>注解所提供名字相匹配的&#8220;bean name（bean名字）&#8221;的Spring管理对象会被注入。 在下面的例子中，Spring会向加了注解的setter方法传递bean名为&#8220;<strong>dataSource</strong>&#8221;的Spring管理对象的引用。</p>
<pre><strong>@Resource(name="dataSource")</strong><br />
<font color="#7f0055"><strong>public void</strong></font> setDataSource(DataSource dataSource) {<br />
<font color="#7f0055"><strong>this</strong></font>.<font color="#0000c0">dataSource</font> = dataSource;<br />
} </pre>
<p>直接使用<strong>@Resource</strong>注解一个域（field）同样是可能的。通过不暴露setter方法，代码愈发紧凑并且还提供了域不可修改的额外益处。正如下面将要证明的，<strong>@Resource</strong>注解甚至不需要一个显式的字符串值，在没有提供任何值的情况下，域名将被当作默认值。</p>
<pre>@Resource<br />
<font color="#7f0055"><strong>private</strong></font> DataSource dataSource; <font color="#3f7f5f">// inject the bean named 'dataSource'</font> </pre>
<p>该方式被应用到setter方法的时候，默认名是从相应的属性衍生出来，换句话说，命名为<strong>'setDataSource'</strong>的方法被用来处理名为<strong>'dataSource'</strong>的属性。</p>
<pre><font color="#7f0055"><strong>private</strong></font> DataSource <font color="#0000c0">dataSource</font>;<br />
@Resource<br />
<font color="#7f0055"><strong>public void</strong></font> setDataSource(DataSource dataSource) {<br />
<font color="#7f0055"><strong>this</strong></font>.<font color="#0000c0">dataSource</font> = dataSource;<br />
} </pre>
<p>当<strong>@Resource</strong>没有显式提供名字的时候，如果根据默认名字找不到对应的Spring管理对象，注入机制会回滚至类型匹配（type-match）。如果刚好只有一个Spring管理对象符合该依赖的类型，那么它会被注入。通过设置<strong>CommonAnnotationBeanPostProcessor</strong> 的<strong>&#8216;fallbackToDefaultTypeMatch&#8217;</strong>属性为&#8220;false&#8221;（默认值是&#8220;true&#8221;）可以禁用这一特性。</p>
<pre><font color="#3f7f7f">&lt;bean</font> <font color="#7f007f">class</font>=<font color="#2a00ff">"org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"</font><font color="#3f7f7f">&gt;</font><br />
<font color="#3f7f7f">&lt;property</font> <font color="#7f007f">name</font>=<font color="#2a00ff">"fallbackToDefaultTypeMatch"</font> <font color="#7f007f">value</font>=<font color="#2a00ff">"false"</font><font color="#3f7f7f">/&gt;</font><br />
<font color="#3f7f7f">&lt;/bean&gt;</font> </pre>
<p>正如上文所提到的，在解析标有<strong>@Resource</strong>注解的依赖时，Spring支持JNDI-lookup。如若要强制对所有使用<strong>@Resource</strong>注解的依赖进行JNDI lookup，那也只要将<strong>CommonAnnotationBeanPostProcessor</strong>的<strong>'alwaysUseJndiLookup'</strong> 标识设置为true就可以了（默认值是false）。</p>
<pre><font color="#3f7f7f">&lt;bean</font> <font color="#7f007f">class</font>=<font color="#2a00ff">"org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"</font><font color="#3f7f7f">&gt;</font><br />
<font color="#3f7f7f">&lt;property</font> <font color="#7f007f">name</font>=<font color="#2a00ff">"alwaysUseJndiLookup"</font> <font color="#7f007f">value</font>=<font color="#2a00ff">"true"</font><font color="#3f7f7f">/&gt;</font><br />
<font color="#3f7f7f">&lt;/bean&gt;</font></pre>
<p>另一个选择是，激活指定为&#8216;resource-ref-mappings&#8217;的依据全局JNDI名的查找，在<strong>@Resource</strong>注解内提供&#8216;<strong>mappedName&#8217;</strong>属性。即使目标对象实际上是一个JNDI资源，仍然推荐引入一个Spring管理对象，这样可以提供一个间接层并且因此降低耦合程度。自Spring2.0开始添加命名空间以来，定义一个委托Spring处理JNDI lookup的bean也变得愈发简练：</p>
<pre><font color="#3f7f7f">&lt;jee:jndi-lookup</font> <font color="#7f007f">id</font>=<font color="#2a00ff">"dataSource"</font> <font color="#7f007f">jndi-name</font>=<font color="#2a00ff">"java:comp/env/jdbc/petclinic"</font><font color="#3f7f7f">/&gt;</font> <br />
</pre>
<p>这个方法的优点在于间接层带来了巨大的部署弹性。比如说，一个单独的系统测试环境应该不再需要JNDI注册。在这种情况下，在系统测试配置中可以提供如下的bean定义：</p>
<pre><font color="#3f7f7f">&lt;bean</font> <font color="#7f007f">id</font>=<font color="#2a00ff">"dataSource"</font> <font color="#7f007f">class</font>=<font color="#2a00ff">"org.springframework.jdbc.datasource.DriverManagerDataSource"</font><br />
<font color="#7f007f">p:driverClassName</font>=<font color="#2a00ff">"${jdbc.driverClassName}"</font><br />
<font color="#7f007f">p:url</font>=<font color="#2a00ff">"${jdbc.url}"</font><br />
<font color="#7f007f">p:username</font>=<font color="#2a00ff">"${jdbc.username}"</font><br />
<font color="#7f007f">p:password</font>=<font color="#2a00ff">"${jdbc.password}"</font><font color="#3f7f7f">/&gt;</font> </pre>
<p>顺便提一下，上面的例子中，实际的JDBC连接属性从一个属性文件（properties file）解析而来，在这个属性文件里，关键字与提供的${占位符}互相对应，这需要注册一个名为<strong>PropertyPlaceholderConfigurer</strong>的<strong>BeanFactoryPostProcessor</strong>实现来完成。这是具体化那些属性（通常是针对特定环境的属性）常用的技术，这些属性可能比其他配置修改得更为频繁。</p>
<pre><font color="#3f7f7f">&lt;bean</font> <font color="#7f007f">class</font>=<font color="#2a00ff">"org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"</font><font color="#3f7f7f">&gt;</font><br />
<font color="#3f7f7f">&lt;property</font> <font color="#7f007f">name</font>=<font color="#2a00ff">"location"</font> <font color="#7f007f">value</font>=<font color="#2a00ff">"classpath:jdbc.properties"</font><font color="#3f7f7f">/&gt;</font><br />
<font color="#3f7f7f">&lt;/bean&gt;</font> </pre>
<p>Srping2.5中新加入了&#8216;context&#8217;命名空间，这个命名空间让我们能够得到更为简洁的方式来实现属性占位符（property placeholder）的配置：</p>
<pre><font color="#3f7f7f">&lt;context:property-placeholder</font> <font color="#7f007f">location</font>=<font color="#2a00ff">"classpath:jdbc.properties"</font><font color="#3f7f7f">/&gt;</font><br />
</pre>
<h3>生命周期注解：@PostConstruct和＠PreDestroy</h3>
<p><strong>@PostConstruct</strong> 和<strong>@PreDestroy</strong>注解分别用来触发Spring的初始化和销毁回调。这个特性在原有基础上得到了扩展，但并没有替代在Spring2.5之前版本中提供的同样的回调的另两个选项。第一个选项是实现Spring的<strong>InitializingBean</strong> 和<strong>DisposableBean</strong> 接口中的一个或两个。这两个接口都需要一个回调方法的实现(分别是<strong>afterPropertiesSet()</strong>和<strong>destroy()</strong> )。这种基于接口的方法利用了Spring自动识别任何实现这些接口的Spring管理对象的能力，因而不再需要另外的配置。另一方面，Spring的一个关键目标是尽可能的非侵入。因此，许多Spring用户并不采用实现这些Spring特定接口的方法，而利用第二个选项，那就是提供他们自己的初始化和销毁方法。尽管入侵性小，但缺点在于使用这个方式的话就必须显式声明<strong>bean</strong>元素的<strong>init-method</strong>或<strong>destroy-method</strong>属性。显式配置有时候是必须的，例如当回调需要在开发人员控制能力之外的代码上被调用的时候。PetClinic应用程序很好地说明了这个场景。当它和JDBC配置一起运行的时候，会用到一个第三方<strong>DataSource</strong>，并且它显式声明了一个<strong>destroy-method</strong>。另外要注意到的是，单独的连接池数据源是<strong>dataSource</strong>的另一个部署选项，并且不需要修改任何代码。</p>
<pre><font color="#3f7f7f">&lt;bean</font> <font color="#7f007f">id</font>=<font color="#2a00ff">"dataSource"</font><br />
<font color="#7f007f">class</font>=<font color="#2a00ff">"org.apache.commons.dbcp.BasicDataSource"</font><br />
<strong>destroy-method="close"</strong><br />
<font color="#7f007f">p:driverClassName</font>=<font color="#2a00ff">"${jdbc.driverClassName}"</font><br />
<font color="#7f007f">p:url</font>=<font color="#2a00ff">"${jdbc.url}"</font><br />
<font color="#7f007f">p:username</font>=<font color="#2a00ff">"${jdbc.username}"</font><br />
<font color="#7f007f">p:password</font>=<font color="#2a00ff">"${jdbc.password}"</font><font color="#3f7f7f">/&gt;</font> </pre>
<p>在使用Spring2.5的过程中，如果一个对象需要调用一个初始化的回调方法的话，这个回调方法可以采用<strong>@PostConstruct</strong>来注解。例如一个假想的例子，一个后台任务需要在启动的时候就开始对一个文件目录进行轮询：</p>
<pre><font color="#7f0055"><strong>public class</strong></font> FilePoller {<br />
<br />
<strong>@PostConstruct</strong><br />
<font color="#7f0055"><strong>public void</strong></font> startPolling() {<br />
...<br />
}<br />
...<br />
} </pre>
<p>类似地，一个在Spring管理对象上用<strong>@PreDestroy</strong>注解的方法会在这个对象寄宿的应用程序上下文（application context）关闭的时候被调用。</p>
<pre><font color="#7f0055"><strong>public class</strong></font> FilePoller {<br />
<br />
<strong>@PreDestroy</strong><br />
<font color="#7f0055"><strong>public void</strong></font> stopPolling() {<br />
...<br />
}<br />
...<br />
} </pre>
<p>在添加了对JSR-250注解的支持以后，现在的Spring2.5结合前面提到的两种生命周期方法的长处。将<strong>@PostConstruct</strong>和<strong>@PreDestroy</strong>作为方法层注解加入，足可以实现在受Spring管理的上下文（context）中触发回调。换句话说，不需要另外基于XML的配置。同时，这两个注解是Java语言本身的一部分（甚至被包括在Java SE 版本6中），所以无需引入特定Spring包。这两个注解拥有在其他环境中也能理解的标识语义的优点，随着时间的推移，Java开发人员可能会发现这些注解在第三方开发库中被越来越多的运用到。最后，基于注解生命周期回调的其中一个有趣的结果是，不止一个方法可以带有这两个注解中的任何一个，并且所有注解了的方法会被调用。</p>
<p>激活刚刚描述的关于<strong>@Resource</strong> 、<strong>@PostConstruct</strong>和<strong>@PreDestroy</strong>注解的所有行为，正如上文提到的，需要为Spring的<strong>CommonAnnotationBeanPostProcessor</strong>提供一个bean定义。但另一个更简练的方法则可能是使用2.5中的新的context命名空间：</p>
<pre><font color="#3f7f7f"><strong>&lt;context:annotation-config/&gt;</strong></font><br />
</pre>
<p>引入这个单个元素将不单单注册一个<strong>CommonAnnotationBeanPostProcessor</strong>，也会像下文将叙述的那样激活自动装配（autowire）行为。<strong>CommonAnnotationBeanPostProcessor</strong>也为<strong>@WebServiceRef</strong> 和<strong>@EJB</strong>注解提供支持。这些将在本文系列的第三篇中和Spring2.5为企业集成提供的其他新特性一起讨论。</p>
<h2>利用注解来优化细粒度自动装配</h2>
<p>涵盖Spring对自动装配支持的文档中常常会提到由于自动装配机制的粗粒度而伴随有很多限制性。Spring2.5之前，自动装配可以通过很多不同的方式来配置：构造器，类型setter，名字setter，或者自动侦测（在该方式中Spring选择自动装配一个构造器或者类型setter）。这些不同的选择确实提供了很大程度的灵活性，但它们中没有一个方法能够提供细粒度控制。换句话说，Spring2.5之前还不可能自动装配某个对象setter方法的特定子集，或者通过类型或名字来自动装配它的一些属性。结果，许多Spring用户意识到将自动装配应用到构建原型和测试中的好处，但当提到在产品中维护和支持系统时，大部分人认为，加入冗长的显式配置对于澄清它所担负的职责是非常值得的。</p>
<p>然而，Spring2.5大幅度地改变了布局。如上文所述，自动配置选项现在已经被扩展，支持JSR-250<strong> @Resource</strong>注解来激活在每个方法或域基础上被命名资源的自动装配。然而，<strong>@Resource</strong>注解若单独使用的话有很多限制。因此，Sring2.5引进了一个名为<strong>@Autowired</strong>的注解进一步提高控制级别。为激活这里所讲的行为需要注册一个单独的bean定义：</p>
<pre><font color="#3f7f7f">&lt;bean</font> <font color="#7f007f">class</font>=<font color="#2a00ff">"org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"</font><font color="#3f7f7f">/&gt;</font><br />
</pre>
<p>另外如上文提到的，context命名空间提供了一个更简明的方法。它将激活本文所讨论的两个post-processor（<strong>AutowiredAnnotationBeanPostProcessor</strong>和<strong>CommonAnnotationBeanPostProcessor</strong>）和我们在Spring2.0中引入的基于注解的post-processor：<strong>RequiredAnnotationBeanPostProcessor</strong>和<strong>PersistenceAnnotationBeanPostProcessor</strong>。</p>
<pre><font color="#3f7f7f">&lt;context:annotation-config/&gt;</font><br />
</pre>
<p>利用<strong>@Autowired</strong> 注解可以对相应类型注入依赖。域、构造器和方法都可以激活此行为。实际上，aotowired方法并不一定要是setter方法，且可以接受多个参数。下面这个例子是完整的可接受的用法：</p>
<pre><strong>@Autowired</strong><br />
<font color="#7f0055"><strong>public void</strong></font> setup(DataSource dataSource, AnotherObject o) { ... } </pre>
<p>默认地，标有<strong>@Autowired</strong>注解的依赖被认为是必须的。然而，也可以将<strong>required</strong>属性值设置为<strong>false</strong>来声明它们中的任何一个。在下面这个例子中，<strong>DefaultStrategy</strong>只有在context命名空间中没有<strong>SomeStrategy</strong>类型的Spring管理对象时才能被使用。</p>
<pre><strong>@Autowired(required=false)</strong><br />
<font color="#7f0055"><strong>private</strong></font> SomeStrategy <font color="#2a00c0">strategy</font> = <font color="#7f0055">new</font> DefaultStrategy(); </pre>
<p>通过类型进行的自动装配明显地在Spring context包含多于一个期望类型的对象的时候造成歧义。默认地，如果一个必须的依赖没不是恰好一个bean与之对应的话，自动装配机制就会失败。同样的，对于任何一个可选属性，如果它拥有一个以上的候选，也都会失败（如果属性可选且没有任何候选可用的话，该属性则会被简单地跳过）。有很多不同的配置选项可以避免这些冲突。</p>
<p>若Context中拥有一个指定类型的一个<strong>主关键</strong>实例，对这个类型定义的bean定义应该包含&#8216;primary&#8217;属性。当Context中含有其他可用实例的时候这个方法就很适用，但那些非主关键实例总是显式配置的。</p>
<pre><font color="#3f7f7f">&lt;bean</font> <font color="#7f007f">id</font>=<font color="#2a00ff">"dataSource"</font> <strong>primary="true"</strong> ... <font color="#3f7f7f">/&gt;</font> <br />
</pre>
<p>在需要更多控制的时候，任何autowired的域、构造参数、或者方法参数可以进一步加注<strong>@Qualifier</strong>注解。qualifier可以包含一个<strong>字符串</strong>值，在这种情况下，Spring会试图通过名字来找到对应的对象。</p>
<pre>@Autowired<br />
<strong>@Qualifier("primaryDataSource")</strong><br />
<font color="#7f0055"><strong>private</strong></font> DataSource dataSource; </pre>
<p><strong>@Qualifier</strong>作为一个独立注解存在的主要原因是它可以被应用在构造器参数或方法参数上，但上文提到的<strong>@Autowired</strong>注解只能运用在构造器或方法本身。</p>
<pre>@Autowired<br />
<font color="#7f0055"><strong>public void</strong></font> setup(<strong>@Qualifier("primaryDataSource")</strong> DataSource dataSource, AnotherObject o) { ... } </pre>
<p>事实上，<strong>@Qualifier</strong>作为一个单独的注解在定制化方面提供了更多的好处。用户自定义的注解在自动装配过程中也可以起到qualifier的作用，最简单的实现方式是在运用自定义注解的同时将<strong>@Qualifier</strong>作为它的元注解。</p>
<pre>@Target({ElementType.<em>FIELD</em>, ElementType.<em>PARAMETER</em>, ElementType.<em>TYPE</em>, ElementType.<em>ANNOTATION_TYPE</em>})<br />
@Retention(RetentionPolicy.<em>RUNTIME</em>)<br />
<strong>@Qualifier</strong><br />
<font color="#7f0055"><strong>public @interface</strong></font> VetSpecialty { ... } </pre>
<p>自定义注解可以选择包含一个值来提供通过名字匹配的功能，但更普遍的用法是将它作为&#8220;标记&#8221;注解或定义一个对qualifier过程提供一些更多含义的值。例如，下面这个摘录则描绘了一个域，它应该和通过名字匹配得到的结果中合格的对象进行自动装配。</p>
<pre>@Autowired<br />
<strong>@VetSpecialty("dentistry")</strong><br />
<font color="#7f0055"><strong>private</strong></font> Clinic dentistryClinic; </pre>
<p>在使用XML配置来达到依赖解析的目标时，<strong>'qualifier'</strong> 子元素可以被加注到bean定义中。在下文的组件扫描部分，我们将呈现一个可供选择的非XML方法。</p>
<pre><font color="#3f7f7f">&lt;bean</font> <font color="#7f007f">id</font>=<font color="#2a00ff">"dentistryClinic"</font> <font color="#7f007f">class</font>=<font color="#2a00ff">"samples.DentistryClinic"</font><font color="#3f7f7f">&gt;</font><br />
<font color="#3f7f7f">&lt;qualifier</font> <font color="#7f007f">type</font>=<font color="#2a00ff">"example.VetSpecialty"</font> <font color="#7f007f">value</font>=<font color="#2a00ff">"dentistry"</font><font color="#3f7f7f">/&gt;</font><br />
<font color="#3f7f7f">&lt;/bean&gt;</font> </pre>
<p>为了避免对<strong>@Qualifier</strong>注解的任何依赖性，可以在Spring context中提供一个<strong>CustomAutowireConfigurer</strong>的bean定义并直接注册所有自定义注解类型：</p>
<pre><font color="#3f7f7f">&lt;bean</font> <font color="#7f007f">class</font>=<font color="#2a00ff">"org.springframework.beans.factory.annotation.CustomAutowireConfigurer"</font><font color="#3f7f7f">&gt;</font><br />
<font color="#3f7f7f">&lt;property</font> <font color="#7f007f">name</font>=<font color="#2a00ff">"customQualifierTypes"</font><font color="#3f7f7f">&gt;</font><br />
<font color="#3f7f7f">&lt;set&gt;</font><br />
<font color="#3f7f7f">&lt;value&gt;</font>example.VetSpecialty<font color="#3f7f7f">&lt;/value&gt;</font><br />
<font color="#3f7f7f">&lt;/set&gt;</font><br />
<font color="#3f7f7f">&lt;/property&gt;</font><br />
<font color="#3f7f7f">&lt;/bean&gt;</font> </pre>
<p>现在，自定义修饰符被显式声明了，就不再需要<strong>@Qualifier</strong>这个元注解符了。</p>
<pre>@Target({ElementType.<em>FIELD</em>, ElementType.<em>PARAMETER</em>, ElementType.<em>TYPE</em>, ElementType.<em>ANNOTATION_TYPE</em>})<br />
@Retention(RetentionPolicy.<em>RUNTIME</em>)<br />
<font color="#7f0055"><strong>public @interface</strong></font> VetSpecialty { ... } </pre>
<p>其实，在配置<strong>AutowiredAnnotationBeanPostProcessor</strong>的时候，取代<strong>@Autowired</strong>注解都是有可能的。</p>
<pre><font color="#3f7f7f">&lt;bean</font> <font color="#7f007f">class</font>=<font color="#2a00ff">"org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"</font><font color="#3f7f7f">&gt;</font><br />
<font color="#3f7f7f">&lt;property</font> <font color="#7f007f">name</font>=<font color="#2a00ff">"autowiredAnnotationType"</font> <font color="#7f007f">value</font>=<font color="#2a00ff">"example.Injected"</font><font color="#3f7f7f">/&gt;</font><br />
<font color="#3f7f7f">&lt;/bean&gt;</font> </pre>
<p>大部分情况下，定义自定义&#8216;标记&#8217;注解的能力结合通过名字或其他文法值进行匹配选项，足以完成自动装配过程的细粒度控制。但Spring还支持在qualifier注解上任意数目的任意属性。比如，下面是一个极为细粒度修饰的例子。</p>
<pre><strong>@SpecializedClinic(species="dog", breed="poodle")</strong><br />
<font color="#7f0055"><strong>private</strong></font> Clinic poodleClinic; </pre>
<p>自定义修饰符的实现应该定义这些属性：</p>
<pre>@Target({ElementType.<em>FIELD</em>, ElementType.<em>PARAMETER</em>, ElementType.<em>TYPE</em>, ElementType.<em>ANNOTATION_TYPE</em>})<br />
@Retention(RetentionPolicy.<em>RUNTIME</em>)<br />
@Qualifier<br />
<font color="#7f0055"><strong>public @interface</strong></font> SpecializedClinic {<br />
<br />
<strong>String species();</strong><br />
<br />
<strong>String breed();</strong><br />
<br />
} </pre>
<p>自定义修饰符<strong>属性</strong>可以匹配那些XML中bean定义的<strong>qualifier</strong>注解的属性子元素。这些元素通常以键／值对方式提供。</p>
<pre><font color="#3f7f7f">&lt;bean</font> <font color="#7f007f">id</font>=<font color="#2a00ff">"poodleClinic"</font> <font color="#7f007f">class</font>=<font color="#2a00ff">"example.PoodleClinic"</font><font color="#3f7f7f">&gt;</font><br />
<font color="#3f7f7f">&lt;qualifier</font> <font color="#7f007f">type</font>=<font color="#2a00ff">"example.SpecializedClinic"</font><font color="#3f7f7f">&gt;</font><br />
<font color="#3f7f7f">&lt;attribute</font> <font color="#7f007f">key</font>=<font color="#2a00ff">"species"</font> <font color="#7f007f">value</font>=<font color="#2a00ff">"dog"</font><font color="#3f7f7f">/&gt;</font><br />
<font color="#3f7f7f">&lt;attribute</font> <font color="#7f007f">key</font>=<font color="#2a00ff">"breed"</font> <font color="#7f007f">value</font>=<font color="#2a00ff">"poodle"</font><font color="#3f7f7f">/&gt;</font><br />
<font color="#3f7f7f">&lt;/qualifier&gt;</font><br />
<font color="#3f7f7f">&lt;/bean&gt;</font> </pre>
<p>目前为止，关于autowire的描述都只是针对单独的实例，其实也支持集合。在任何需要得到所有context中某种特定类型的Spring管理对象的时候，只需要简单地在一个强类型（strongly-typed）集合上加注<strong>@Autowired</strong> 注解。</p>
<pre>@Autowired<br />
<font color="#7f0055"><strong>private</strong></font> List&lt;Clinic&gt; <font color="#2a00c0">allClinics</font>; </pre>
<p>本章节最后一个值得指出的特性是自动装配的使用替代了Spring的Aware接口。在Spring2.5之前，如果某个对象需要一个Spring context的<strong>ResourceLoader</strong>的引用，它可以通过实现<strong>ResourceLoaderAware</strong>的方式使得Spring通过<strong>setResourceLoader</strong>(<strong>ResourceLoader resourceLoader</strong>)方法来提供该依赖。借助同样的方法可以得到Spring管理的<strong>MessageSource</strong>的引用，甚至可以得到<strong>ApplicationContext</strong>本身。对于Spring2.5用户而言，这个行为现在通过autowiring得到全面支持（需要指出的是包含这些Spring特定依赖的时候应该考虑周到，特别是它们只能用于从业务逻辑清楚地分割出来的基础构架代码中）。</p>
<pre>@Autowired<br />
<font color="#7f0055"><strong>private</strong></font> MessageSource messageSource;<br />
<br />
@Autowired<br />
<font color="#7f0055"><strong>private</strong></font> ResourceLoader resourceLoader;<br />
<br />
@Autowired<br />
<font color="#7f0055"><strong>private</strong></font> ApplicationContext applicationContext;<br />
</pre>
<h2>自动侦测Spring组件</h2>
<p>从2.0版本开始，Spring引入了构造型（stereotype）注解的概念以及将<strong>@Repository</strong>注解作为数据访问代码的标记的方法。在此基础上，Spring2.5又加入了两个新的注解 —— <strong>@Service</strong>和<strong>@Controller</strong> 来完成为通常的三层架构（数据访问对象、服务、web控制器）角色委任。Spring2.5也引入了泛型<strong>@Component</strong>注解，其他构造型可从逻辑上对其进行扩展。通过清晰地指明应用程序的角色，这些构造型方便了Spring AOP和post-processor的使用，这些post-processor给基于这些角色的加了注解的对象提供了附加行为。比如，Spring2.0引入了<strong>PersistenceExceptionTranslationPostProcessor</strong>对任何带有<strong>@Repository</strong> 注解的对象自动激活其数据访问异常转换。</p>
<p>这些注解同样可以结合Spring2.5其他一些新性能来使用：自动侦测classpath上的组件。尽管XML已经成为最常见的Spring元数据的格式，但它决不是唯一选择。实际上，Spring容器内的元数据是由纯Java来表示的，当XML被用来定义Spring管理对象时，在实例化过程之前，那些定义会被解析并转化成Java对象。Spring2.5的一个巨大的新功能是支持从源码层注解读取元数据。因而，上文描述的自动装配机制使用注解的元数据来注入依赖，但它仍然需要注册至少一个bean定义以便提供每个Spring管理对象的实现类。组件扫描功能则使得这个XML中最起码的bean定义都不再存在需求性。</p>
<p>正如上面所示，Spring注解驱动的自动装配可以在不牺牲细粒度控制的前提下极大程度地减少XML的使用。组件侦测机制将这个优点更发扬光大。全面替代XML中的配置不再必要，组件扫描反而可以处理XML元数据来简化整体配置。结合XML和注解驱动技术可以得到一个平衡优化的方法，这在2.5版本的PetClinic范例中有详细阐述。在该范例中，基础构架组件（数据源、事务管理等）结合上文提到的外化属性在XML中定义。数据访问层对象也有部分在XML中定义，它们的配置也都利用了<strong>@Autowired</strong>注解来简化依赖注入。最后，web层控制器完全不在XML中显式定义，相反，下面提供的这段配置被用来触发所有web控制器的自动侦测：</p>
<pre><strong><font color="#3f7f7f">&lt;context:component-scan</font> <font color="#7f007f">base-package</font>=<font color="#2a00ff">"org.springframework.samples.petclinic.web"</font><font color="#3f7f7f">/&gt;</font></strong><br />
</pre>
<p>需要注意到的是这段示例中使用到了base-package属性。组件扫描的默认匹配规则会递归侦测该包（多个包可以以逗号分隔的list方式提供）内的所有类的所有Spring构造型注解。正因为如此，PetClinic应用程序范例中的各类控制器的实现都采用了<strong>@Controller</strong>注解（Spring的<strong>内置</strong>构造型之一）。请看下面这个例子：</p>
<pre><strong>@Controller</strong><br />
<font color="#7f0055"><strong>public class</strong></font> ClinicController {<br />
<br />
<font color="#7f0055"><strong>private final</strong></font> Clinic <font color="#2a00c0">clinic</font>;<br />
<br />
@Autowired<br />
<font color="#7f0055"><strong>public</strong></font> ClinicController(Clinic clinic) {<br />
<font color="#7f0055"><strong>this</strong></font>.<font color="#2a00c0">clinic</font> = clinic;<br />
}<br />
... </pre>
<p>自动侦测组件在Spring容器中注册，就像它们在XML中被定义一样。如上所示，那些对象可以轮流利用注解驱动的自动装配。</p>
<p>组件扫描的匹配规则可以通过过滤器（filter）来自定义，以根据类型、AspectJ表达式、或针对命名模式的正则表达式来决定包含或不包含哪些组件。默认的构造型也可以被禁用。比如这里有一个配置的例子，这个配置会忽略默认的构造型，但会自动侦测名字以Stub打头或者包含<strong>@Mock</strong>注解的所有类：</p>
<pre><font color="#3f7f7f">&lt;context:component-scan</font> <font color="#7f007f">base-package</font>=<font color="#2a00ff">"example"</font> <font color="#7f007f">use-default-filters</font>=<font color="#2a00ff">"false"</font><font color="#3f7f7f">&gt;</font><br />
<font color="#3f7f7f">&lt;context:include-filter</font> <font color="#7f007f">type</font>=<font color="#2a00ff">"aspectj"</font> <font color="#7f007f">expression</font>=<font color="#2a00ff">"example..Stub*"</font><font color="#3f7f7f">/&gt;</font><br />
<font color="#3f7f7f">&lt;context:include-filter</font> <font color="#7f007f">type</font>=<font color="#2a00ff">"annotation"</font> <font color="#7f007f">expression</font>=<font color="#2a00ff">"example.Mock"</font><font color="#3f7f7f">/&gt;</font><br />
<font color="#3f7f7f">&lt;/context:component-scan&gt;</font> </pre>
<p>类型匹配的限制性也可以用排他的过滤器控制。例如，<strong>除了@Repository</strong>注解外其他都依赖于默认过滤器，那么就需要加入一个<strong>排他过滤器</strong>(<strong>exclude-filter</strong>)。</p>
<pre><font color="#3f7f7f">&lt;context:component-scan</font> <font color="#7f007f">base-package</font>=<font color="#2a00ff">"example"</font><font color="#3f7f7f">&gt;</font><br />
<font color="#3f7f7f">&lt;context:exclude-filter</font> <font color="#7f007f">type</font>=<font color="#2a00ff">"annotation"</font> <font color="#7f007f">expression</font>=<font color="#2a00ff">"org.springframework.stereotype.Repository"</font><font color="#3f7f7f">/&gt;</font><br />
<font color="#3f7f7f">&lt;/context:component-scan&gt;</font> </pre>
<p>很明显，有很多方法可以扩展组件扫描来注册自定义的类型。构造型注解是最简单的选择，所以构造型概念本身也是可扩展的。像先前提到的，<strong>@Component</strong>是<strong>泛型</strong>模型，<strong>@Repository</strong>、<strong>@Service</strong>,和<strong>@Controller</strong>注解都从该构造型逻辑扩展而得。正因为如此，<strong>@Component</strong>可被用来作为元注解（也就是说，在另外的注解上声明的注解），所有具有<strong>@Component</strong>元注解的自定义注解都会被默认扫描匹配规则自动侦测到。一个例子就有希望让你领会到其实它根本没有听起来那么难。</p>
<p>让我们回想一下在讲<strong>@PostConstruct</strong>和<strong>@PreDestroy</strong>生命周期注解的时候的假想的后台任务。也许一个应用程序有很多很多这样的后台任务，这些任务实例需要XML bean定义以便在Spring context里注册并使它们自己的生命周期方法在正确时候被调用。利用组件扫描就不再需要这些显式的XML bean定义。如果这些后台任务都实现一个相同的接口或者都沿用同样的命名惯例，那么可以用<strong>include-filters</strong>。然而，更简单的方法是为这些任务对象创建一个注解并提供<strong>@Component</strong>元注解。</p>
<pre>@Target({ElementType.<em>TYPE</em>})<br />
@Retention(RetentionPolicy.<em>RUNTIME</em>)<br />
@Documented<br />
<strong>@Component</strong><br />
<font color="#7f0055"><strong>public @interface</strong></font> BackgroundTask {<br />
String value() <font color="#7f0055"><strong>default</strong></font> <font color="#0000c0">""</font>;<br />
} </pre>
<p>然后在所有后台任务的类定义中提供自定义构造型注解。</p>
<pre><strong>@BackgroundTask</strong><br />
<font color="#7f0055"><strong>public class</strong></font> FilePoller {<br />
<br />
@PostConstruct<br />
<font color="#7f0055"><strong>public void</strong></font> startPolling() {<br />
...<br />
}<br />
<br />
@PreDestroy<br />
<font color="#7f0055"><strong>public void</strong></font> stopPolling() {<br />
...<br />
}<br />
...<br />
} </pre>
<p>泛型<strong>@Component</strong>注解可以像例子中提供的那样简单使用，自定义注解技术则提供了一个使用更具涵义的、领域特定的名字的机会。这些领域特定注解提供更深入的机会，比如使用AspectJ切点表达式来识别所有后台任务，以便增加advice来监控这些任务的活动性。</p>
<p>默认的，组件被侦测到的时候，Spring会自动生成一个没有修饰符的类名作为bean名字。上一个例子中，生成的bean名字会是filePoller。但是，任何加注了Spring构造型注解（<strong>@Component</strong>、<strong>@Repository</strong>、<strong>@Service</strong>或 <strong>@Controller</strong>）或是加注了其他的以@Component作为元注解的注解（比如上面例子中的<strong>@BackgroundTask</strong> ）的类，构造型注解的<strong>value</strong>属性可以被显式指定，实例将该值作为它的bean名字注册到context中。接下来的例子里，实例名应该是petClinic而不是默认生成的名字simpleJdbcClinic。</p>
<pre><strong>@Service("petClinic")</strong><br />
<font color="#7f0055"><strong>public class</strong></font> SimpleJdbcClinic {<br />
...<br />
} </pre>
<p>同样的，在下面修正版的FilePoller例子里，生成的bean名字应该是poller而不是filePoller。</p>
<pre><strong>@BackgroundTask("poller")</strong><br />
<font color="#7f0055"><strong>public class</strong></font> FilePoller {<br />
...<br />
} </pre>
<p>虽然所有Spring管理对象都被默认地当作<strong>单例</strong>实例来处理，但有些时候还是有必要为某个对象指明一个备用的范围（scope）。举个例子来说，在web层，一个Spring管理对象可能捆绑到request或session的范围。对于2.0版本，Spring的scope机制更具延展性，这样一来，自定义scope可以被注册到应用程序上下文（application context）。在XML配置中，仅仅是简单地包含进<strong>scope</strong>属性及该scope的名字就可以了。</p>
<pre><font color="#3f7f7f">&lt;bean</font> <font color="#7f007f">id</font>=<font color="#2a00ff">"shoppingCart"</font> <font color="#7f007f">class</font>=<font color="#2a00ff">"example.ShoppingCart"</font> <strong>scope=<font color="#2a00ff">"session"</font></strong><font color="#3f7f7f">&gt;</font><br />
...<br />
<font color="#3f7f7f">&lt;/bean&gt;</font> </pre>
<p>Spring2.5中，为被扫描的组件提供<strong>@Scope</strong>注解可以起到同样的作用。</p>
<pre>@Component<br />
<strong>@Scope("session")</strong><br />
<font color="#7f0055"><strong>public class</strong></font> ShoppingCart {<br />
...<br />
} </pre>
<p>这里要指出的最后一点是使用组件扫描时qualifier注解应用是多么的简单。在上一节，下面这个对象曾被作为使用自定义qualifier注解进行自动装配的例子：</p>
<pre><strong>@VetSpecialty("dentistry")</strong><br />
<font color="#7f0055"><strong>private</strong></font> Clinic <font color="#2a00c0">dentistryClinic</font>; </pre>
<p>同样的例子接着展现了在XML内使用&#8216;qualifier&#8217;元素为依赖提供指定目标bean定义。在使用组件扫描时，XML元数据不是必须的。但自定义修饰符也许在目标类定义中被作为类型层注解而引入。另一个将被扫描的<strong>@Repository</strong>实例作为依赖的例子如下：</p>
<pre>@Repository<br />
<strong>@VetSpecialty("dentistry")</strong><br />
<font color="#7f0055"><strong>public class</strong></font> DentistryClinic <font color="#7f0055"><strong>implements</strong></font> Clinic {<br />
...<br />
} </pre>
<p>最终，因为前面的例子展现了自定义注解及其<strong>属性</strong>的例子，相等同的非XML表示依赖目标的方法如下：</p>
<pre>@Repository<br />
<strong>@SpecializedClinic(species="dog", breed="poodle")</strong><br />
<font color="#7f0055"><strong>public class</strong></font> PoodleClinic <font color="#7f0055"><strong>implements</strong></font> Clinic {<br />
...<br />
} </pre>
<h2>小结</h2>
<p>Spring2.5在很多方面都提供了很有意义的新功能。本文主要关注于怎样通过掌控Java注解的力量将配置简化。就如在JSR-250中定义的那样，Spring支持公共注解（Common Annotations），同时为自动装配过程的更细粒度的控制提供了额外注解。Spring2.5也扩展了从Spring2.0的<strong>@Repository</strong>就开始的构造型（stereotype）注解，并且所有这些构造型注解都可以和新的组件扫描功能结合使用。Spring2.5仍然全面支持基于XML的配置，同时它又引进了一个新的context命名空间对常见配置场景提供更精要的文法。实际上，支持XML和基于注解配置的无缝结合最终产生一个更为平衡的全面的方法。基本构架的复杂配置可以在模块XML文件中定义，而应用程序栈日益增多地更高层配置可以更多的从基于注解的技术中获益——前提是都在同一个Spring2.5应用程序context内。</p>
<p>在接下来的文章中，我们将讨论到在Spring web层强大的基于注解的新功能项。敬请关注该系列的下一篇文章。 </p>
<strong>查看英文原文：</strong><a href="http://www.infoq.com/articles/spring-2.5-part-1;jsessionid=B865B5E9A616768875B173F36EC9693A">What's New in Spring 2.5: Part 1</a>&nbsp;&nbsp;<br />
<br />
<p id="TBPingURL">Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=2054220<br />
<br />
转：<a href="http://blog.csdn.net/andilyliao/archive/2008/01/20/2054220.aspx">http://blog.csdn.net/andilyliao/archive/2008/01/20/2054220.aspx</a></p>
<img src ="http://www.blogjava.net/chenlb/aggbug/179940.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/chenlb/" target="_blank">流浪汗</a> 2008-02-14 15:40 <a href="http://www.blogjava.net/chenlb/articles/179940.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载]Java开发技术十年的回顾与展望</title><link>http://www.blogjava.net/chenlb/articles/89974.html</link><dc:creator>流浪汗</dc:creator><author>流浪汗</author><pubDate>Mon, 25 Dec 2006 12:30:00 GMT</pubDate><guid>http://www.blogjava.net/chenlb/articles/89974.html</guid><wfw:comment>http://www.blogjava.net/chenlb/comments/89974.html</wfw:comment><comments>http://www.blogjava.net/chenlb/articles/89974.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/chenlb/comments/commentRss/89974.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/chenlb/services/trackbacks/89974.html</trackback:ping><description><![CDATA[[转载] <a href="http://news.csdn.net/n/20061219/99619.html">http://news.csdn.net/n/20061219/99619.html</a><br /><br /><br />    从JDK诞生到现在已经有11年的时间了。沧海桑田一瞬间。转眼11年过去了，JDK已经发布了6个版本。在这11年里诞生了无数和Java相关的技术和标准。现在让我们进入时间隧道，重新回到1995年，再来回顾一下Java的发展轨迹和历史变迁。 <br /><br />　　<strong>一、 JDK前传</strong><br /><br />　　在这个世界上，熟悉Java历史的人非常多，如果要问一个人Java是从哪年诞生的，也许大多数人都会回答是1995年（这个非常好记，因为微软的Windows95也是在这一年发布的）。但事实上Java早在上个世纪90年代初就开始酝酿了。 <br /><br />　　1991年4月，Sun公司的James Gosling领导的绿色计划(Green Project)开始着力发展一种分布式系统结构，使其能够在各种消费性电子产品上运行。而Green项目组的成员一开始使用C++语言来完成这个项目，由于Green项目组的成员都具有C++背景，所以他们首先把目光锁定了C++编译器，Gosling首先改写了C++编译器，但很快他就感到C++的很多不足，需要研发一种新的语言Java来替代它，一杯飘香的咖啡成为了它的标志。 <br /><br />　　在17 个月后，整个系统完成了，这个系统是更注重机顶盒式的操作系统，不过在当时市场不成熟的情况下，他们的项目没有获得成功，但Java语言却得到了Sun总裁McNealy的赏识。 <br />　<br />　　直至 1994年下半年，由于Internet的迅猛发展和环球信息网 WWW的快速增长，第一个全球信息网络浏览器Mosaic诞生了；此时，工业界对适合在网络异构环境下使用的语言有一种非常急迫的需求；Games Gosling决定改变绿色计划的发展方向，他们对Oak进行了小规模的改造，就这样，Java在1995年的3月23日诞生了！Java的诞生标志着互联网时代的开始，它能够被应用在全球信息网络的平台上编写互动性及强的Applet程序，而1995年的Applet无疑能给人们无穷的视觉和脑力震荡。我们姑且将Java的这段历史称为Java前传吧。 <br /><br />　　其实Java的诞生颇有那么一股“有心栽花花不开，无心插柳柳成阴”的味道。就象当年Unix和它的前身MULTICS系统一样。<br /><br /><br /><img onclick="if(this.width&gt;screen.width-461) window.open('../../.././1123517557/Fid_46/46_4677.jpg');" alt="" src="http://bbs.lupaworld.com/1123517557/Fid_46/46_4677.jpg" onload="if(this.width&gt;screen.width-460)this.width=screen.width-460;" border="0" twffan="done" /><br /><br />　　图1 Java创始人 James Gosling博士<br /><br />　　<strong>二、JDK的幼年时期(1995～1998)</strong><br /><br />　　Sun继Green项目后又经过了几年的研究，终于在1995年5月23日在SunWorld'95上正式发布Java和HotJava浏览器。在同年，有很多公司先后获得了Java许可证，如Netscape在1995年8月，Oracle在1995年10月分别获得了Java许可证。Sun在1995年发布第一个Java版本后，于1996年1月宣布成立新的业务部门──JavaSoft部，这个部分主要负责开发、销售并支持基于Java技术的产品，由AlanBaratz先生任总裁。 <br /><br />　　在1995年Sun虽然推出了Java，但这只是一种语言，而要想开发复杂的应用程序，必须要有一个的强大的开发库支持还行。因此，Sun在1996年1月23日发布了JDK1.0。这个版本包括了两部分：运行环境（即JRE）和开发环境(即JDK)。在运行环境中包括了核心API、集成API，用户界面API，发布技术，Java虚拟机(JVM)五个部分。而开发环境还包括了编译Java程序的编译器（即javac）。在JDK1.0时代，JDK除了AWT（一种用于开发图形用户界面的API）外，其它的库并不完整。 <br /><br />　　Sun在推出JDK1.0后，紧跟着，Sun在1997年2月18日发布了JDK1.1。JDK1.1相对于JDK1.0最大的改进就是为JVM增加了JIT(即时编译)编译器。JIT和传统的编译器不同，传统的编译器是编译一条，运行完后再将其扔掉，而JIT会将经常用到的指令保存在内容中，在下次调用时就不需要再编译了。这样JDK在效率上有了非常大的提升。 <br /><br />　　Sun在推出JDK1.1后，接着又推出了数个JDK1.x版本。自从Sun推出Java后，JDK的下载量不断彪升，在1997年，JDK的下载量突破了220,000，而在1998年，JDK的下载量已经超过了2,000,000。 <br /><br />　　虽然在1998年之前，Java被众多的软件企业所采用，但由于当时硬件环境和JVM的技术原因，它的应用却很有限。当时Java主要只使用在前端的Applet以及一些移动设备中。然而这并不等于Java的应用只限于这些领域。在1998年是Java开始迅猛发展的一年。在这一年中Sun发布了JSP/Servlet、EJB规范以及将Java分成了J2EE、J2SE和J2ME。标志着Java已经吹响了向企业、桌面和移动3个领域进军的号角。<br /><br />　　<strong>三、JDK的青少年时期(1998～2004)</strong><br /><br />　　到1998年，Java已经走过了3个年头。从JDK1.0到JDK1.1.8。JDK1.x经过了9个小版本的发展，已经初具规模。至此，它已经走出了摇篮，可以去独闯世界了。 <br /><br />　　在1998年12月4日。Sun发布了Java的历史上最重要的一个JDK版本：JDK1.2。这个版本标志着Java已经进入Java2时代。这个时期也是Java飞速发展的时期。 <br /><br />　　在Java2时代Sun对Java进行了很多革命性的变化 ，而这些革命性的变化一直沿用到现在，对Java的发展形成了深远的影响。 <br /><br />　　JDK1.2自从被分成了J2EE、J2SE和J2ME三大块，得到了市场的强烈反响。不仅如此，JDK1.2还对它的API分成了三大类。 <br /><br />　　核心API <br />　　由Sun公司制定的基本的API，所有的Java平台都应该提供。这就是我们平常所说的Java核心类库。 <br /><br />　　可选API <br />　　这是Sun为JDK提供的扩充API，这些API因平台的不同而不同。 <br />?<br />　　特殊API <br />　　用于满足特殊要求的API。如用于JCA和JCE的第三方加密类库。 <br /><br />　　Java2除了上述的一些改进外，还增加了很多新的特性。其中最吸引眼球的当属Swing了。Swing是Java的另一个图形库。它不但有各式各样先进的组件，而且连组件风格都可抽换。在Swing出现后，很快就抢了AWT的风头。但Swing并不是为取代AWT而存在的，事实上Swing是建立在AWT之上的。就象JFace是建立在SWT之上一样。另外Java2还在多线程、集合类和非同步类上做了大量的改进。 <br /><br />　　从JDK1.2开始，Sun以平均2年一个版本的速度推出新的JDK。在2000年5月8日。Sun对JDK1.2进行了重大升级。推出了JDK1.3。 <br /><br />　　Sun在JDK1.3中同样进行了大量的改进，主要表现在一些类库上（如数学运算、新的Timer API等）、在JNDI接口方面增加了一些DNS的支持、增加了JNI的支持，这使得Java可以访问本地资源了、支持XML以及使用新的Hotspot虚拟机代替了传统的虚拟机。 <br /><br />　　在JDK1.3时代，相应的应用程序服务器也得到了广泛的应用，如第一个稳定版本Tomcat3.x在这一时期得到了广泛的应用，WebLogic等商业应用服务器也渐渐被接受。 <br /><br />　　时间如水、生命如歌。转眼到了2002年。Sun在这一年的2月13日发布了JDK历史上最为成熟的版本：JDK1.4。在进入21世纪以来，曾经在.NET平台和Java平台之间发生了一次声势浩大的孰优孰劣的论战，Java的主要问题就是性能。 <br /><br />　　因此，这次Sun将主要精力放到了Java的性能上。在JDK1.4中，Sun放言要对Hotspot虚拟机的锁机制进行了改进，使JDK1.4的性能有了质的飞跃。同时由于Compaq、Fujitsu、 SAS、 Symbian、 IBM等公司的参与，使JDK1.4成为发展最快的一个JDK版本。到JDK1.4为止，我们已经可以使用Java实现大多数的应用了。<br /><br />　　<strong>四、JDK的壮年时期(2004～至今)</strong><br /><br />　　虽然从JDK1.4开始，Java的性能有了显著的提高，但Java又面临着另一个问题，那就是复杂。 <br /><br />　　虽然Java是纯面向对象语言，但它对一些高级的语言特性（如泛型、增强的for语句）并不支持。而且和Java相关的技术，如EJB2.x，也由于它们的复杂而很少有人问津。也许是Sun意识到了这一点。因此，在2004年10月，Sun发布了我们期待已久的版本：JDK1.5，同时，Sun将JDK1.5改名为J2SE5.0。和JDK1.4不同，JDK1.4的主题是性能，而J2SE5.0的主题是易用。Sun之所以将版本号1.5改为5.0，就是预示着J2SE5.0较以前的J2SE版本有着很大的改过。 <br /><br />　　Sun不仅为J2SE5.0增加了诸如泛型、增强的for语句、可变数目参数、注释(Annotations)、自动拆箱（unboxing）和装箱等功能，同时，也更新的企业级规范，如通过注释等新特性改善了EJB的复杂性，并推出了EJB3.0规范。同时又针对JSP的前端界面设计而推出了JSF。这个JSF类似于ASP.NET的服务端控件。通过它可以很快地建立起复杂的JSP界面。 <br /><br />　　到今年年底Sun也再接再厉地推出了J2SE6.0的测试版，预计在2007年初将推出它的正式版。 <br /><br />　　正象J2SE6.0的开发代号“野马（Mustang）”一样，我们已经隐约听到了野马的嘶鸣。据Sun发言人透露，J2SE6.0不仅在性能、易用性方面得到了前所未有的提高，而且还提供了如脚本、全新的API（Swing和AWT等API已经被更新）的支持。而且J2SE6.0是专为Vista而设计的，它在Vista上将会拥有更好的性能。在推出J2SE6.0的同时，J2SE7.0项目也已经启动。 <br /><br />　　在Java发展的十几年的时间里，经历了无数的风风雨雨。现在Java已经成为一种相当成熟的语言了。在这10年的发展中，Java平台吸引了数百万的开发者，在网络计算遍及全球的今天，更是有20亿台设备使用了Java技术。作为Java技术的基础，J2SE功不可没，让我们期望J2SE伴随Java平台一路走好！<br /><br />　　<strong>五、JDK各版的发布时间表 </strong><br /><br />  到现在为止我们已经重新走了一遍Java的历史轨迹。在这一部分，为了有一个总体的认识，让我们来看一看Java发展的时间表。 （版本号 名称 中文名 发布日期） <br /><br />JDK 1.1.4 <br />Sparkler <br />宝石 <br />1997-09-12 <br /><br />JDK 1.1.5 <br />Pumpkin <br />南瓜 <br />1997-12-13 <br /><br />JDK 1.1.6 <br />Abigail <br />阿比盖尔--女子名 <br />1998-04-24 <br /><br />JDK 1.1.7 <br />Brutus<br />布鲁图--古罗马政治家和将军 <br />1998-09-28 <br /><br />JDK 1.1.8 <br />Chelsea <br />切尔西--城市名 <br />1999-04-08 <br /><br />J2SE 1.2 <br />Playground <br />运动场 <br />1998-12-04 <br /><br />J2SE 1.2.1 <br />none<br />无<br />1999-03-30 <br /><br />J2SE 1.2.2 <br />Cricket<br />蟋蟀<br />1999-07-08 <br /><br />J2SE 1.3 <br />Kestrel <br />美洲红隼 <br />2000-05-08 <br /><br />J2SE 1.3.1 <br />Ladybird <br />瓢虫 <br />2001-05-17 <br /><br />J2SE 1.4.0 <br />Merlin <br />灰背隼 <br />2002-02-13 <br /><br />J2SE 1.4.1 <br />grasshopper <br />蚱蜢 <br />2002-09-16 <br /><br />J2SE 1.4.2 <br />Mantis <br />螳螂 <br />2003-06-26 <br /><br />J2SE 5.0 (1.5.0) <br />Tiger <br />老虎 <br />2004-10 <br /><br />J2SE 6.0 (Beta) <br />Mustang <br />野马 <br />2006-04 <br /><br />　　从这个表中我们可以看出一个非常有意思的现象，就是JDK的每一个版本号都使用一个开发代号表示（就是表中的中文名）。而且从JDK1.2.2开始,主要版本(如1.3,1.4,5.0)都是以鸟类或哺乳动物来命名的. 而它们的bug修正版本(如1.2.2,1.3.1,1.4.2)都是以昆虫命名的。<br /><br />　　<strong>六、Java的未来10年</strong><br /><br />　　在2005年的Java One开发者大会上，James Gosling作了题为“Java技术下一个10年贡献”的演讲。谈到未来Java的发展时，James Gosling提到了有关Java软件的性能和复杂性问题。鉴于许多机器运行着大量进程的实际情况，人们对线程模型投以越来越多的关注。 <br /><br />　　随着人们对桌面应用的要求越来越高，系统将变得越来越复杂。他指出： “从工程的角度来看，未来10年内我们所面临的最大挑战就是复杂性问题，” James Gosling说， “目前，我们开展了许多工作以解决应用编程接口、语言以及工具中所涉及的复杂性问题。在工具和用户界面(UI)中都会遇到复杂性问题，Java技术设计人员必须处理好大小尺寸调整和国际化的问题。” <br /><br />　　在这次大会上，James Gosling还同Java技术先驱，现任Kleiner, Perkins Caulfield and Byers合伙人的Bill Joy先生，Sun公司首席科学家John Gage先生，未来研究所主任Paul Saffo先生，Sun杰出工程师Guy Steele先生以及Applied Mindes公司主席及首席技术官Danny Hillis先生等一起探讨了讨论Java语言的过去和未来发展情况。 <br /><br />　　他们认为，Java技术提高了计算的“流动性”，就如同货币的发明提高了商品的流动性一样。无所不在的网络丰富了每个人的信息，就如同可以兑换的货币产生了财富一样。由于从前的网络是很慢的，所以计算被束缚在特定的计算机上，而这种情况将一去不复返了。 <br /><br />　　目前，全球Java开发人员已经超过450万，而与之相对应的是Java社区充满活力和创新精神，这正是Java下一个10年更加繁荣的保障。为了保持Java的增长和推进Java社区的参与, Sun在Java One开发者大会上宣布开放Java核心源代码，以鼓励更多的人参与到社团活动中来，这是Sun为推进社团发展和维护Java技术兼容性而迈出的重要一步。 <br /><br />　　Sun公司总裁兼首席运营官Jonathan Schwartz先生指出，来自Java社团和IBM等全球技术合作伙伴两方面的支持，乃是Java技术在创新和社会进步上继续发挥重要作用的强有力的标志。技术开放和社团建设降低了技术应用的壁垒，其结果是为参与和增长创造了更多的商机，这就形成了价值上千亿美元的Java产业。 <br /><br />　　有很多人认为Java开源后，在众多开发人员的参与之下，Java会变得更加强大。随着Java和IT业界的关系变得更加紧密，Sun公司也将更容易卖出自己兼容Java良好的WEB服务器和操作系统。这个举动将会给软件开发群体带来新的活力，改善Sun公司的公众形象，并同时证明Sun可以成为一个开源社会的“良民”。 <br /><br />　　随着Java的开源，Java的未来似乎变得更加明朗。在未来，Java的应用范围有可能变得更广。Sun董事长麦克里尼在2006年的JavaOne会议上说，“全球有3/4的人还不能接入Internet，这对Java技术伙伴来说是一个巨大的经济机会。瘦客户机、微小的传感器以及其它Java驱动的小装置，可以帮助我们改善人们的生活。他希望Java社区通过他们的工作能够弥合数字鸿沟”。 <br /><br />　　Sun认为，数字媒体将是Java的下一个重点市场，同时，教育和健康将是未来Java发展过程中的两大重点应用领域。但愿Java的未来真能象Sun宣称的那样，成为我们未来生活的一部分。<img src ="http://www.blogjava.net/chenlb/aggbug/89974.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/chenlb/" target="_blank">流浪汗</a> 2006-12-25 20:30 <a href="http://www.blogjava.net/chenlb/articles/89974.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MD5</title><link>http://www.blogjava.net/chenlb/articles/83367.html</link><dc:creator>流浪汗</dc:creator><author>流浪汗</author><pubDate>Fri, 24 Nov 2006 13:12:00 GMT</pubDate><guid>http://www.blogjava.net/chenlb/articles/83367.html</guid><wfw:comment>http://www.blogjava.net/chenlb/comments/83367.html</wfw:comment><comments>http://www.blogjava.net/chenlb/articles/83367.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/chenlb/comments/commentRss/83367.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/chenlb/services/trackbacks/83367.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 收集于网络MD5简介：MD5的全称是Message-Digest Algorithm 5，在90年代初由MIT的计算机科学实验室和RSA Data Security Inc发明，经MD2、MD3和MD4发展而来。Message-Digest泛指字节串(Message)的Hash变换，就是把一个任意长度的字节串变换成一定长的大整数。请注意我使用了“字节串”而不是“字符串”这个词，是因为这种变换只与字...&nbsp;&nbsp;<a href='http://www.blogjava.net/chenlb/articles/83367.html'>阅读全文</a><img src ="http://www.blogjava.net/chenlb/aggbug/83367.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/chenlb/" target="_blank">流浪汗</a> 2006-11-24 21:12 <a href="http://www.blogjava.net/chenlb/articles/83367.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>简单的读写文件</title><link>http://www.blogjava.net/chenlb/articles/80586.html</link><dc:creator>流浪汗</dc:creator><author>流浪汗</author><pubDate>Sat, 11 Nov 2006 07:40:00 GMT</pubDate><guid>http://www.blogjava.net/chenlb/articles/80586.html</guid><wfw:comment>http://www.blogjava.net/chenlb/comments/80586.html</wfw:comment><comments>http://www.blogjava.net/chenlb/articles/80586.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/chenlb/comments/commentRss/80586.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/chenlb/services/trackbacks/80586.html</trackback:ping><description><![CDATA[
		<p> </p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />
				<span style="COLOR: #000000">
						<br />
						<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />
						<br />
						<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />
				</span>
				<span style="COLOR: #0000ff">import</span>
				<span style="COLOR: #000000"> java.io.File;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span>
				<span style="COLOR: #0000ff">import</span>
				<span style="COLOR: #000000"> java.io.FileInputStream;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span>
				<span style="COLOR: #0000ff">import</span>
				<span style="COLOR: #000000"> java.io.FileNotFoundException;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span>
				<span style="COLOR: #0000ff">import</span>
				<span style="COLOR: #000000"> java.io.IOException;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span>
				<span style="COLOR: #0000ff">import</span>
				<span style="COLOR: #000000"> java.nio.ByteBuffer;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span>
				<span style="COLOR: #0000ff">import</span>
				<span style="COLOR: #000000"> java.nio.channels.FileChannel;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><br /><img id="Codehighlighter1_214_975_Open_Image" onclick="this.style.display='none'; Codehighlighter1_214_975_Open_Text.style.display='none'; Codehighlighter1_214_975_Closed_Image.style.display='inline'; Codehighlighter1_214_975_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_214_975_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_214_975_Closed_Text.style.display='none'; Codehighlighter1_214_975_Open_Image.style.display='inline'; Codehighlighter1_214_975_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" /></span>
				<span style="COLOR: #0000ff">public</span>
				<span style="COLOR: #000000"> </span>
				<span style="COLOR: #0000ff">class</span>
				<span style="COLOR: #000000"> ReadAString </span>
				<span id="Codehighlighter1_214_975_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
						<img src="http://www.blogjava.net/images/dot.gif" />
				</span>
				<span id="Codehighlighter1_214_975_Open_Text">
						<span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" /><br /><img id="Codehighlighter1_218_241_Open_Image" onclick="this.style.display='none'; Codehighlighter1_218_241_Open_Text.style.display='none'; Codehighlighter1_218_241_Closed_Image.style.display='inline'; Codehighlighter1_218_241_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_218_241_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_218_241_Closed_Text.style.display='none'; Codehighlighter1_218_241_Open_Image.style.display='inline'; Codehighlighter1_218_241_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span>
						<span id="Codehighlighter1_218_241_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">/** */</span>
						<span id="Codehighlighter1_218_241_Open_Text">
								<span style="COLOR: #008000">/**</span>
								<span style="COLOR: #008000">
										<br />
										<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />     * </span>
								<span style="COLOR: #808080">@param</span>
								<span style="COLOR: #008000"> args<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />     </span>
								<span style="COLOR: #008000">*/</span>
						</span>
						<span style="COLOR: #000000">
								<br />
								<img id="Codehighlighter1_283_972_Open_Image" onclick="this.style.display='none'; Codehighlighter1_283_972_Open_Text.style.display='none'; Codehighlighter1_283_972_Closed_Image.style.display='inline'; Codehighlighter1_283_972_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" />
								<img id="Codehighlighter1_283_972_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_283_972_Closed_Text.style.display='none'; Codehighlighter1_283_972_Open_Image.style.display='inline'; Codehighlighter1_283_972_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span>
						<span style="COLOR: #0000ff">public</span>
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #0000ff">static</span>
						<span style="COLOR: #000000"> </span>
						<span style="COLOR: #0000ff">void</span>
						<span style="COLOR: #000000"> main(String[] args) </span>
						<span id="Codehighlighter1_283_972_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
								<img src="http://www.blogjava.net/images/dot.gif" />
						</span>
						<span id="Codehighlighter1_283_972_Open_Text">
								<span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        </span>
								<span style="COLOR: #008000">//</span>
								<span style="COLOR: #008000"> TODO 自动生成方法存根</span>
								<span style="COLOR: #008000">
										<br />
										<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />
								</span>
								<span style="COLOR: #000000">
										<br />
										<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        File aFile </span>
								<span style="COLOR: #000000">=</span>
								<span style="COLOR: #000000"> </span>
								<span style="COLOR: #0000ff">new</span>
								<span style="COLOR: #000000"> File(</span>
								<span style="COLOR: #000000">"</span>
								<span style="COLOR: #000000">d:/test.txt</span>
								<span style="COLOR: #000000">"</span>
								<span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        FileInputStream inFile </span>
								<span style="COLOR: #000000">=</span>
								<span style="COLOR: #000000"> </span>
								<span style="COLOR: #0000ff">null</span>
								<span style="COLOR: #000000">;<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        <br /><img id="Codehighlighter1_387_431_Open_Image" onclick="this.style.display='none'; Codehighlighter1_387_431_Open_Text.style.display='none'; Codehighlighter1_387_431_Closed_Image.style.display='inline'; Codehighlighter1_387_431_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_387_431_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_387_431_Closed_Text.style.display='none'; Codehighlighter1_387_431_Open_Image.style.display='inline'; Codehighlighter1_387_431_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />        </span>
								<span style="COLOR: #0000ff">try</span>
								<span style="COLOR: #000000"> </span>
								<span id="Codehighlighter1_387_431_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
										<img src="http://www.blogjava.net/images/dot.gif" />
								</span>
								<span id="Codehighlighter1_387_431_Open_Text">
										<span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />            inFile </span>
										<span style="COLOR: #000000">=</span>
										<span style="COLOR: #000000"> </span>
										<span style="COLOR: #0000ff">new</span>
										<span style="COLOR: #000000"> FileInputStream(aFile);<br /><img id="Codehighlighter1_464_521_Open_Image" onclick="this.style.display='none'; Codehighlighter1_464_521_Open_Text.style.display='none'; Codehighlighter1_464_521_Closed_Image.style.display='inline'; Codehighlighter1_464_521_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_464_521_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_464_521_Closed_Text.style.display='none'; Codehighlighter1_464_521_Open_Image.style.display='inline'; Codehighlighter1_464_521_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />        }</span>
								</span>
								<span style="COLOR: #000000"> </span>
								<span style="COLOR: #0000ff">catch</span>
								<span style="COLOR: #000000">(FileNotFoundException e) </span>
								<span id="Codehighlighter1_464_521_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
										<img src="http://www.blogjava.net/images/dot.gif" />
								</span>
								<span id="Codehighlighter1_464_521_Open_Text">
										<span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />            e.printStackTrace(System.err);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />            System.exit(</span>
										<span style="COLOR: #000000">1</span>
										<span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />        }</span>
								</span>
								<span style="COLOR: #000000">
										<br />
										<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        FileChannel inChannel </span>
								<span style="COLOR: #000000">=</span>
								<span style="COLOR: #000000"> inFile.getChannel();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        ByteBuffer buf </span>
								<span style="COLOR: #000000">=</span>
								<span style="COLOR: #000000"> ByteBuffer.allocate(</span>
								<span style="COLOR: #000000">48</span>
								<span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        </span>
								<span style="COLOR: #008000">//</span>
								<span style="COLOR: #008000">String buf = "";</span>
								<span style="COLOR: #008000">
										<br />
										<img id="Codehighlighter1_644_868_Open_Image" onclick="this.style.display='none'; Codehighlighter1_644_868_Open_Text.style.display='none'; Codehighlighter1_644_868_Closed_Image.style.display='inline'; Codehighlighter1_644_868_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" />
										<img id="Codehighlighter1_644_868_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_644_868_Closed_Text.style.display='none'; Codehighlighter1_644_868_Open_Image.style.display='inline'; Codehighlighter1_644_868_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />
								</span>
								<span style="COLOR: #000000">        </span>
								<span style="COLOR: #0000ff">try</span>
								<span style="COLOR: #000000"> </span>
								<span id="Codehighlighter1_644_868_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
										<img src="http://www.blogjava.net/images/dot.gif" />
								</span>
								<span id="Codehighlighter1_644_868_Open_Text">
										<span style="COLOR: #000000">{<br /><img id="Codehighlighter1_682_805_Open_Image" onclick="this.style.display='none'; Codehighlighter1_682_805_Open_Text.style.display='none'; Codehighlighter1_682_805_Closed_Image.style.display='inline'; Codehighlighter1_682_805_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_682_805_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_682_805_Closed_Text.style.display='none'; Codehighlighter1_682_805_Open_Image.style.display='inline'; Codehighlighter1_682_805_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />            </span>
										<span style="COLOR: #0000ff">while</span>
										<span style="COLOR: #000000">(inChannel.read(buf) </span>
										<span style="COLOR: #000000">!=</span>
										<span style="COLOR: #000000"> </span>
										<span style="COLOR: #000000">-</span>
										<span style="COLOR: #000000">1</span>
										<span style="COLOR: #000000">) </span>
										<span id="Codehighlighter1_682_805_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
												<img src="http://www.blogjava.net/images/dot.gif" />
										</span>
										<span id="Codehighlighter1_682_805_Open_Text">
												<span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />                System.out.println(</span>
												<span style="COLOR: #000000">"</span>
												<span style="COLOR: #000000">String read: </span>
												<span style="COLOR: #000000">"</span>
												<span style="COLOR: #000000">+</span>
												<span style="COLOR: #000000">
														<br />
														<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />                        ((ByteBuffer)(buf.flip())).asCharBuffer().toString());<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />                buf.clear();<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />            }</span>
										</span>
										<span style="COLOR: #000000">
												<br />
												<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />            System.out.println(</span>
										<span style="COLOR: #000000">"</span>
										<span style="COLOR: #000000">EOF readched.</span>
										<span style="COLOR: #000000">"</span>
										<span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />            inFile.close();<br /><img id="Codehighlighter1_891_948_Open_Image" onclick="this.style.display='none'; Codehighlighter1_891_948_Open_Text.style.display='none'; Codehighlighter1_891_948_Closed_Image.style.display='inline'; Codehighlighter1_891_948_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_891_948_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_891_948_Closed_Text.style.display='none'; Codehighlighter1_891_948_Open_Image.style.display='inline'; Codehighlighter1_891_948_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align="top" />        }</span>
								</span>
								<span style="COLOR: #000000"> </span>
								<span style="COLOR: #0000ff">catch</span>
								<span style="COLOR: #000000">(IOException e) </span>
								<span id="Codehighlighter1_891_948_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">
										<img src="http://www.blogjava.net/images/dot.gif" />
								</span>
								<span id="Codehighlighter1_891_948_Open_Text">
										<span style="COLOR: #000000">{<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />            e.printStackTrace(System.err);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />            System.exit(</span>
										<span style="COLOR: #000000">1</span>
										<span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />        }</span>
								</span>
								<span style="COLOR: #000000">
										<br />
										<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        <br /><img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />        System.exit(</span>
								<span style="COLOR: #000000">0</span>
								<span style="COLOR: #000000">);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span>
						</span>
						<span style="COLOR: #000000">
								<br />
								<img src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align="top" />
								<br />
								<img src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span>
				</span>
				<span style="COLOR: #000000">
						<br />
						<img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" />
				</span>
		</div>
<img src ="http://www.blogjava.net/chenlb/aggbug/80586.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/chenlb/" target="_blank">流浪汗</a> 2006-11-11 15:40 <a href="http://www.blogjava.net/chenlb/articles/80586.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>