2008年10月23日		  
	#
		
			
			
			
		
				
						c3p0很容易使用的开源专业级jdbc数据库缓冲池。
它是sourceforge上的一个开源项目,
项目在 
						
								
										http://sourceforge.net/projects/c3p0
								
						
						
						他的众多特性这里就不一一介绍了。
比较爽的一点就是
当Connection归还缓冲池时,c3p0会很小心的关闭
这条连接打开的Statement和ResultSet,免去了使用时
自己动手小心翼翼的关闭。
				
				
						c3p0使用非常简单,这里给一个例子
				
				
						package common.db;
				
				
						import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
				
				
						
						import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.mchange.v2.c3p0.DataSources;
				
				
						public final class ConnectionManager {
 private static ConnectionManager instance;
 
 public ComboPooledDataSource ds;
 private static String c3p0Properties="c3p0.properties";
  
 private ConnectionManager() throws Exception {
  Properties p = new Properties();
  p.load(this.getClass().getResourceAsStream(c3p0Properties));
  ds = new ComboPooledDataSource();
 }
 
 public static final ConnectionManager getInstance() {
  if (instance == null) {
   try {
    instance = new ConnectionManager();
   } catch (Exception e) {
    e.printStackTrace();
   }
  }
  return instance;
 }
 
 public synchronized final Connection getConnection() {
  try {
   return ds.getConnection();
  } catch (SQLException e) {
   e.printStackTrace();
  }
  return null;
 }
				
				
						 protected void finalize() throws Throwable {
  DataSources.destroy(ds); //关闭datasource
  super.finalize();
 }
 
}
				
				
						然后在ConnectionManager类的目录下再创建一个配置文件c3p0.properties
内容如下:
#db login parameters
driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql://localhost/test?useUnicode=no&characterEncoding=GBK
user=test
password=test
				
				
						#pool parameters
initialPoolSize=2
maxPoolSize=5
#maxIdleTime=10
#idleConnectionTestPeriod=5
autoCommitOnClose=true
				
				
						完整的配置文件参数参看c3p0的文档
				
				
						使用connection时很简单
Connection conn = ConnectionManager.getInstance().getConnection();
... 
最后 conn.close() 即可,
				
		 
			
			
		 
	
		
			
			
			如题。研究中...以前没有注意过。
			
			
		 
	
	
		
	2008年10月21日		  
	#
		
	
	
		
	2008年10月17日		  
	#
		
			
			
			*匹配除了换行之外的所有字符
