04 September 2005

通常我們會將 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 的就盡可能使用。以前對這點只模模糊糊的記著,現下可真是學了個乖,永遠不會忘了!