本文是"
使XML作为持久存储介质的解决方案 "的续文.
上文中对成员的CRUD都采用同步进行资源保护,这种方案实际上是保护过度,带来的消极影响是降低了程序的效率,在下面的例子中,我们应该使用读写锁对资源进行保护.关于读写锁的分析请见"
读写锁的OO分析(http://www.blogjava.net/sitinspring/archive/2007/10/21/154652.html)".
下面是代码:
MemberService类:
package com.sitinspring.model.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;

import org.apache.log4j.Logger;

import com.sitinspring.exception.PersistFileReadException;
import com.sitinspring.exception.PersistFileWriteException;
import com.sitinspring.model.domain.Member;
import com.sitinspring.model.domain.MemberFilter;
import com.sitinspring.model.persistence.Db4OPersistence;
import com.sitinspring.model.persistence.HibernatePersistence;
import com.sitinspring.model.persistence.Persistence;
import com.sitinspring.model.persistence.SqlPersistence;
import com.sitinspring.model.persistence.XmlPersistence;
import com.sitinspring.util.ReadWriteLock;


public class MemberService
{
private static Logger logger = Logger.getLogger(MemberService.class);
private Persistence persistence;
private Persistence xmlPersistence;
private Persistence sqlPersistence;
private Persistence db4OPersistence;
private Persistence hibernatePersistence;

private Hashtable<String, Member> members;

private ReadWriteLock lock;


public MemberService()
{
members = new Hashtable<String, Member>();
lock = new ReadWriteLock();
}

public void setPersistenceType(String type)
{
logger.info("指定持久层为"+type);

if(type.equals("Xml"))
{

if(xmlPersistence==null)
{

try
{
xmlPersistence=new XmlPersistence();
}

catch(Exception ex)
{
logger.error("不能初始化XmlPersistence,原因:"+ex.getMessage());
}
}
persistence=xmlPersistence;
}

else if(type.equals("Sql"))
{

if(sqlPersistence==null)
{

try
{
sqlPersistence=new SqlPersistence();
}

catch(Exception ex)
{
logger.error("不能初始化XmlPersistence,原因:"+ex.getMessage());
}
}
persistence=sqlPersistence;
}

else if(type.equals("Hibernate"))
{

if(hibernatePersistence==null)
{

try
{
hibernatePersistence=new HibernatePersistence();
}

catch(Exception ex)
{
logger.error("不能初始化XmlPersistence,原因:"+ex.getMessage());
}
}
persistence=hibernatePersistence;
}

else
{

if(db4OPersistence==null)
{

try
{
db4OPersistence=new Db4OPersistence();
}

catch(Exception ex)
{
logger.error("不能初始化XmlPersistence,原因:"+ex.getMessage());
}
}
persistence=db4OPersistence;
}

try
{
members.clear();
members=persistence.loadMemberFromPersistence();
}

catch(PersistFileReadException ex)
{
logger.error("从"+persistence+"中读取失败");
}
}


public boolean hasMember(String name)
{
return members.containsKey(name);
}


public boolean hasMember(Member member)
{
return hasMember(member.getName());
}


public boolean add(Member member) throws PersistFileWriteException
{

if (hasMember(member))
{
System.out.println("Member:" + member.getName()
+ " has been exist!");
return false;

} else
{

try
{
lock.writeLock();
persistence.add(member);
members.put(member.getName(), member);
return true;

} finally
{
lock.writeUnlock();
}
}
}


public boolean update(Member member) throws PersistFileWriteException
{

if (hasMember(member))
{

try
{
lock.writeLock();

persistence.update(member);

Member oldMember = members.get(member.getName());
oldMember.setTitle(member.getTitle());
oldMember.setAge(member.getAge());

return true;

} finally
{
lock.writeUnlock();
}


} else
{
System.out.println("Member:" + member.getName()
+ " can't been found!");
return false;
}
}


public boolean saveOrUpdate(Member member) throws PersistFileWriteException
{

if (hasMember(member))
{
return update(member);

} else
{
return add(member);
}
}


public boolean delete(Member member) throws PersistFileWriteException
{
return delete(member.getName());
}

public boolean delete(String memberName) throws PersistFileWriteException
{

if (hasMember(memberName))
{

try
{
lock.writeLock();
persistence.delete(memberName);
members.remove(memberName);
return true;

} finally
{
lock.writeUnlock();
}

} else
{
System.out.println("Member:" + memberName
+ " can't been found!");
return false;
}
}

@SuppressWarnings("unchecked")

public List<Member> search(MemberFilter memberFilter)
{
List<Member> retval = new ArrayList<Member>();


try
{
lock.readLock();


for (Iterator it = members.keySet().iterator(); it.hasNext();)
{
String key = (String) it.next();
Member member = members.get(key);


if (memberFilter.match(member))
{
retval.add(member);
}
}

} finally
{
lock.readUnlock();
}

Collections.sort(retval);

return retval;
}


public List<Member> getAll()
{

MemberFilter filter = new MemberFilter()
{

public boolean match(Member member)
{
return true;
}
};

return search(filter);
}


public Member getMemberByName(String name)
{

try
{
lock.readLock();

for (Iterator it = members.keySet().iterator(); it.hasNext();)
{
String key = (String) it.next();
Member member = members.get(key);


if (member.getName().equals(name))
{
return member;
}
}

} finally
{
lock.readUnlock();
}

return null;
}

}
XmlPersistence类代码:
package com.sitinspring.model.persistence;

import java.io.File;
import java.io.FileWriter;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

import com.sitinspring.exception.PersistFileReadException;
import com.sitinspring.exception.PersistFileWriteException;
import com.sitinspring.model.domain.Member;
import com.sitinspring.util.FileDirUtil;


public class XmlPersistence extends Persistence
{
private Document document;

public XmlPersistence() throws PersistFileReadException,

PersistFileWriteException
{
filePos = "member.xml";


if (FileDirUtil.isFileExist(filePos) == false)
{
// Create document when file not exist
createDocument();
return;

} else
{
// Get Docunent when file exist
SAXReader reader = new SAXReader();


try
{
document = reader.read(new File(filePos));

} catch (Exception ex)
{
throw new PersistFileReadException(ex.getMessage());
}
}
}

public String toString()
{
return "XML存储介质,文件为:"+filePos;
}


private void createDocument() throws PersistFileWriteException
{
String text = "<members></members>";


try
{
document = DocumentHelper.parseText(text);
writeDocumentToFile();

} catch (PersistFileWriteException ex)
{
throw ex;

} catch (Exception ex)
{
ex.printStackTrace();
}
}


private void writeDocumentToFile() throws PersistFileWriteException
{

try
{
XMLWriter writer = new XMLWriter(new FileWriter(filePos));
writer.write(document);
writer.close();

} catch (Exception ex)
{
throw new PersistFileWriteException(ex.getMessage());
}
}

public Hashtable<String, Member> loadMemberFromPersistence()

throws PersistFileReadException
{

try
{
Hashtable<String, Member> retval = new Hashtable<String, Member>();

List nodes = document.getRootElement().elements("member");


for (Iterator it = nodes.iterator(); it.hasNext();)
{
Element elm = (Element) it.next();
Member member = new Member(elm.attributeValue("name"), elm
.elementText("age"), elm.elementText("title"));
retval.put(member.getName(), member);
}

return retval;

} catch (Exception ex)
{
throw new PersistFileReadException(ex.getMessage());
}
}


public boolean add(Member member) throws PersistFileWriteException
{

try
{
Element rootElm = document.getRootElement();
Element newMemberElm = rootElm.addElement("member");

newMemberElm.addAttribute("name", member.getName());

Element ageElm = newMemberElm.addElement("age");
ageElm.setText(member.getAge());
Element titleElm = newMemberElm.addElement("title");
titleElm.setText(member.getTitle());

writeDocumentToFile();

return true;

} catch (PersistFileWriteException ex)
{
throw ex;
}
}


public boolean update(Member member) throws PersistFileWriteException
{

try
{
Element rootElm = document.getRootElement();
List nodes = rootElm.elements("member");


for (Iterator it = nodes.iterator(); it.hasNext();)
{
Element elm = (Element) it.next();


if (elm.attributeValue("name").equals(member.getName()))
{
elm.element("age").setText(member.getAge());
elm.element("title").setText(member.getTitle());
break;
}
}

writeDocumentToFile();

return false;

} catch (PersistFileWriteException ex)
{
throw ex;
}
}


public boolean delete(String name) throws PersistFileWriteException
{

try
{
Element rootElm = document.getRootElement();
List nodes = rootElm.elements("member");


for (Iterator it = nodes.iterator(); it.hasNext();)
{
Element elm = (Element) it.next();
Member member = new Member(elm.attributeValue("name"), elm
.elementText("age"), elm.elementText("title"));


if (member.getName().equals(name))
{
rootElm.remove(elm);
break;
}
}

writeDocumentToFile();

return false;

} catch (PersistFileWriteException ex)
{
throw ex;
}
}


public boolean delete(Member member) throws PersistFileWriteException
{
return delete(member.getName());
}
}