合法IP的正则表达式 ((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)
\s匹配任意的空白符、(空格、制表符、换行符、中文全角空格)
\w匹配字母或数字或下划线或汉字
表1.常用的元字符| 代码 | 说明 | 
|---|
| . | 匹配除换行符以外的任意字符 | 
| \w | 匹配字母或数字或下划线或汉字 | 
| \s | 匹配任意的空白符 | 
| \d | 匹配数字 | 
| \b | 匹配单词的开始或结束 | 
| ^ | 匹配字符串的开始 | 
| $ | 匹配字符串的结束 | 
表2.常用的限定符| 代码/语法 | 说明 | 
|---|
| * | 重复零次或更多次 | 
| + | 重复一次或更多次 | 
| ? | 重复零次或一次 | 
| {n} | 重复n次 | 
| {n,} | 重复n次或更多次 | 
| {n,m} | 重复n到m次 | 
后向引用
使用小括号指定一个子表达式后,匹配这个子表达式的文本(也就是此分组捕获的内容)可以在表达式或其它程序中作进一步的处理。默认情况下,每个分组会自动拥有一个组号,规则是:从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2,以此类推。
后向引用用于重复搜索前面某个分组匹配的文本。例如,\1代表分组1匹配的文本。难以理解?请看示例:
\b(\w+)\b\s+\1\b可以用来匹配重复的单词,像go go, 或者kitty kitty。这个表达式首先是一个单词,也就是单词开始处和结束处之间的多于一个的字母或数字(\b(\w+)\b),这个单词会被捕获到编号为1的分组中,然后是1个或几个空白符(\s+),最后是分组1中捕获的内容(也就是前面匹配的那个单词)(\1)。
你也可以自己指定子表达式的组名。要指定一个子表达式的组名,请使用这样的语法:(?<Word>\w+)(或者把尖括号换成'也行:(?'Word'\w+)),这样就把\w+的组名指定为Word了。要反向引用这个分组捕获的内容,你可以使用\k<Word>,所以上一个例子也可以写成这样:\b(?<Word>\w+)\b\s+\k<Word>\b。
使用小括号的时候,还有很多特定用途的语法。下面列出了最常用的一些:
表4.常用分组语法| 分类 | 代码/语法 | 说明 | 
|---|
| 捕获 | (exp) | 匹配exp,并捕获文本到自动命名的组里 | 
|---|
| (?<name>exp) | 匹配exp,并捕获文本到名称为name的组里,也可以写成(?'name'exp) | 
| (?:exp) | 匹配exp,不捕获匹配的文本,也不给此分组分配组号 | 
| 零宽断言 | (?=exp) | 匹配exp前面的位置 | 
|---|
| (?<=exp) | 匹配exp后面的位置 | 
| (?!exp) | 匹配后面跟的不是exp的位置 | 
| (?<!exp) | 匹配前面不是exp的位置 | 
| 注释 | (?#comment) | 这种类型的分组不对正则表达式的处理产生任何影响,用于提供注释让人阅读 | 
|---|
表5.懒惰限定符| 代码/语法 | 说明 | 
|---|
| *? | 重复任意次,但尽可能少重复 | 
| +? | 重复1次或更多次,但尽可能少重复 | 
| ?? | 重复0次或1次,但尽可能少重复 | 
| {n,m}? | 重复n到m次,但尽可能少重复 | 
| {n,}? | 重复n次以上,但尽可能少重复 | 
表6.常用的处理选项| 名称 | 说明 | 
|---|
| IgnoreCase(忽略大小写) | 匹配时不区分大小写。 | 
| Multiline(多行模式) | 更改^和$的含义,使它们分别在任意一行的行首和行尾匹配,而不仅仅在整个字符串的开头和结尾匹配。(在此模式下,$的精确含意是:匹配\n之前的位置以及字符串结束前的位置.)  | 
| Singleline(单行模式) | 更改.的含义,使它与每一个字符匹配(包括换行符\n)。  | 
| IgnorePatternWhitespace(忽略空白) | 忽略表达式中的非转义空白并启用由#标记的注释。 | 
| RightToLeft(从右向左查找) | 匹配从右向左而不是从左向右进行。 | 
| ExplicitCapture(显式捕获) | 仅捕获已被显式命名的组。 | 
| ECMAScript(JavaScript兼容模式) | 使表达式的行为与它在JavaScript里的行为一致。 | 
表7.尚未详细讨论的语法| 代码/语法 | 说明 | 
|---|
| \a | 报警字符(打印它的效果是电脑嘀一声) | 
| \b | 通常是单词分界位置,但如果在字符类里使用代表退格 | 
| \t | 制表符,Tab | 
| \r | 回车 | 
| \v | 竖向制表符 | 
| \f | 换页符 | 
| \n | 换行符 | 
| \e | Escape | 
| \0nn | ASCII代码中八进制代码为nn的字符 | 
| \xnn | ASCII代码中十六进制代码为nn的字符 | 
| \unnnn | Unicode代码中十六进制代码为nnnn的字符 | 
| \cN | ASCII控制字符。比如\cC代表Ctrl+C | 
| \A | 字符串开头(类似^,但不受处理多行选项的影响) | 
| \Z | 字符串结尾或行尾(不受处理多行选项的影响) | 
| \z | 字符串结尾(类似$,但不受处理多行选项的影响) | 
| \G | 当前搜索的开头 | 
| \p{name} | Unicode中命名为name的字符类,例如\p{IsGreek} | 
| (?>exp) | 贪婪子表达式 | 
| (?<x>-<y>exp) | 平衡组 | 
| (?im-nsx:exp) | 在子表达式exp中改变处理选项 | 
| (?im-nsx) | 为表达式后面的部分改变处理选项 | 
| (?(exp)yes|no) | 把exp当作零宽正向先行断言,如果在这个位置能匹配,使用yes作为此组的表达式;否则使用no | 
| (?(exp)yes) | 同上,只是使用空表达式作为no | 
| (?(name)yes|no) | 如果命名为name的组捕获到了内容,使用yes作为表达式;否则使用no | 
| (?(name)yes) | 同上,只是使用空表达式作为no | 
			
			
		 
	
		
			
			
			Lucene是一个高性能的java全文检索工具包,它使用的是倒排文件索引结构。该结构及相应的生成算法如下:
0)设有两篇文章1和2
文章1的内容为:Tom lives in Guangzhou,I live in Guangzhou too.
文章2的内容为:He once lived in Shanghai.
1)由于lucene是基于关键词索引和查询的,首先我们要取得这两篇文章的关键词,通常我们需要如下处理措施
a.我们现在有的是文章内容,即一个字符串,我们先要找出字符串中的所有单词,即分词。英文单词由于用空格分隔,比较好处理。中文单词间是连在一起的需要特殊的分词处理。
b.文章中的”in”, “once” “too”等词没有什么实际意义,中文中的“的”“是”等字通常也无具体含义,这些不代表概念的词可以过滤掉
c.用户通常希望查“He”时能把含“he”,“HE”的文章也找出来,所以所有单词需要统一大小写。
d.用户通常希望查“live”时能把含“lives”,“lived”的文章也找出来,所以需要把“lives”,“lived”还原成“live”
e.文章中的标点符号通常不表示某种概念,也可以过滤掉
在lucene中以上措施由Analyzer类完成
经过上面处理后
    文章1的所有关键词为:[tom] [live] [guangzhou] [i] [live] [guangzhou]
    文章2的所有关键词为:[he] [live] [shanghai]
2) 有了关键词后,我们就可以建立倒排索引了。上面的对应关系是:“文章号”对“文章中所有关键词”。倒排索引把这个关系倒过来,变成:“关键词”对“拥有该关键词的所有文章号”。文章1,2经过倒排后变成
关键词   文章号
guangzhou  1
he         2
i           1
live       1,2
shanghai   2
tom         1
通常仅知道关键词在哪些文章中出现还不够,我们还需要知道关键词在文章中出现次数和出现的位置,通常有两种位置:a)字符位置,即记录该词是文章中第几个字符(优点是关键词亮显时定位快);b)关键词位置,即记录该词是文章中第几个关键词(优点是节约索引空间、词组(phase)查询快),lucene中记录的就是这种位置。
加上“出现频率”和“出现位置”信息后,我们的索引结构变为:
关键词   文章号[出现频率]   出现位置
guangzhou 1[2]               3,6
he       2[1]               1
i         1[1]               4
live      1[2],2[1]           2,5,2
shanghai  2[1]               3
tom      1[1]               1
以live 这行为例我们说明一下该结构:live在文章1中出现了2次,文章2中出现了一次,它的出现位置为“2,5,2”这表示什么呢?我们需要结合文章号和出现频率来分析,文章1中出现了2次,那么“2,5”就表示live在文章1中出现的两个位置,文章2中出现了一次,剩下的“2”就表示live是文章2中第 2个关键字。    
以上就是lucene索引结构中最核心的部分。我们注意到关键字是按字符顺序排列的(lucene没有使用B树结构),因此lucene可以用二元搜索算法快速定位关键词。    
实现时 lucene将上面三列分别作为词典文件(Term Dictionary)、频率文件(frequencies)、位置文件 (positions)保存。其中词典文件不仅保存有每个关键词,还保留了指向频率文件和位置文件的指针,通过指针可以找到该关键字的频率信息和位置信息。
    Lucene中使用了field的概念,用于表达信息所在位置(如标题中,文章中,url中),在建索引中,该field信息也记录在词典文件中,每个关键词都有一个field信息(因为每个关键字一定属于一个或多个field)。
     为了减小索引文件的大小,Lucene对索引还使用了压缩技术。首先,对词典文件中的关键词进行了压缩,关键词压缩为<前缀长度,后缀>,例如:当前词为“阿拉伯语”,上一个词为“阿拉伯”,那么“阿拉伯语”压缩为<3,语>。其次大量用到的是对数字的压缩,数字只保存与上一个值的差值(这样可以减小数字的长度,进而减少保存该数字需要的字节数)。例如当前文章号是16389(不压缩要用3个字节保存),上一文章号是16382,压缩后保存7(只用一个字节)。    
    下面我们可以通过对该索引的查询来解释一下为什么要建立索引。
