品味Spring 的魅力



  Spring的哲学是在不影响Java对象的设计的情况下将Java对象加入到框架中。

  EJB的框架采用了一种侵略性(Invasive)的方法来设计对象,它要求你在设计中加入符合EJB规范的代码。一些轻量级的COP框架,例如Avalon,也要求对象设计时必须符合某种规范,例如Serviceable接口,这种做法是典型的Type 1做法。

  这种设计思路要求Spring采用一种动态的、灵活的方式来设计框架。所以spring大量采用了反射。首先spring要解决的一个问题就是如何管理bean。因为IOC的思想要求bean之间不能够直接调用,而应该采用一种被动的方式进行协作。所以bean的管理是spring中的核心部分。

  反射和内省在代码的层次上思考问题,有时候能够带来出人意料的灵活性。但它的使用有时候也是一个哲学问题,不论是在ORM设计还是在AOP设计上都出现了类似的问题-究竟是使用反射,还是使用代码生成。

  在Spring中,处理这个问题的核心是在org.springframework.beans包中。而其中最为核心的部分,则是BeanWrapper。BeanWrapper,顾名思义,就是bean的包装器。所以,它的主要工作,就是对任何一个bean,进行属性(包括内嵌属性)的设置和方法的调用。在BeanWrapper的默认实现类BeanWrapperImpl中,虽然代码较长,但完成的工作却是非常的集中的。

  BeanWrapper的深入研究

  我们看看这个BeanWrapper是如何发挥运作的,假设我们有两个bean:

  public class Company {
  private String name;
  private Employee managingDirector;

  public String getName() {
  return this.name;
  }
  public void setName(String name) {
  this.name = name;
  }
  public Employee getManagingDirector() {
  return this.managingDirector;
  }
  public void setManagingDirector(Employee managingDirector) {
  this.managingDirector = managingDirector;
  }
  }

  public class Employee {
  private float salary;

  public float getSalary() {
  return salary;
  }
  public void setSalary(float salary) {
  this.salary = salary;
  }
  }

  然后我们使用BeanWrapper来调用这两个bean:

  Company c = new Company();
  BeanWrapper bwComp = BeanWrapperImpl(c);
  // setting the company name...
  bwComp.setPropertyValue("name", "Some Company Inc.");
  // ... can also be done like this:
  PropertyValue v = new PropertyValue("name", "Some Company Inc.");
  bwComp.setPropertyValue(v);

  // ok, let's create the director and tie it to the company:
  Employee jim = new Employee();
  BeanWrapper bwJim = BeanWrapperImpl(jim);
  bwJim.setPropertyValue("name", "Jim Stravinsky");
  bwComp.setPropertyValue("managingDirector", jim);

  // retrieving the salary of the managingDirector through the company
  Float salary = (Float)bwComp.getPropertyValue("managingDirector.salary");

  看起来麻烦了许多,但是这样spring就可以使用统一的方式来管理bean的属性了。


  Bean的制造工厂

  有了对单个Bean的包装,还需要对多个的bean进行管理。在spring中,把bean纳入到一个核心库中进行管理。bean的生产有两种方法:一种是一个bean产生多个实例,一种是一个bean只产生一个实例。如果对设计模式熟悉的话,我们就会想到,前者可以采用Prototype,后者可以采用Singleton。

  注意到,反射技术的使用使得我们不再像原始的工厂方法模式那样创建对象。反射可以非常灵活的根据类的名称创建一个对象。所以spring只使用了Prototype和Singleton这两个基本的模式。

  spring正是这样处理的,但是我们希望用户能够维护统一的接口,而不需要关心当前的bean到底是Prototype产生的独立的bean,还是Singleton产生的共享的bean。所以,在org.springframework.beans.factory包中的BeanFactory定义了统一的getBean方法。

  JDBC再封装JDBC优雅的封装了底层的数据库,但是JDBC仍然存在诸多的不变。你需要编写大量的代码来完成CRUD操作,而且,JDBC无论是遇到什么样的问题,都抛出一个SQLException,这种做法在异常使用上被称为不完备的信息。因为问题可能是很复杂的,也许是数据库连接的问题,也许是并发控制的问题,也许只是SQL语句出错。没有理由用一个简单的SQLException就搞定全部的问题了,这种做法有些不负责任。针对这两个问题,Spring Framework提出了两种解决方法:首先,提供一个框架,把JDBC应用中的获取连接、异常处理、释放等比较通用的操作全部都集中起来,用户只需要提供特定的实现就OK了。实现的具体细节采用的是模板方法。举个例子,在org.springframework.jdbc.object包中,MappingSqlQuery类实现了将SQL查询映射为具体的业务对象。JavaDoc中这样写到:Reusable query in which concrete subclasses must implement the abstract mapRow(ResultSet, int) method to convert each row of the JDBC ResultSet into an object. 用户必须实现mapRow方法,这是典型模板方法的应用。我们拿一个具体的例子来看看:

  class UserQuery extends MappingSqlQuery {

  public UserQuery(DataSource datasource) {
  super(datasource, "SELECT * FROM PUB_USER_ADDRESS WHERE USER_ID = ?");
  declareParameter(new SqlParameter(Types.NUMERIC));
  compile();
  }

  // Map a result set row to a Java object
  protected Object mapRow(ResultSet rs, int rownum) throws SQLException {
  User user = new User();
  user.setId(rs.getLong("USER_ID"));
  user.setForename(rs.getString("FORENAME"));
  return user;
  }

  public User findUser(long id) {
  // Use superclass convenience method to provide strong typing
  return (User) findObject(id);
  }
  }

  其次是第二个问题,最麻烦的地方应该说是需要截住JDBC的异常,然后判断异常的类型,并重新抛出异常。错误的问题可以通过连接来获取,所以麻烦的是如何截获异常。Spring Framework采用的方法是回调,处理回调的类在Spring Framework中被称为template

  JdbcTemplate template = new JdbcTemplate(dataSource);
  final List names = new LinkedList();
  template.query("SELECT USER.NAME FROM USER",
  new RowCallbackHandler() {
  public void processRow(ResultSet rs) throws SQLException {
  names.add(rs.getString(1));
  }
  });

  回调函数是一个匿名类,其中也使用了模板方法,异常的处理都在父类中完成了。

  层间松耦合

  在开放源码界已经出现了大量的基于MVC的Web容器,但是这些容器都仅限于Web的范围,不涉及Web层次后端的连接,spring作为一个整体性的框架,定义了一种Web层和后端业务层的连接方式, 这个思路仍然疏运图MVC的范畴,但耦合更松散,不依赖于具体的集成层次。

  public class GoogleSearchController
  implements Controller {

  private IGoogleSearchPort google;

  private String googleKey;

  public void setGoogle(IGoogleSearchPort google) {
  this.google = google;
  }

  public void setGoogleKey(String googleKey) {
  this.googleKey = googleKey;
  }

  public ModelAndView handleRequest(
  HttpServletRequest request, HttpServletResponse response)
  throws ServletException, IOException {
   String query = request.getParameter("query");
   GoogleSearchResult result =
   // Google property definitions omitted...

   // Use google business object
   google.doGoogleSearch(this.googleKey, query,start, maxResults, filter, restrict, safeSearch, lr, ie, oe);

   return new ModelAndView("googleResults", "result", result);
  }
  }

  回调函数是一个匿名类,其中也使用了模板方法,异常的处理都在父类中完成了。



