EJB框架采用了种侵略性(Invasive)思路方法来设计对象它要求你在设计中加入符合EJB规范标准代码些轻量级COP框架例如Avalon也要求对象设计时必须符合某种规范标准例如Serviceable接口这种做法是典型Type 1做法
这种设计思路要求Spring采用种动态、灵活方式来设计框架所以spring大量采用了反射首先spring要解决个问题就是如何管理beanIOC思想要求bean的间不能够直接而应该采用种被动方式进行协作所以bean管理是spring中核心部分
反射和内省在代码层次上研究问题有时候能够带来出人意料灵活性但它使用有时候也是个哲学问题不论是在ORM设计还是在AOP设计上都出现了类似问题-究竟是使用反射还是使用代码生成
在Spring中处理这个问题核心是在org.springframework.beans包中而其中最为核心部分则是BeanWrapperBeanWrapper顾名思义就是bean包装器所以它主要工作就是对任何个bean进行属性(包括内嵌属性)设置和思路方法在BeanWrapper默认实现类BeanWrapperImpl中虽然代码较长但完成工作却是非常集中
BeanWrapper深入研究
我们看看这个BeanWrapper是如何发挥运作假设我们有两个bean:
public Company {
private String name;
private Employee managingDirector;
public String getName {
this.name;
}
public void Name(String name) {
this.name = name;
}
public Employee getManagingDirector {
this.managingDirector;
}
public void ManagingDirector(Employee managingDirector) {
this.managingDirector = managingDirector;
}
}
public Employee {
private float salary;
public float getSalary {
salary;
}
public void Salary(float salary) {
this.salary = salary;
}
}
然后我们使用BeanWrapper来这两个bean: Company c = Company;
BeanWrapper bwComp = BeanWrapperImpl(c);
// ting the company name...
bwComp.PropertyValue("name", "Some Company Inc.");
// ... can also be done like this:
PropertyValue v = PropertyValue("name", "Some Company Inc.");
bwComp.PropertyValue(v);
// ok, lets create the director and tie it to the company:
Employee jim = Employee;
BeanWrapper bwJim = BeanWrapperImpl(jim);
bwJim.PropertyValue("name", "Jim Stravinsky");
bwComp.PropertyValue("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 subes must implement the abstract mapRow(ResultSet, ) method to convert each row of the JDBC ResultSet o an object. 用户必须实现mapRow思路方法这是典型模板思路方法应用我们拿个具体例子来看看:
UserQuery extends MappingSqlQuery {
public UserQuery(DataSource datasource) {
super(datasource, "SELECT * FROM PUB_USER_ADDRESS WHERE USER_ID = ?");
declareParameter( SqlParameter(Types.NUMERIC));
compile;
}
// Map a result row to a Java object
protected Object mapRow(ResultSet rs, rownum) throws SQLException {
User user = User;
user.Id(rs.getLong("USER_ID"));
user.Forename(rs.getString("FORENAME"));
user;
}
public User findUser(long id) {
// Use super convenience method to provide strong typing
(User) findObject(id);
}
}
其次是第 2个问题最麻烦地方应该说是需要截住JDBC异常然后判断异常类型并重新抛出异常问题可以通过连接来获取所以麻烦是如何截获异常Spring Framework采用思路方法是回调处理回调类在Spring Framework中被称为templateJdbcTemplate template = JdbcTemplate(dataSource);
final List names = LinkedList;
template.query("SELECT USER.NAME FROM USER",
RowCallbackHandler {
public void processRow(ResultSet rs) throws SQLException {
names.add(rs.getString(1));
}
});
回调是个匿名类其中也使用了模板思路方法异常处理都在父类中完成了层间松耦合
在开放源码界已经出现了大量基于MVCWeb容器但是这些容器都仅限于Web范围不涉及Web层次后端连接spring作为个整体性框架定义了种Web层和后端业务层连接方式 这个思路仍然疏运图MVC范畴但耦合更松散不依赖于具体集成层次
public GoogleSearchController
implements Controller {
private IGoogleSearchPort google;
private String googleKey;
public void Google(IGoogleSearchPort google) {
this.google = google;
}
public void GoogleKey(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);
ModelAndView("googleResults", "result", result);
}
}
回调是个匿名类其中也使用了模板思路方法异常处理都在父类中完成了
最新评论