假设要查询单词 “live”,lucene先对词典二元查找、找到该词,通过指向频率文件的指针读出所有文章号,然后返回结果。词典通常非常小,因而,整个过程的时间是毫秒级的。
而用普通的顺序匹配算法,不建索引,而是对所有文章的内容进行字符串匹配,这个过程将会相当缓慢,当文章数目很大时,时间往往是无法忍受的。 
			
			
		
 
	
	
		
	2008年10月13日		  
	#
		
			
			
			
		 
		
				
						
								
										
												一、  写jsp页面的时候,在struts2中,用的是s标记,先引入标记:  <%@ taglib prefix="s" uri="/struts-tags"%>  二、  struts2的标签和1是完全不同的。  struts2的标签分为两大类:非UI标志和UI标志 struts1 将标志库按功能分成HTML、Tiles、Logic和Bean等几部分  下面就介绍strut2的具体标签:  1、UI  UI标志又可以分为表单UI和非表单UI两部分。表单UI部分基本与Struts 1.x相同,都是对HTML表单元素的包装。不过,Struts 2.0加了几个我们经常在项目中用到的控件如:datepicker、doubleselect、timepicker、optiontransferselect等。因为这些标志很多都经常用到,而且参数也很多,要在一篇文章详细说明并非易事。  下面主要是ui标签的一些用法  form:  <s:form action="exampleSubmit" method="post" enctype="multipart/form-data">  <s:submit />      <s:reset /> 
												</s:form>可以上传文件的form。  textfield:  <s:textfield              label="姓名:"              name="name"              tooltip="Enter your Name here" />  datepicker:  <s:datepicker              tooltip="Select Your Birthday"              label="生日"              name="birthday" />  textarea:  <s:textarea              tooltip="Enter your remart"              label="备注"              name="remart"              cols="20"              rows="3"/>  select:  <s:select              tooltip="Choose user_type"              label=""              list="#{'free':'免费','vip':'收费'}" value="#{'free':'免费'}"               name="bean.user_type"              emptyOption="true"              headerKey="None"              headerValue="None"/>  <s:select              tooltip="Choose user_type"              label=""              list="#{'free':'免费','vip':'收费'}" value="#{'free':'免费'}"               name="bean.user_type"              emptyOption="true"              headerKey="None"              headerValue="None"/>  <s:select  list="venderList"  listKey="id"  listValue="name"  value="%{profile.companyName}"  name="companyName" cssClass="sel_style_w_180"/>    挺好用的  checkboxlist:  <s:checkboxlist              tooltip="Choose your Friends"              label="朋友"              list="{'Patrick', 'Jason', 'Jay', 'Toby', 'Rene'}"              name="friends"/>  checkbox:     <s:checkbox              tooltip="Confirmed that your are Over 18"              label="年龄"              name="legalAge"              value="18"/>  file:     <s:file              tooltip="Upload Your Picture"              label="Picture"              name="picture" />  a:  <s:a href="getP.jsp">超链接提交</s:a>  date :  <s:date name="ad_end_time" format="yyyy-MM-dd"/> 
												
														 2、非UI  if、elseif和else 描述:  执行基本的条件流转。  参数:  名称必需默认类型描述备注test是Boolean决定标志里内容是否显示的表达式else标志没有这个参数id否Object/String用来标识元素的id。在UI和表单中为HTML的id属性 例子:  <%@ page c %>  <%@ taglib prefix="s" uri="/struts-tags" %>  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  <html>      <head>          <title>Condition Flow</title>      </head>      <body>          <h3>Condition Flow</h3>                      <!--              这里有点小技巧:              本来可以用#parameters.name[0]来获得,请求中name的值。但是,在我实现include例子时,              无论我用param标志给name赋任何值,#parameters里面不会含有任何值,所以#parameters.name也为空值。                            其原因为:              当使用include标志时,被包含的页面(included)里#parameters拿到的是包含页面里的请求参数。                            因此,这里必须手工调用request.getParameter("name")。          -->      <s:iterator value="linkList" status="bean">    <tr>     <td class="data_tab_tdcl">      <s:property value="#bean.Index+1" />    </td>     <td class="data_tab_tdcl"><s:property value="link_title" /></td>     <td class="data_tab_tdcl"><s:property value="link_url" /></td>     <td class="data_tab_tdcl">     <s:if test="link_type == 1">                     文字                 </s:if>                  <s:elseif test="link_type == 2">                     图片                 </s:elseif>                   <s:else>                   -----                </s:else>         </td> 
												         </body>  </html>  例1 condition.jsp  iterator 描述:  用于遍历集合(java.util.Collection)或枚举值(java.util.Iterator)。  参数:  名称必需默认类型描述status否String如果设置此参数,一个IteratorStatus的实例将会压入每个遍历的堆栈value否Object/String要遍历的可枚举的(iteratable)数据源,或者将放入新列表(List)的对象id否Object/String用来标识元素的id。在UI和表单中为HTML的id属性 例子:  <%@ page c %>  <%@ page import="java.util.List" %>  <%@ page import="java.util.ArrayList" %>  <%@ taglib prefix="s" uri="/struts-tags" %> 
												<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  <%      List list = new ArrayList();      list.add("Max");      list.add("Scott");      list.add("Jeffry");      list.add("Joe");      list.add("Kelvin");      request.setAttribute("names", list);  %>  <html>      <head>          <title>Iterator</title>      </head>      <body>          <h3>Names: </h3>          <!--              1、此处的空property元素用于获得当前iterator的值              2、status被设成stuts,在iterator的里面就可以通过#stuts取得IteratorStatus的对象。IteratorStatus类包含当前序号信息,如是否第一个或最后一个,是否为奇数序号。这些信息在我们做格式化的时候,显得非常有用。          -->          <ol>              <s:iterator value="#request.names" status="stuts">                                  <s:if test="#stuts.odd == true">                      <li>White <s:property /></li>                  </s:if>                  <s:else>                      <li style="background-color:gray"><s:property /></li>                  </s:else>              </s:iterator>          </ol>      </body>  </html> 
										 
								 | 
						
				
		
			
			
		 
	
	
		
	2008年10月9日		  
	#
		
			
			
			     摘要: EJB
				
						方面
						
						
				
		
		
				
						 
						
								
										
												94
										
										
												、
										
										
												EJB2.0
					...  
