Colin Wong's Bookmarks tagged spring → View Popular
You are here: Diigo Home > Colin Wong's Bookmarks
使用struts+spring+hibernate组装你的web应用架构 - otto - 博客园
-
摆在开发者面前有很多问题:要考虑是怎样建立用户接口?在哪里处理业务逻辑? 怎样持久化的数据。 而这三层构架中,每一层都有他们要仔细考虑的。 各个层该使用什么技术? 怎样的设计能松散耦合还能灵活改变? 怎样替换某个层而不影响整体构架?应用程序如何做各种级别的业务处理(比如事务处理)?
-
一个好框架具备以下几点: 减轻开发者处理复杂的问题的负担("不重复发明轮子"); 内部有良好的扩展; 并且有一个支持它的强大的用户团体。 好的构架一般有针对性的处理某一类问题,并且能将它做好(Do One Thing well)
-
如何建立你的架构,并且怎样让你的各个应用层保持一致。?如何整合框架以便让每个层在以一种松散偶合的方式彼此作用而不用管低层的技术细节
-
Spring还提供了Setter Injection(type2),Constructor Injection(type3)等方式供我们选择。 Spring把程序中所涉及到包含业务逻辑和Dao的Objects——例如transaction management handler(事物管理控制)、Object Factoris(对象工厂)、service objects(服务组件)——都通过XML来配置联系起来。
-
业务层所负责的如下:
* 处理应用程序的 业务逻辑和业务校验
* 管理事物
* 允许与其它层相互作用的接口
* 管理业务层级别的对象的依赖。
* 在显示层和持久层之间增加了一个灵活的机制,使得他们不直接的联系在一起。
* 通过揭示 从显示层到业务层之间的Context来得到business services。
* 管理程序的执行(从业务层到持久层)。 -
既然我们致力于的是一个不是很复杂的Web的应用, 我们需要一个对象集合,让它在不同层之间移动的。 域模块层由实际需求中的业务对象组成 比如, OrderLineItem , Product等等。 开发者在这层 不用管那些DTOs,仅关注domain object即可
-
我们就先来创建domain objects。首先,我们要在这些Object中要确定那些是需要持久化的,哪些是提供给business logic,那些是显示接口的设计。 下一步,我们将配置我们的持久层并且定义好Hibernate的OR mappings。然后定义好Business Objects。有了这些组成部分之后,我们将 使用Spring把这些连接起来。 最后,我们提供给Spring一个持久层,从这个持久层里我们可以知道它是如何与业务逻辑层(business service layer)通信的,以及它是怎样处理其他层抛出的异常的。。
-
好好考虑怎你的package命名,这反应出了你是怎样分层的。 例如 domain objects在程序中可能打包在com.meagle.bo内。 更详细一点将打包在com. meagle.bo的子目录下面。business logic应该从com.meagle.serice开始打包,而DAO 对象应该位于com.meagle.service.dao.hibernate。反应Forms和Actions的 持久对象(presentation classes) 应该分别放在 com.meagle.action和com.meagle.forms包。 准确的给包命名使得你的classes很好分割并且易于维护,并且在你添加新的classes时,能使得程序结构上保持上下一致
-
建立Hibernate的持久层 需要好几个步骤。 第一步让我们把BO持久化。 既然Hibernate是通过POJO工作的, 因此Order和 OrderLineItem对象需要给所有的fileds 加上getter,setter方法。 Hibernate通过XML文件来映射(OR)对象,以下两个xml文件分别映射了Order 和OrderItem对象。(这里有个叫XDoclet工具可以自动生成你的XML影射文件)
-
你可以在WebContent/WEB-INF/classes/com/meagle/bo目录下找到这些xml文件。Hibernate的 [urlhttp://www.hibernate.org/hib_docs/api/net/sf/hibernate/SessionFactory.html]SessionFactory [/url]是用来告诉程序 应该与哪个数据库通信,该使用哪个连接池或使用了DataSource, 应该加载哪些持久对象。而Session接口是用来完成Selecting,Saving,Delete和Updating这些操作。 后面的我们将讲述SessionFactory和Session是怎样设置的 -
既然我们已经有了domain objects,接下来我们就要business service objects了,用他们来执行程序的logic,调用持久层,得到UI层的requests,处理transactions,并且控制exceptions。 为了将这些连接起来并且易于管理,我们将使用面向方面的 SpringFramework。 Spring 提供了 控制倒置(inversion of control 0==IoC)和注射依赖设置(setter dependency injection)这些方式(可供选择),用XML文件将对象连接起来。 IoC是一个简单概念(它允许一个对象在上层接受其他对象的创建),用IoC这种方式让你的对象从创建中释放了出来,降低了偶合度。
-
Business Object中的Setter方法接受的是接口,这样我们可以很松散的定义对象实现,然后注入。 在我们的案例中,我们将用一个business service object接收一个DAO,用它来控制domain objects的持久化。 由于在这个例子中使用了Hibernate,我们可以很方便的用其他持久框架实现 同时通知Spring 有新的DAO可以使用了。
-
注意到这段代码里有一个 setOrderDao(),它就是一个DAO Object设置方法(注射器)。 但这里并没有一个getOrderDao的方法,这不必要,因为你并不会在外部访问这个orderDao。这个DAO Objecte将被调用,和我们的persistence layer 通信。我们将用Spring把DAO Object 和 business service object搭配起来的。因为我们是面向接口编程的,所以并不需要将实现类紧密的耦合在一起。
-
接下去我们开始我们的DAO的实现类进行编码。 既然Spring已经有对Hibernate的支持,那这个例子就直接继承HibernateDaoSupport类了,这个类很有用,我们可以参考HibernateTemplate(它主要是针对HibernateDaoSupport的一个用法,译注:具体可以查看Srping 的API)。 -
我们仍然要给我们持久层组装很多关联的对象,这里包含了HibernateSessionFactory 和TransactionManager。 Spring 提供了一个 HibernateTransactionManager,他用线程捆绑了一个Hibernate Session,用它来支持transactions(请查看ThreadLocal) 。
-
每个对象都可以在Spring 配置信息中用<bean>标签引用。在这里,mySessionFactory引用了HibernateSessionFactory,而myTransactionManager引用了HibernateTransactionManage。 注意代码中myTransactionManger Bean有个sessionFactory属性。 HibernateTransactionManager有个sessionFactory setter 和 getter方法,这是用来在Spring启动的时候实现"依赖注入" (dependency injection)的。 在sessionFactory 属性里 引用mySessionFactory。这两个对象在Spring容器初始化后就被组装了起来了。 这样的搭配让你从 单例(singleton objects)和工厂(factories)中解放了出来,降低了代码的维护代价。 mySessionFactory.的两个属性,分别是用来注入mappingResources 和 hibernatePropertes的。通常,如果你在Spring之外使用Hibernate,这样的设置应该放在hibernate.cfg.xml中的。 不管怎样,Spring提供了一个便捷的方式-----在Spring内部配置中并入了Hibernate的配置
-
既然我们已经组装配置好了Service Beans,就需要把Business Service Object和 DAO也组装起来,并把这些对象配到一个事务管理器(transaction manager)里。
-
图4 是我们对象搭建的一个提纲。 从中可以看出,每个对象都联系着Spring,并且能通过Spring注入到其他对象。把它与Spring的配置文件比较,观察他们之间的关系
图 4. Spring就是这样基于配置文件,将各个Bean搭建在一起。 -
这个例子使用一个TransactionProxyFactoryBean,它定义了一个setTransactionManager()。 这对象很有用,他能很方便的处理你申明的事物还有Service Object。 你可以通过transactionAttributes属性来定义怎样处理。 想知道更多还是参考TransactionAttributeEditor吧。
TransactionProxyFactoryBean 还有个setter. 这会被我们 Business service object(orderTarget)引用, orderTarget定义了 业务服务层,并且它还有个属性,由setOrderDAO()引用。这个属性 -
Spring 和Bean 的还有一点要注意的: bean可以以用两种方式创造。 这些都在单例模式(Sington)和原型模式(propotype)中定义了。 默认的方式是singleton,这意味着共享的实例将被束缚。 而原形模式是在Spring用到bean的时候允许新建实例的。当每个用户需要得到他们自己Bean的Copy时,你应该仅使用prototype模式。(更多的请参考设计模式中的单例模式和原形模式)
-
既然我们已经将我们的Serices和DAO搭配起来了。我们需要把我们的Service显示到其他层。 这个通常是在Struts或者Swing这层里编码。一个简单方法就是用 服务定位器返回给Spring context 。当然,可以通过直接调用Spring中的Bean来做。
-
这篇文章在技术和构架方面掩盖了很多低层的基础信息, 文章的主要的意图在于让你意识到如何给你应用程序分层。 分层可以"解耦"你的代码——允许新的组件被添加进来,而且让你的代码易于维护。 这里用到的技术只是专注于把"解偶"做好。 不管怎样,使用这样的构架可以让你用其他技术代替现在的层。 例如,你可能不使用Hibernate实现持久化。既然你在DAO中面向接口的编程的,所以你完全可以用iBATIS来代替。或者,你也可能想用Struts外的其他的技术或者框架替换现在的UI层(转换久层,实现层并不应该直接影响到你的业务逻辑和业务服务层)。 用适当的框架搭建你的Web应用,其实也不是一件烦琐的工作,更主要的是它"解耦"了你程序中的各个层。
用spring 实现观察者设计模式 — IT技术 - 赛迪网
-
观察者设计模式其实就是一种发布预订的设计模式,大家都知道JMS里面有发布预订的模式,也就是有一个一对多的关系,一个发布者,然后有N多个消费者,一旦发布者发出消息,那么所有预订的消费者都将收到消息。
直接召唤系与IoC fashion使用Spring — IT技术 - 赛迪网
Tags: desing_pattern, spring, spring_mvc on 2007-08-15 -All Annotations (0) -About
more fromjava.ccidnet.com
-
.直接召唤系--Singleton的Application Context
最简单的,就像在UnitTest里那样,直接构造Application Context:ApplicationContext ctx = new ClasspathXmlApplicationContext("ApplicationContext.xml");
在Web环境里,会使用ContextLoader构造ApplicationContext后,压进Servlet Context。
由ContextLoaderListener或ContextLoaderServlet,在Web应用启动时完成。
然后在Jsp/Servelet中,可以通过Servlet Context取得ApplicationContext: ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(application); -
但像Singleton类或者EJB中,就没有Servlet Context可用了。
如果全部像UnitTest那样直接构造,速度就会很不堪。自然的,就想到把ApplicationContext做成单例。
Spring提供了ContextSingletonBeanFactoryLocator这样的物体。
先搞一个beanRefFactory.xml,里面写上所有的applcationContext-*.xml文件名,并把Context命名为"default-context":
applicationContext.xml -
然后让loactor去找它,但代码有点长: BeanFactoryReference bfr = DefaultLocatorFactory.getInstance().useBeanFactory("default-context");
BeanFactory factory = bfr.getFactory();
MyService myService = factory.getBean("myService");
bfr.release();
// now use myService上面的代码实在是太灵活,太麻烦了。
还不如自己实现一个简单的Singleton,扩展ContextLoaderListener类,在Web系统启动时压入Singleton。新的ContextLoaderListener类重载如下,ContextUtil中包含一个静态的ApplicationContext变量:
public void contextInitialized(ServletContextEvent event)
{
super.contextInitialized(event);ServletContext context = event.getServletContext();
ApplicationContext ctx = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
ContextUtil.setContext(ctx);
}
用家可直接取用:
ApplicationContext context = ContextUtil.getContext();
Spring: Creating Objects So You Don't Have To
-

<!-- ---- OAS AD '120x60-1' end ---- -->
<!-- OAS ad tag end -->
This code creates a Person object and calls the setEmail() method, passing in the string defined as a value.
It is good practice to default your classes to being immutable until you have a reason to make them mutable. Constructor-based injection will allow you to take advantage of dependency-injection while still permitting immutability. If your classes are meant to be immutable, then it is probably best to stick with constructor-based injection. -
This feature is meant to save you from having to explicitly type out the names of the beans that you reference. I personally favor explicitness in order to make the bean definitions more readable, thus I choose not to use Spring's autowiring functionality, but you may find it useful.
-
The Spring documentation recommends always using ApplicationContext unless you have memory usage restrictions,
-
One major advantage to ApplicationContext is that it can be loaded declaratively within the context of an application server
-
ApplicationContext is actually an interface in Spring. WebApplicationContext is a class that implements ApplicationContext and can be used in your Web applications. Here is how you access the ApplicationContext from within your Web application.
Spring: Creating Objects So You Don't Have To
-
Spring provides a core factory pattern, which eliminates the need to manually program factory objects (usually realized as singletons). It also, as the documentation explains, "allows you to decouple the configuration and specification of dependencies from your actual program logic."
-
The fundamental benefit of the Spring framework is its ability to act as a factory to create objects. Spring reads a schematic defined in an external configuration file, creates and wires the objects together using reflection, and then passes the objects back to you. Think of Spring as a factory that you don't have to write any code for.
Spring: Creating Objects So You Don't Have To
-
Spring's object linking is defined in XML files, thus you can plug-in different components during runtime, or for different application configurations. This is particularly useful for applications that do unit testing or applications that deploy different configurations for different customers.
-
The terms 'dependency injection' and 'inversion of control' are often used interchangeably. Martin Fowler recently elaborated on the terminology, stating that dependency injection is a specific type of inversion of control. Specifically, dependency injection is a pattern where the responsibility for object creation and object linking is removed from the objects themselves and moved into a factory. Thus, dependency injection inverts the control for object creation and linking.
-
Spring provides an MVC framework, support for several presentation frameworks, a transaction management framework, DAO support, support for several O/R mapping tools, and more.
Spring和Hibernate學習筆記02 - 白色黑暗 - 澳門 BBS 澳門論壇 - powered by X-Space
-
使用business delegate pattern的主要原因:
- Most presentation tier components execute a unit of business logic. It's best to put this logic in a non-web class so a web-service or rich platform client can use the same API as a servlet.
- Most business logic can take place in one method, possibly using more than one DAO. Using a business delegate allows you to use Spring's declarative transactions feature at a higher "business logic" level.
英文程度不高,所以不亂翻譯了。
自己認為,使用Manager(business delegate)的好處就是可以將業務邏輯完全的抽象出來,至於功能的實現Manager完全不用理會,Manager只是調用一個或多個DAO提供的功能來完成業務。
DAO針對數據處理,Manager針對業務邏輯。
robbin的口水 -JavaEye技术社区 - Mozilla Firefox
-
2.0的一个非常大的改进是引入了XML Schema的namespace,因而可以将bean的配置文件做大幅度的简化
-
在Spring2.0里面XML Schema语法的配置可以在相当程度上降低配置文件的复杂程度和烦琐程度,可以视为Spring的重大改进之一。但是我们也必须看到XML Schema并没有从根源上面解决XML配置复杂的问题,而只是减轻。
-
我个人比较期待未来的Spring能够使用脚本语言来编写和组装bean之间的关系,这样组装脚本本身也是可测试的,而且脚本的描述能力要远远好于XML配置文件,同时编写和维护起来也比XML轻松。
-
对于业务层来说,不应该涉及request和session的scope,否则业务层代码无法脱离Servlet容器进行单元测试
-
也许request/session scope的bean也是为了提供给Spring MVC的Controller使用的。
-
三、集成AspectJ,可以管理容器外对象,提供了领域模型的依赖注入
通常由Hibernate管理的持久化对象PO,并不是由Spring容器初始化的,往往是用户自己new出来,或者通过find,load方法创建的,其结果就是Spring容器无法对这种容器外创建的对象进行bean依赖关系注入。
在Spring2.0中,可以使用AspectJ对领域模型进行静态织入,这样当该领域模型在容器外被创建的时候,会产生对容器的回调,进行依赖关系的注入。
Spring2.0提供的这一特性,确保了Martin Folwer的Rich Domain Object的可行性,这一特性的提供恐怕会对未来很多Java系统的设计产生相当深远的影响。
其实针对Rich Domain Object更进一步,如果将DAO功能作为Domain Object的抽象父类,那么持久化对象PO就会集PO,DAO,Service对象于一身,整个业务层,持久层完全合并为一个对象,通过这种方式进行框架简化得到的结果就是,高度类似于ruby on rails的full-stack的MVC框架。
-
本身就会导致XML阅读和修改一定的困难。并且用XML配置本身无法直接进行单元测试来验证依赖关系
robbin的口水 -JavaEye技术社区 - Mozilla Firefox
-
但是Hibernate不够易用,而且有一些明显的缺陷:one-to-one必须通过bytecode enhancement才能lazy loading;不支持多态关联;怪异的inverse配置和维护;DetachedCriteria有明显的bug;many-to-one的eager fetch设置不够灵活
-
我们已经听到太多对于spring的xml bean配置文件的抱怨。也许配置文件不是太大的问题,spring已经开始尝试引入annotation。但是spring的致命问题是无法方便的对动态创建的bean进行依赖注入。Google Guice的出现让我们看到了其实prototype的bean和动态创建的bean其实也可以很容易的管理。spring自身的缺陷事实上造成了很难进行rich domain model架构的实现。
Hibernate 學習筆記 - Mozilla Firefox
-
為了能夠重複使用Criteria物件,在Hibernate
3中新增了DetchedCriteria,您可以先建立DetchedCriteria實例,並加入各種查詢條件,並於需要查詢時再與Session綁
定,獲得一個綁定Session的Criteria物件
Hibernate 學習筆記 - Mozilla Firefox
-
然而如果是在網路上的系統,同時間會有許多連線,如果每一次讀取資料都造成鎖定,其後繼的存取就必須等
待,這將造成效能上的問題,造成後繼使用者的長時間等待。 -
在不實行悲觀鎖定策略的情況下,資料不一致的情況一但發生,有幾個解決的方法,一種是先更新為主,一種是後更新的為主,比較複雜的就是檢查發生變動的資料
來實現,或是檢查所有屬性來實現樂觀鎖定。 -
Hibernate中透過版本號檢查來實現後更新為主,這也是Hibernate所推薦的方式,在資料庫中加入一個version欄位記錄,在讀取資料時
連同版本號一同讀取,並在更新資料時比對版本號與資料庫中的版本號,如果等於資料庫中的版本號則予以更新,並遞增版本號,如果小於資料庫中的版本號就丟出
例外。 -
ERROR
AbstractFlushingEventListener:277 - Could not synchronize database
state with session
org.hibernate.StaleObjectStateException:
Row was updated or deleted by another transaction (or unsaved-value
mapping was incorrect): [onlyfun.caterpillar.User#1]
at
org.hibernate.persister.entity.BasicEntityPersister.check -
由於新的版本號是1,而userV2的版本號還是0,因此更新失敗丟出StableObjectStateException,您可以捕捉這個例外作善後
處理,例如在處理中重新讀取資料庫中的資料,同時將目前的資料與資料庫中的資料秀出來,讓使用者有機會比對不一致的資料,以決定要變更的部份,或者您可以
設計程式自動讀取新的資料,並比對真正要更新的資料,這一切可以在背景執行,而不用讓您的使用者知道。
Hibernate 學習筆記 - Mozilla Firefox
-
悲觀鎖定(Pessimistic
Locking)一如其名稱所示,悲觀的認定每次資料存取時,其它的客戶端也會存取同一筆資料,因此對該筆資料進行鎖定,直到自己操作完成後解除鎖定。 -
用Query或
Criteria的setLockMode()方法來設定要鎖定的表或列(Row)及其鎖定模式 -
- LockMode.UPGRADE:利用資料庫的for update子句進行鎖定。
- LockMode.UPGRADE_NOWAIT:使用for update
nowait子句進行鎖定,在Oracle資料庫中使用
-
- LockMode.WRITE:在insert或update時進行鎖定,Hibernate會在save()方法時自動獲得鎖
定。 - LockMode.READ:在讀取記錄時Hibernate會自動獲得鎖定。
- LockMode.NONE:沒有鎖定。
- LockMode.WRITE:在insert或update時進行鎖定,Hibernate會在save()方法時自動獲得鎖
-
如果資料庫不支援所指定的鎖定模式,Hibernate會選擇一個合適的鎖定替換,而不是丟出一個例外。
Hibernate 學習筆記 - Mozilla Firefox
-
Hibernate本身沒有交易管理功能,它依賴於JDBC或JTA的交易管理功能,預設是使用JDBC交易管理,可以在配置文件中加上
hibernate.transaction.factory_class屬性來指定Transaction的工廠類別 -
Session是lazy的,也就是在一開始的openSession()取得Session時,並不會馬上取得Connection,在beginTransaction()時,才會真正取得JDBC的Connection實例,並設定AutoCommit為false,在
操作過程中,最後要commit
(),否則的話對資料庫的操作不會有作用,在commit()之後,Connection與Session脫勾,如果使用Session再度
beginTransaction()的話,會重新取得Connection,如果操作過程中因發生例外,則最後commit()不會被執行,之前的操作
取消,執行rollback()可撤
消之前的操作 -
PS. 要使用MySQL中的交易處理,必須建立交易表類型的表格,例如InnoDB的表格:
CREATE TABLE user (
.....
....
) TYPE = InnoDB;
Hibernate 學習筆記 - Mozilla Firefox
-
Query上有list()與iterate()方法,兩者的差別在於開啟Query快取之後,list()方法在讀取資料時,會利用到Query快取,
而iterate()則不會使用到Query快取功能,而是直接從資料庫中再查詢資料
Hibernate 學習筆記 - Mozilla Firefox
-
您的資料庫表格中的資料很少變動,在
使用Query查詢資料時,如果表格內容沒有變動,您希望能重用上一次查詢的結果,除非表格內容有變動才向資料庫查詢 -
因為要使用Query的快取功能必須在兩次查詢時所使用的SQL相同,且兩次查詢之間表格沒有任何資料變動下才有意義
-
先在hibernate.cfg.xml中設定hibernate.cache.use_query_cache屬
-
然後在每次建立Query實例時,執行setCacheable(true)
Hibernate 學習筆記 - Mozilla Firefox
-
Hibernate二級快取可以跨越數個Session,二級快取由同一個SessionFactory所建立的Session所共享,因而又稱為
SessionFactory level快取。
Hibernate本身並未提供二級快取的實現,而是藉由第三方(Third-party)產品來實現,Hibernate預設使用EHCache作為其
二級快取的實現,在最簡單的情況下,您只需在Hibernate下撰寫一個ehcache.xml作為EHCache的資源定義檔,可以在
Hibernate下載檔案中的etc目錄下找到一個已經撰寫好的ehcache.xml -
Session會先在Session
level快取中查詢看有無資料,如果沒有就試著從二級快取中查詢資料 -
如果打算清除二級快取的資料,可以使用SessionFactory的evict()方法
-
如果打算在Hibernate中使用其它第三方產品進行快取,則可以在hibernate.cfg.xml中定義
hibernate.cache.provider_class屬性 -
可以設定的策略包括read-only、read-write、nonstrict-read-write與transactional,並不是每一個第
三方快取實現都支援所有的選項,每一個選項的使用時機與支援的產品
Hibernate 學習筆記 - Mozilla Firefox
-
快取(Cache)是資料庫在記憶體中的臨時容器,從資料庫中讀取的資料在快取中會有一份臨時拷貝,當您查詢某個數據時,會先在快取中尋找是否有相對應的
拷貝,如果有的話就直接返回資料,而無需連接資料庫進行查詢,只有在快取中找不到資料時,才從資料庫中查詢資料,藉由快取,可以提昇應用程式讀取資料時的
效能。 -
在Hibernate中快取分作兩個層級:Session
level與SessionFactory level(又稱Second level快取)。 -
Session會維護一個Map容器,並保留與目前Session發生關係的資料,當您透過主鍵來載入資料時,Session會先依據所要載入的類別與所
給定的主鍵,看看Map中是否已有資料,如果有的話就返回,若沒有就對資料庫進行查詢,並在載入資料後在Map中維護 -
可以透過evict()將某個物件從快取中移去
-
也可以使用clear()清除快取中的所有物件
-
Session level的快取隨著Session建立與銷毀
-
您也可以使用Session的setReadOnly(object, true),設定某物件為唯讀,對於唯讀資料,不會在快取中維護一個複本,不會執行dirty check
Notation: * = Private bookmark and comment|… = Clipping [?] | … = Public highlight [?]


