| |
Spring Framework從誕生之日起,受到了越來越多的關注。最近,新的開源項目大多支持Spring Framework。國內目前也有專門的網站(http://spring.jactiongroup.net/)。那它為什么如此受歡迎呢? 我想最重要的是,EJB讓每個人都痛恨。要編寫一個EJB,需要寫LocalHome, RemoteHome, Bean, LocalInterface, RemoteInterface,需要一個標準描述符,一個特殊廠商描述符(Weblogic、WebSphere都不一樣),如果是Entity Bean,還需要Mapping文件。如此之多,實在麻煩。但EJB最重要的是解決Transaction問題,沒有Spring之前,沒有其他方法能夠描述式的解決它。每個人、每個公司為了解決Transaction的問題,編程的寫法都不一樣,百花齊放。于是,在最需要它的時候,Spring出現了。 Spring的功能非常多。但對于一個產品,最重要的是如何用好它的精華。Spring包含AOP、ORM、DAO、Context、Web、MVC幾個部分組成。Web、MVC暫不用考慮,用成熟的Struts、JSP或Webwork更好。DAO由于目前Hibernate、JDO的流行,也可不考慮。因此最需要用的是AOP、ORM、Context。 Context中,最重要的是Beanfactory,它是將接口與實現分開,非常重要。以前我們寫程序,如一個接口IDocument,一個實現類Document1。在寫程序時,需寫成IDocument doc = new Document1(),一旦我們的實現類需改變時,變為Document2,則程序需寫成IDocument doc = new Document2(),所有用到的地方全需改。Beanfactory幫我們解決了這個問題,用context后,寫法變為IDocument doc=(IDocument)beanFactory.getBean("doc")。如果實現類從Document1改為Document2,直接在配置文件改就可以了。Context是Bean factory的進一步抽象。很多人都喜歡用ApplicationConext,用Servlet把它Load。這樣就把Bean Factory與Web綁定在一起。如果是Fat Client或Remote調用,則這些Bean factory就很難調用,實際是將表現層與業務層綁定的太緊。推薦的方法是SingletonBeanFactoryLocator。具體為: BeanFactoryLocator bfLocator = SingletonBeanFactoryLocator.getInstance();
<beans> <bean id="beanFactory" class="org.springframework.context.support.ClassPathXmlApplicationContext"> </beans>
Spring Framework最得以出名的是與Hibernate的無縫鏈接,基本上用Spring,就會用Hibernate。可惜的是Spring提供的HibernateTemplate功能顯得不夠,使用起來也不是很方便。我們編程序時,一般先寫BusinessService,由BusinessService調DAO來執行存儲,在這方面Spring沒有很好的例子,造成真正想用好它,并不容易。 我們的思路是先寫一個BaseDao,仿照HibernateTemplate,將基本功能全部實現: public class BaseDao extends HibernateDaoSupport{ private Log log = LogFactory.getLog(getClass()); public Session openSession() { public Object get(Class entityClass, Serializable id) throws DataAccessException { public Serializable create(Object entity) throws DataAccessException { ... 其它的DAO,從BaseDao繼承出來,這樣寫其他的DAO,代碼就會很少。 從BaseDao繼承出來EntityDao,專門負責一般實體的基本操作,會更方便。 public interface EntityDao { public Object get(Class entityClass, Serializable id) throws DataAccessException; public Object load(Class entityClass, Serializable id) throws DataAccessException; public Serializable create(Object entity) throws DataAccessException; /** } 為了Transaction的控制,采用AOP的方式: public interface EntityManager { public Object get(Class entityClass, Serializable id); public Object load(Class entityClass, Serializable id); public Serializable create(Object entity); } /** private EntityDao entityDao; public void setEntityDao(EntityDao entityDao) { public Object get(Class entityClass, Serializable id) { public Object load(Class entityClass, Serializable id) { } 這樣我們就有了一個通用的Hibernate實體引擎,可以對任何Hibernate實體實現基本的增加、修改、刪除、查詢等。 其它的BusinessService就可以繼承EntityManager,快速實現業務邏輯。 具體XML配置如下: <!-- Oracle JNDI DataSource for J2EE environments --> <!-- Hibernate SessionFactory for Oracle --> <!-- AOP DAO Intecepter --> <bean id="entityDaoTarget" class="com.gpower.services.entity.dao.EntityDaoImpl"> <bean id="entityDao" class="org.springframework.aop.framework.ProxyFactoryBean"> <!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) --> <!-- Transaction manager that delegates to JTA (for a transactional JNDI DataSource) --> <!-- Transactional proxy for the Application primary business object --> <bean id="entityManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
|