相关阅读:
javascript修复浏览器中头痛问题
JSP漏洞大观
linux如何实现用户注销/挂起(logout)
ASP FSO文件操作函数代码(复制文件、重命名文件、删除文件、替换字符串)
JavaScript教程:常用对象的属性和方法
CSS图片垂直居中实现方法详解
轻松修复Discuz!数据库
Wordpress博客首页中的每篇日志添加图片
sql 触发器使用例子
SEO的最高境界-SEO外链增加流量总结大全(收藏)
Community Server专题三:HttpModule
面向XHTML的IE条件注释
php中显示数组与对象的实现代码
CSS实例::nth-child和:nth-type-of的区别
快速导航
PHP MySQL HTML CSS JavaScript MSSQL AJAX .NET JSP Linux Mac ASP 服务器 SQL jQuery C# C++ java Android IOS oracle MongoDB SQLite wamp 交通频道 作文范文 上半年宣传工作总结 我是一只蝴蝶作文 寂寞的长夜(转) 辨书记 冬季运动会作文800字 豁达是一种生存艺术 与爱一起拾荒 成长忆思作文700字 此日不复,寸阴尺宝 小小说女人不记仇 高中高三作文2100字:聊一聊身边的“话” 轻伤 下岗职工再创业演讲稿 一辈子这么长,谁不曾遇到点绝望的事 我是小书迷 大班数学活动:花儿与夹子 演讲稿——立高尚师德,做诚信教师 春天,走出娇情 2015正风肃纪专项行动方案 后山果园作文 【中学作文】银手镯 XX年年度述职报告(学院教员) 那是家乡,那是雪 喜欢那样的轻狂、内心、不孤单作文 面包发霉的秘密 副区长在全区社区建设工作会议上的讲话 端午节幽默祝福短信 赚钱需有狼性,逮住机会,绝不手软! 舟曲泥石流,惊!作文300字 肥皂水泡泡200字 先讲背景 八年级命题作文怎么写 考试祝福语成功必备 真正影响光辉的是灯里的油 爱情像风一样突然袭来让你措手不及 时光的遗忘 新中国成立了 腊八节短信祝福精编 我爱读书的作文精选650字 为何不能放弃过去? 女政工师先进事迹材料(煤矿) 不望国耻,振兴中华 学报告心得体会 邮政个人鉴定 假如我是一个削笔刀作文200字 经典空间说说大全 人尽其责作文900字 钉纽扣250字 劈山救母的故事 2013年人事局工作总结及明年工作打算

Copyright © 2016 phpStudy |