阅读全文
			
			
		 
	
	
		
	2008年9月21日		  
	#
		
			
			
			在我装完Wincvs之后,提示我没有安装python,但后来我又装了python2.4,可Wincvs还是说配置不对.到底要怎么配置python呢?期待着您的回复,谢谢你了!    
| TCL or Python are not available, shell is disabled。 | 
有的网友说是版本的问题,我今天安装时也是一样,装了好三四个版本,都一样,最后在CSDN上找到了答案。
解决办法:
在admin-〉Preferences->wincvs中有关于python的设置,   
  其中python是指你的python虚拟机的位置,一般是python2X.dll的位置。在你来说就是python24.dll的位置,一般这个文件会在你的系统文件中找到。   
  Tcl则一般会在python文件架的dlls子文件架中找到,一般名称为tclxx.dll,在你大概就是tcl84.dll。如果是安装python2.3版本的话,会自动找到,不需要设置。
设置好了,WinCVS输出窗口:
| Python 2.5.2 (r252:60911, Feb 21 2008, 13:11:45) [MSC v.1310 32 bit (Intel)] on win32Tk is available, Tk-macros are enabledTCL is available, shell is enabled : help (select and press enter) | 
			
			
		 
	
	
		
	2008年9月16日		  
	#
		
			
			
			
		  AbstractFactory模式和可扩展性
  假如要实现较好的可扩展性,AbstractFactory模式确实是一件利器。如上面所说,假如要创建的Forum接口的不同实现,而又不想更改代码的话,就需要用到抽象工厂了。再Jive中,AuthorizationFactory类是一个抽象类,用来创建Authorization对象。这是一个抽象工厂,可以通过不同的子类来创建不同的Authorization对象。这个工厂的实现方法是:
  
  在AuthorizationFactory中使用一个private static变量factory,用来引用具体的抽象工厂的实例:
  private static AuthorizationFactory factory = null;
  
  用一个private static的String,来指明具体的抽象工厂的子类类名:
  private static String className ="com.coolservlets.forum.database.DbAuthorizationFactory";
  
  然后是用一个private static的loadAuthorizationFactory方法来给这个factory变量赋值,生成具体的抽象工厂类:
  
    private static void loadAuthorizationFactory() {
      if (factory == null) {
        synchronized(className) {
          if (factory == null) {
            String classNameProp = PropertyManager.getProperty(
              "AuthorizationFactory.className"
            );
            if (classNameProp != null) {
              className = classNameProp;
            }
            try {
              Class c = Class.forName(className);
              factory = (AuthorizationFactory)c.newInstance();
            }
            catch (Exception e) {
              System.err.println("Exception loading class: " + e);
              e.printStackTrace();
            }
          }
        }
      }
  }
  
  在static的getAuthorization方法返回一个Authorization的过程中,先初始化工厂类factory变量,然后用factory的createAuthorization方法来创建:
  
    public static Authorization getAuthorization(String username,
        String passWord) throws UnauthorizedException
    {
      loadAuthorizationFactory();
      return factory.createAuthorization(username, password);
  }
  
  不同的子类有不同的createAuthorization方法的实现。比如在DbAuthorizationFactory这个AuthorizationFactory的数据库实现子类中,createAuthorization方法是这样实现的:
  
    public Authorization createAuthorization(String username, String password)
        throws UnauthorizedException
    {
      if (username == null password == null) {
        throw new UnauthorizedException();
      }
      password = StringUtils.hash(password);
      int userID = 0;
      Connection con = null;
      PreparedStatement pstmt = null;
      try {
        con = DbConnectionManager.getConnection();
        pstmt = con.prepareStatement(AUTHORIZE);
        pstmt.setString(1, username);
        pstmt.setString(2, password);
  
        ResultSet rs = pstmt.executeQuery();
        if (!rs.next()) {
          throw new UnauthorizedException();
        }
        userID = rs.getInt(1);
      }
      catch( SQLException sqle ) {
        System.err.println("Exception in DbAuthorizationFactory:" + sqle);
        sqle.printStackTrace();
        throw new UnauthorizedException();
      }
      finally {
        try { pstmt.close(); }
        catch (Exception e) { e.printStackTrace(); }
        try { con.close();  }
        catch (Exception e) { e.printStackTrace(); }
      }
      return new DbAuthorization(userID);
    }
  
  在这个类中,可以看到抽象类和具体的子类之间的关系,它们是如何协作的,又是如何划分抽象方法和非抽象方法的,这都是值得注重的地方。一般的,抽象方法需要子类来实现,而抽象类中的非抽象方法应该所有子类所能够共享的,或者可是说,是定义在抽象方法之上的较高层的方法。这确实是一个抽象工厂的好例子!虽然实现的方法已经和GOF中给出的实现相差较远了,但思想没变,这儿的实现,也确实是要巧妙的些。
  
  还有就是静态方法的使用,使得这个类看起来有些Singleton的意味。这使得对于AbstractFactory的创建变得简单。
  
  在AuthorizationFactory中定义的其它方法,涉及到具体的如何创建Authorization,都是作为abstract方法出现,具体实现留给子类来完成。
  
  这样,在需要生成一个Authorization的时候,只需要调用AuthorizationFactory的静态方法getAuthorization就可以了,由子类实现了具体的细节。
  
  其它的,如同上面讲到的,在创建Forum的时候用的ForumFactory,具有同上面一样的实现,这就是模式之所以称为模式的所在了。 
