通常我們會將 business service facade 設計成 stateless 且 thread-safe,以便可以重覆使用。另外,這個 facade 應該避免在 cluster 做 replication ,如此可減輕 state replication 的負擔,大大增加 scalibility。一般 stateless + thread-safe 的手段是:
public class AuthenciationServiceImpl implement AuthenciationService { //no instance variable or use thread safe component private UserDAO userDAO; // a thread-safe component public IUser authenticate(String name, String password) { return userDAO.find(name, password); } }
注意 AuthenciationServiceImpl 並不需要 implement Serializable (因為不用 replicate)
大致上是這樣子。不過今天在寫一些 prototype 時,發生了一個以前不大注意的東西:
public class AuthenticationServiceImpl implement AuthenticationService { private UserDAO userDAO; // a quick/test implementation public IUser authenticate(String name, String password) { return new IUser() { public String getUsername() { return "testUser" ; } public String getPassword() { return "testPassword" ; } }; } }
因為是 prototype,所以隨便寫個臨時的 anonymous inner IUser,然後傳出去給 view layer。哈,沒想到這一傳出去,引發所有的 statless service 通通一鼓腦全部都進入 httpSession 了。原因是這個 inner class 是 AuthenticationServiceImpl$1,而且還被 view layer 放入了 httpSession 裡,乖乖,這一下從 AuthenticationServiceImpl 開始,牽連到 UserDAO,再牽連到 hibernateTemplate,再牽連到 BeanFactory... Spring 的東西全部倒進 httpSession 裡了。沒想到一個小小的 inner class 卻釀成巨災,以後得特別小心啊。無怪乎Effective Java 裡大聲疾呼少用 non-static 的 inner class,能夠用 static 的就盡可能使用。以前對這點只模模糊糊的記著,現下可真是學了個乖,永遠不會忘了!