1.org.springframework.beans.support.PagedListHolder
PagedListHolder 是一个简单状态的,可以处理对象列表的持有者,它将这些对象分成页面。页号从0开
始。
这个主要在WEB UI中使用。具有代表的,一个实例将被以列示一列bean,将它们放置到session中,然后
将它们导出为一个model(模型)。所有的属性将程序化set/get,但是最常用的方式是数据绑定,例如组
装请求参数中的bean。View层中主要用到getter方法。
使用一个属性“sort”,将通过一个SortDifinition实现将基本的list排序。默认,一个
MutableSortDefinition实例将被使用,使用相同的属性将递增给定的值。
BeanWrapper要求,绑定数据名必须被称作“pageSize”和 “sort.ascending”。 注意,名字
和嵌套语法匹配各自的JSTL EL表达式,例如“myModelAttr.pageSize”和
“myModelAttr.sort.ascending”。
其实,就是用来提供给表现分页用的。
2. org.springframework.beans.factory.InitializingBean
这是一个能够被bean实现的接口,如果这个bean需要一旦它所有的属性被注入(还有指定的
BeanFactoryAware和ApplicationContextAware接口相关的方法都被执行)后就做出反应:例如,执行一
个自定义的初始化,或者仅仅是检查所有托管的属性是否被正确的注入。可以通过抛出异常阻止继续初
始化。
我们也可以选择指定一个自定义的 init-method来代替实现InitializingBean,这个init-
method通过一个描述bean定义的XML定义。
3. org.springframework.aop. AfterReturningAdvice
After returning advice 仅仅在正常的方法返回后调用,而不是在抛出异常时调用。这个通知能够看到
返回值,但是不能改变它。
它唯一的方法为:void afterReturning(Object returnValue, Method method, Object[] args,
Object target) throws Throwable;
在指定的方法(其实就是JoinPoint)成功返回后被调用。
参数 returnValue: 指定的方法的返回值。
参数 method:被调用的方法。
参数 args:方法的参数。
参数 target:方法期待的目标。可以使null。JoinPoint所在的对象。
@throws :如果当前对象希望中断调用,则抛出异常。所有方法签名中允许抛出的异
常将会返回给调用者。否则将会被包装为运行期异常。
4. org.springframework.mail.SimpleMailMessage
设计一个简单mail 信息,它包括收信人mail、发信人mail、主题和内容。
考虑JavaMailSender 和 JavaMailMimeMessage 来创建更复杂的信息,例如带有附件的信息,
特殊符号,或者私人邮件。
5. org.springframework.samples.jpetstore.domain.logic. PetStoreImpl
这里是该程序的作者对其说明,很有意义。
JPetStore主要业务对象。
这个对象使用了5个DAO对象,从具体的操作持久化API工作中解脱出来。因此,虽然这个程序使用
iBATIS 做数据访问,但是如果要使用其它的持久化工具来访问,就不需要修改这个类的任何代码。
这个对象使用DAO实例是通过Spring容器依赖注入的(使用依赖注入使DAO变成是可配置的)。我们这里使
用的setter注入,暴露每个DAO的setter方法给用户。这就意味着我们只要在配置该类的bean时,使用“
property”属性就可以注入DAO。这里的属性是只写的(write-only):相应的setter方法没有对应的
getter方法。Getter方法是可选的:只有当你的业务对象需要访问这些属性时,才去暴露getter方法。
在JPetStore程序中只有一个该类的对象。在Spring术语中,这叫做一个“singleton“(单例)
对象。这就意味着每个程序上下文都只有一个。工厂创建一个单例对象;在这里没有必要提供一个私有
的构造器,静态工厂方法等是单例模式的传统实现方式。
这是一个POJO(普通的Java对象,自我维护自身的状态,处理本身的属性及存取方法外,一般不
提供任何API)。它不依赖于任何的Spring API。在Spring容器外,仍然可用,而且能够在使用JUnit 测
试时,初始化该对象。但是,我们仍然使用声明式事务管理,而依赖Spring的AOP。
这个类给每个方法定义了一个默认的事务属性。
注意,这个属性定义仅仅在使用Commons Attribute auto-proxying (即使用Common Attribute
或 Annotation时, Annotation是Spring提供的API,所以依赖了Spring API或Common Attribute API)
时才是必须使用的。
在 war/WEB-INF 目录下的默认applicationContext.xml 文件中的TransactionFactoryProxyBean不需要
定义attributes。
而在接下来使用Commons Attributes attribute 语法来定义的attribute。
6. org.springframework.orm.ibatis.support.SqlMapClientDaoSupport
给iBATIS SqlMapClientDAO提供的方便的父类。需要设置一个SqlMapClient,提供给子类一个基于设入
的SqlMapClient的SqlMapClinetTemplate。
你也可以传递一个已经配置好的SqlMapClientTemplate实例来代替传递一个SqlMapClient(也就是代替默
认的SqlMapClientTemplate,默认的SqlMapClientTemplate使用了传入的SqlMapClient)。这样就使得你
所有的DAO的分享同一个SqlMapClientTemplate配置,例如,一个自定义的SQLExceptionTranslator也可
以使用这个SqlMapClientTemplate。
7. org.springframework.orm.ibatis.SqlMapClientTemplate
一个帮助类,用来简化使用iBATIS com.ibatis.sqlmap.client.SqlMapClient API进行数据访
问,依照org.springframework.dao 异常模型,将被检查性异常SQLExceptions转换成不受检测异常
DataAccessExceptions。使用和org.springframework.jdbc.core.JdbcTemplate相同的
org.springframework.jdbc.support.SQLExceptionTranslator机制。
这个类的主要方法执行了数据访问行为的回调。此外,该类提供了众多的方法去镜像
com.ibatis.sqlmap.client.SqlMapExecutor的执行方法。
这个模版一般都使用了方便而简单的方法去执行 query/insert/update/delete 操作。但是,
更复杂的操作例如批量更新,就必须自定义一个SqlMapClientCallback,常常都是使用匿名的内部类实
现。例如:
getSqlMapClientTemplate().execute(new SqlMapClientCallback() {
public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException {
executor.startBatch();
executor.update("insertSomething", "myParamValue");
executor.update("insertSomethingElse", "myOtherParamValue");
executor.executeBatch();
return null;
}
});
这个模版需要一个SqlMapClient来工作,可以通过”sqlMapClient”属性来传递。一个Spring
上下文都典型地使用一个SqlMapClientFactoryBean去构建SqlMapClient。模版还需要配置一个
DataSource来取得连接,但是,如果在传入的SqlMapClient中指定了DataSource(典型地,使用
SqlMapClientFactoryBean的”dataSource”属性),那么这不是必须的。
所谓的回调就是指,一个对象通过调用另一个对象的方法来完成既定的行为(也可以说是委托
给另一个对象来完成),而本对象可以去执行其它的操作。
8. org.springframework.samples.jpetstore.web.struts. BaseAction
JPetStore的Web层的所有Struts Action的父类
从ServletContext中获得WebApplicationContext,然后又从WebApplicationContext中获得
PetStoreFacade,然后通过一个getter方法提供给子类。(或者是继承Spring提供的ActionSupport类,
它预实现了WebApplicatinContext的查找)但是这里在Struts中插入了Spring的API。所以增加了耦合度
,该Action类及其子类不能脱离Spring使用,这里并不是最佳实践。
比较好的方式是:配置Spring将Action作为Bean托管,使用ContextLoaderPlugin,并在Spring context
。
* 中设置依赖关系。具体看Spring手册。
9. org.springframework.util.StringUtils
String工具方法的混合类。
主要在Spring框架内工作;请参考Jakarta's Commons Lang 来了解更多而全面的String 工具类的信息
。
这个提供了一些处理core Java String 和 StringBuffer的简单功能,例如替换一个目标字符串中所有
给定的子字符串的功能。它也提供易使用的方法去转换定界字符串,如CSV字符串,和集合以及数组。
关于持久层DAO接口的好处(个人想法)
事实上,在程序中有很多对象依赖了DAO,如果我们直接使用DAO,而不是使用DAO的接口的话,
那么如果我们改变底层的数据库时(或者是不同的ORM框架),相关的依赖该DAO的对象的类,或者配置
必须修改。例如,我们使用AOP可配置编程时,我们就必须修改织入的DAO,而如果我们使用DAO接口,我
们可以直接织入到接口上,那么我们不需要修改任何代码。业务层和持久层也应该通过接口通信。
同样,DAO接口也获得所有接口必将获得的好处,那么就是耦合度的下降。
具体来说就是,避免其它API的污染,增加API维护和使用的复杂性;另外就是提供给一个更灵
活的多态实现,也就是说在我们无法修改源码的情况下,也能改变具体实现,而且我们应该总是避免,
因为我们常常没有这样的权限,那么就要就API的设计者提供更好的实现(开--闭原理),这里是通过
XML配置文件的方式。
但是显然,这里增加了间接性,增加了代码量,似乎增加了复杂性,然而恰恰相反,合理的使
用接口使得程序的结构更加的清晰。
JPetStore使用了SecureBaseAction 主要是提供了当HttpSession中未包含登陆信息时,跳到登
陆页面,其实所有扩展了这个类的类的实例,都是需要在安全条件下(用户权限控制)使用的,其实我们
可以用filter代替。但是这样显然效率更高,但是耦合度也更高了,因为我们不可以配置自己的安全策
略了。
JPetStore在Struts Web控制代码中使用了大量的Spring API,其实这是不推荐使用的,例如,
BaseAction中使用了WebApplicationContext;SearchProductsAction使用了
org.springframework.util.StringUtils,还有使用很频繁的
org.springframework.beans.support.PagedListHolder。
JPetStore在使用Struts时,大量使用了HttpSession,好的建议是尽量少使用HttpSession,所
以这里也不是好的实践,例如,将所有的页面都找出来,但是是缓存在HttpSession中,虽然提高了客户
端的用户感受,但是会给服务器以沉重的负担。
JPetStore中将ActionForm做了两种作用,一种主要是用于数据的提交(Form中用),一般以
working开头,一种主要用于处理过后的数据的显示和数据的保存。因为都是存储在HttpSession中,为
了区分采用了不同的名字,而working FormBean的生命周期是在提交了数据后结束,因此在这时,我们
应该将内存空间收回。