资料引用:http://www.knowsky.com/365144.html
			
			
		 
	
	
		
	2008年8月27日		  
	#
		
			
			
			
		 
题目: IOC 后台机制学习
给定:
配置文件 config.txt, 文件内容
className = test.JavaBean1
field = username
value = ABC
该文件中的三个值会随时可能变化, 唯一不变的是 className 指定的都是一个 JavaBean(为了简化, 我们假定里面已经有一个 username 属性, 例如:
class JavaBeanxxxx {
    private String username;
    public String getUsername() {
        return username;
    }
    public void setUsername(String uname) {
        this.username = uname;
    }
}
要求: 写一段代码, 读取配置文件 config.txt, 然后实现把 className 指定的 JavaBean 类加载(注意这个类名是可以修改的, 可配置的), 然后生成一个实例,
并把配置文件中field字段指定的值作为这个实例的属性名(这里是username)所对应的值设置为 ABC(字符串), 并且要读出最后设置的值.
此题已经被 TigerTian 解答出来, 欢迎学习, 也感谢 TigerTian:
package com.gcoresoft.ioc;
import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import java.beans.*;
public class IOCStudy {
    
    //Load the properties file
    private Properties prop=new Properties();
    
    public void loadPropFile(String filename)
    {
        try
        {
            FileInputStream fin=new FileInputStream(filename);
            prop.load(fin);
            fin.close();
        }catch(Exception e){
            System.out.println(e.toString());
        }
    }
    
    private String getValueByName(String Name)
    {
        return prop.getProperty(Name);
    }
    
    public static void main(String[] args)
    {
        IOCStudy ioc=new IOCStudy();
        ioc.loadPropFile("E:\\Work\\GetInIOC\\src\\com\\gcoresoft\\ioc\\Config.txt");
        try
        {
            Class bean=Class.forName(ioc.getValueByName("className"));
            try {
                java.beans.BeanInfo info=java.beans.Introspector.getBeanInfo(bean);
                java.beans.PropertyDescriptor pd[]=info.getPropertyDescriptors();
                try {
                    Method mSet=null,mRead=null;
                    Object obj=bean.newInstance();
                    for(int i=0;i<pd.length;i++)
                        if(pd[i].getName().equalsIgnoreCase(ioc.getValueByName("field")))
                        {
                            mSet=pd[i].getWriteMethod();
                            mRead=pd[i].getReadMethod();                            
                        }
                    try {
                        mSet.invoke(obj, ioc.getValueByName("value"));
                        String str=(String)mRead.invoke(obj, null);
                        System.out.println(str);
                    } catch (IllegalArgumentException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                } catch (InstantiationException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                
            } catch (IntrospectionException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            
        }catch(ClassNotFoundException e){
            System.out.println(e.toString());
        }
        
    }
    
}