Warp framework - 一个相当有前途的Java轻量级Web开发框架

March 11, 2008

转载自robbin javaeye
Warp framework 是最近刚刚发布的、基于Google Guice的轻量级Web开发框架,我也是在JavaEye网站的新闻频道看到的这条新闻: warp-persist 1.0: 为Google Guice专门提供持久层与事务处理的框架,通过这个新闻仔细阅读了Warp网站上面的文档,感觉到很振奋,Warp是一个相当棒的Java Web框架,而且前景非常看好。

Warp框架充分利用了JDK5.0的Annotation和泛型机制,并且基于Google Guice这个IoC框架,提供了full-stack的Web开发设施,他主要包含了四个部分:

warp-persist框架:封装Hibernate和JPA,提供事务管理和持久化资源管理
warp-dynamic-finder:提供了基于Annotation的动态查询功能,让数据库查询变得异常简单,不再需要DAO层
warp-mvc:借鉴了Tapestry5,提供了一个基于事件机制和组件化的Web层,并且组件注入方式高度IoC化
warp-servlet: 提供了一些Servlet的封装和附加的高级功能,例如URL过滤,和其他web框架集成等等

这几年来,Java在Web开发框架方面的进步显得很有限,Spring/Hibernate组合对撼JBoss Seam形成两大竞争的主流态势,但是这两个Web框架在Web快速开发方面的创新还显得不够好:Spring是越来越臃肿了,配置文件也是越来越复杂难懂了;JBoss Seam门槛又过高,而且集成的JSF一向受人垢病,并非完美的解决方案,特别是在Ruby on Rails横空出世之后,Java社区对于简洁易用的快速web开发框架的企盼也是一直很高的。

Warp在我看来是这方面做的最好的,它有以下几个鲜明的特点:

一、充分利用JDK5的annotation,简化编程和配置文件

Warp基于Google Guice并且发扬光大,自身无配置文件,所有功能完成均通过annotation,所以编程相当简洁

二、大量使用JDK5的泛型编程,提供强类型安全保证

虽说脚本语言的Duck Typing理念很流行,不过Java的优势也就是类型安全,Spring大量运用反射和XML配置等于是放弃了Java的优势。Warp在泛型方面做的很好,我相信在IDE的帮助下,Warp编程会更轻松

三、Warp-persist提供了声明式的事务管理,终于可以取代Spring了

Google Guice很好很强大,但是它没有事务管理能力和资源管理能力,所以无法取代spring,但是Warp-persist填补了这一缺憾,注入和管理Hibernate很容易:

Java代码
Injector injector = Guice.createInjector(…, PersistenceService
.usingHibernate()
.across(UnitOfWork.TRANSACTION)
.buildModule());

要声明事务比spring可简单多了:

Java代码
public class MyService {
@Inject Provider session;

@Transactional
public void createNewPerson() {
session.get().saveOrUpdate(new Person(…));
}
}

Warp支持Hibernate/JPA的所有事务管理策略,不但注入方式简单,而且声明事务方式更简单,代码看着简洁,写着更省心。

四、Dynamic Finder实在很酷!

还是直接看代码吧:

Java代码
@Finder(query=”from Person”)
public List
listAll() { return null; }

用annotation声明一下,一行查询代码都没有,你还要DAO干啥呢?

Java代码
@Finder(query=”from Person where firstName = :firstName”)
Person find(@Named(”firstName”) String name);

带参数的绑定变量查询,还是一行代码不用写,DAO是啥?

Java代码
@Finder(query=”from Person”)
List listAll(@FirstResult int first, @MaxResults int max);

带分页的查询,还是一行代码不用写,谁用DAO我跟谁急 !

五、Web层也极其简单

Warp-MVC模仿了Tapestry 5的架构,但是作者做了大量的改良和简化,作者解释了一下为什么不直接使用Tapestry,而是自己开发的理由。

Warp-MVC看起来像一个Tapestry的简化版,有组件的概念,事件响应的方式,但是非常易用,非常简洁,URL映射也通过annotation方式声明,作者在自己的博客上面提供了相关的简单示例,可以参考:

http://www.jroller.com/dhanji/

Warp框架是最近几年来,我看到的第一个走在正确发展方向上的Java Web框架:结构简单、易用使用、但充分发挥了Java自身的语法优势,非常值得期待!

目前Warp框架还不是特别成熟,但是Warp-persistent已经相当稳定了,如果你是使用Hibernate/Spring/Struts来开发项目的话,不妨试试Warp,把spring换掉改成Hibernate/Warp/Struts2.0,也是一个不错的解决方案,全部运用annotation,让你的项目Zero Configuration。

友情提醒:Warp官方网站无法直接访问,建议在FireFox浏览器上面安装gladder插件,跨越GFW。

Warp Framework - 官方网站

Prototypes and Java Config with Spring

Sometimes in Spring, you need to create a one-time use instance that has state (a.k.a a prototype bean) from a Singleton object. Essentially, one would need to access a prototype for a number of cases, namely those where the Gang of Four Abstract Factory can be applied :

You have an object that requires complex construction

You have many potential implementations of an interface, and generic logic that applies to all of those implementations.

I’ve been thinking about and even working on Spring JavaConfig (SJC) for a while. Take a look at this SJC bug that talks about lookup methods. The way you’d implement “lookup methods” in a java oriented environment is quite straight forward. The bean stays the same:

package fiona.apple;

// no more Spring imports!
public abstract class CommandManager {
public Object process(Object commandState) {
// grab a new instance of the appropriate Command interface
Command command = createCommand();
// set the state on the (hopefully brand new) Command instance
command.setState(commandState);
return command.execute();
}

// okay… but where is the implementation of this method?
protected abstract Command createCommand();
}

The configuration code is surprisingly simple:

package fiona.apple;

// a whole bunch of spring and business object imports

@Configuration
public class CommandManagerConfiguration {

@Bean
public CommandManager commandManager(){
return new CommandManager(){
protected Command createCommand(){
/* you can add your dependencies here,
if you have any */
return new AsyncCommand();
}
};
}

}

A Java based configuration is, IMHO, a much more natural implementation than the XML approach. This is a surprisingly trivial implementation of a relatively complicated scenario.

The slickness here comes from writing simple Java code
SJC beyond prototypes

The prototype slickness lead me down a path that helped me shed the preconceived notions that came from XML-based development. I started thinking about where I could use java to make my application configuration process even better. Now, I definitely thought of some cool infrastructure stuff that I could add to Spring JavaConfig, but that’s not the application configuration ingredients that I find most interesting.

The most interesting techniques a programmatic environment can add to application construction come from really simple day-to-day java code. For example, you can create conditional beans using a simple “if” statement. You can concatenate Lists and Maps. Those examples, plus other simple programming techniques that we’ve come to depend on as second nature, are now available. Spring doesn’t dictate what I can do when constructing an application. You can now use Plain Old Java to configure your Plain Old Java Objects.

Spring2.5的新特性:第一部分

转载自infoq
简介

从诞生之初,Spring框架就坚守它的宗旨:简化企业级应用开发,同时给复杂问题提供强大的、非侵入性解决方案。一年前发布的Spring2.0就把这些主题推到了一个新的高度。XML Schema的支持和自定义命名空间的使用大大减少了基于XML的配置。使用Java5及更新版本java的开发人员如今可以利用植入了像泛型(generic)和注解等新语言特性的Spring库。最近,和AspectJ表达式语言的紧密集成,使得以非侵入方式添加跨越定义良好的Spring管理对象分组的行为成为可能。
相关厂商内容

《IDC:SOA中国路线图》技术分析报告下载

通过Oracle SQL、Linux和Ruby解决与数据集相关的问题

基于浪潮Loushang统一平台的电力行业解决方案

新发布的Spring2.5继续坚持了这个发展趋向,特别是为那些使用Java 5或更新版本java的开发人员提供了进一步简化而强大的新特性。这些新特性包括:注解驱动的依赖性注入(annotation-driven dependency injection),使用注解而非XML元数据来自动侦测classpath上的Spring组件,注解对生命周期方法的支持,一个新的web控制器模型将请求映射到加注解的方法上,在测试框架中支持Junit4,Spring XML命名空间的新增内容,等等。

本文是探讨这些新特性的3篇系列文章中的第一篇。本文将主要关注于简化的配置和在Spring应用程序上下文(application context)核心新增的基于注解的功能;第二篇文章将涵盖web层可用的新特性;最后一篇文章将着重介绍集成和测试的新增性能。这一系列的三篇文章中引用的例子都基于Spring PetClinic应用程序范例。此范例最近被重构以用于展示Spring最新功能,并被包含于Spring 2.5的发布下载包中,可以从Spring Framework 下载网页下载。查看”samples/petclinic”目录下的”readme.txt”文件可以得知关于如何构建和部署PetClinic应用程序,掌握本文提到的新技术的最佳方法也许就是对PetClinic应用程序中所展示的特性进行试验。
Spring支持JSR-250注解

Java EE5中引入了“Java平台的公共注解(Common Annotations for the Java Platform)”,而且该公共注解从Java SE 6一开始就被包含其中。 2006年5月,BEA系统宣布了他们在一个名为Pitchfork的项目上与Interface21的合作,该项目提供了基于Spring的Java EE 5编程模型的实现,包括支持用于注入(injection)、拦截( interception)和事务处理(transactions)的JSR-250注解和EJB 3注解(JSR-220)。 在2.5版本中,Spring框架的核心(core)现在支持以下JSR-250注解:
@Resource
@PostConstruct
@PreDestroy

结合Spring,这些注解在任何开发环境下都可以使用——无论是否有应用程序服务器——甚至是集成测试环境都可以。激活这样的支持仅仅是注册一个单独的Spring post-processor的事情:

@Resource注解

@Resource 注解被用来激活一个命名资源(named resource)的依赖注入,在JavaEE应用程序中,该注解被典型地转换为绑定于JNDI context中的一个对象。 Spring确实支持使用@Resource通过JNDI lookup来解析对象,默认地,拥有与@Resource注解所提供名字相匹配的“bean name(bean名字)”的Spring管理对象会被注入。 在下面的例子中,Spring会向加了注解的setter方法传递bean名为“dataSource”的Spring管理对象的引用。
@Resource(name=”dataSource”)
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}

直接使用@Resource注解一个域(field)同样是可能的。通过不暴露setter方法,代码愈发紧凑并且还提供了域不可修改的额外益处。正如下面将要证明的,@Resource注解甚至不需要一个显式的字符串值,在没有提供任何值的情况下,域名将被当作默认值。
@Resource
private DataSource dataSource; // inject the bean named ‘dataSource’

该方式被应用到setter方法的时候,默认名是从相应的属性衍生出来,换句话说,命名为’setDataSource’的方法被用来处理名为’dataSource’的属性。
private DataSource dataSource;
@Resource
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
}

当@Resource没有显式提供名字的时候,如果根据默认名字找不到对应的Spring管理对象,注入机制会回滚至类型匹配(type-match)。如果刚好只有一个Spring管理对象符合该依赖的类型,那么它会被注入。通过设置CommonAnnotationBeanPostProcessor 的‘fallbackToDefaultTypeMatch’属性为“false”(默认值是“true”)可以禁用这一特性。

正如上文所提到的,在解析标有@Resource注解的依赖时,Spring支持JNDI-lookup。如若要强制对所有使用@Resource注解的依赖进行JNDI lookup,那也只要将CommonAnnotationBeanPostProcessor的’alwaysUseJndiLookup’ 标识设置为true就可以了(默认值是false)。

另一个选择是,激活指定为‘resource-ref-mappings’的依据全局JNDI名的查找,在@Resource注解内提供‘mappedName’属性。即使目标对象实际上是一个JNDI资源,仍然推荐引入一个Spring管理对象,这样可以提供一个间接层并且因此降低耦合程度。自Spring2.0开始添加命名空间以来,定义一个委托Spring处理JNDI lookup的bean也变得愈发简练:

这个方法的优点在于间接层带来了巨大的部署弹性。比如说,一个单独的系统测试环境应该不再需要JNDI注册。在这种情况下,在系统测试配置中可以提供如下的bean定义:
p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.url}"
p:username="${jdbc.username}"
p:password="${jdbc.password}"/>

顺便提一下,上面的例子中,实际的JDBC连接属性从一个属性文件(properties file)解析而来,在这个属性文件里,关键字与提供的${占位符}互相对应,这需要注册一个名为PropertyPlaceholderConfigurer的BeanFactoryPostProcessor实现来完成。这是具体化那些属性(通常是针对特定环境的属性)常用的技术,这些属性可能比其他配置修改得更为频繁。

Srping2.5中新加入了‘context’命名空间,这个命名空间让我们能够得到更为简洁的方式来实现属性占位符(property placeholder)的配置:

生命周期注解:@PostConstruct和@PreDestroy

@PostConstruct 和@PreDestroy注解分别用来触发Spring的初始化和销毁回调。这个特性在原有基础上得到了扩展,但并没有替代在Spring2.5之前版本中提供的同样的回调的另两个选项。第一个选项是实现Spring的InitializingBean 和DisposableBean 接口中的一个或两个。这两个接口都需要一个回调方法的实现(分别是afterPropertiesSet()和destroy() )。这种基于接口的方法利用了Spring自动识别任何实现这些接口的Spring管理对象的能力,因而不再需要另外的配置。另一方面,Spring的一个关键目标是尽可能的非侵入。因此,许多Spring用户并不采用实现这些Spring特定接口的方法,而利用第二个选项,那就是提供他们自己的初始化和销毁方法。尽管入侵性小,但缺点在于使用这个方式的话就必须显式声明bean元素的init-method或destroy-method属性。显式配置有时候是必须的,例如当回调需要在开发人员控制能力之外的代码上被调用的时候。PetClinic应用程序很好地说明了这个场景。当它和JDBC配置一起运行的时候,会用到一个第三方DataSource,并且它显式声明了一个destroy-method。另外要注意到的是,单独的连接池数据源是dataSource的另一个部署选项,并且不需要修改任何代码。
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close"
p:driverClassName="${jdbc.driverClassName}"
p:url="${jdbc.url}"
p:username="${jdbc.username}"
p:password="${jdbc.password}"/>

在使用Spring2.5的过程中,如果一个对象需要调用一个初始化的回调方法的话,这个回调方法可以采用@PostConstruct来注解。例如一个假想的例子,一个后台任务需要在启动的时候就开始对一个文件目录进行轮询:
public class FilePoller {

@PostConstruct
public void startPolling() {

}

}

类似地,一个在Spring管理对象上用@PreDestroy注解的方法会在这个对象寄宿的应用程序上下文(application context)关闭的时候被调用。
public class FilePoller {

@PreDestroy
public void stopPolling() {

}

}

在添加了对JSR-250注解的支持以后,现在的Spring2.5结合前面提到的两种生命周期方法的长处。将@PostConstruct和@PreDestroy作为方法层注解加入,足可以实现在受Spring管理的上下文(context)中触发回调。换句话说,不需要另外基于XML的配置。同时,这两个注解是Java语言本身的一部分(甚至被包括在Java SE 版本6中),所以无需引入特定Spring包。这两个注解拥有在其他环境中也能理解的标识语义的优点,随着时间的推移,Java开发人员可能会发现这些注解在第三方开发库中被越来越多的运用到。最后,基于注解生命周期回调的其中一个有趣的结果是,不止一个方法可以带有这两个注解中的任何一个,并且所有注解了的方法会被调用。

激活刚刚描述的关于@Resource 、@PostConstruct和@PreDestroy注解的所有行为,正如上文提到的,需要为Spring的CommonAnnotationBeanPostProcessor提供一个bean定义。但另一个更简练的方法则可能是使用2.5中的新的context命名空间:

引入这个单个元素将不单单注册一个CommonAnnotationBeanPostProcessor,也会像下文将叙述的那样激活自动装配(autowire)行为。CommonAnnotationBeanPostProcessor也为@WebServiceRef 和@EJB注解提供支持。这些将在本文系列的第三篇中和Spring2.5为企业集成提供的其他新特性一起讨论。
利用注解来优化细粒度自动装配

涵盖Spring对自动装配支持的文档中常常会提到由于自动装配机制的粗粒度而伴随有很多限制性。Spring2.5之前,自动装配可以通过很多不同的方式来配置:构造器,类型setter,名字setter,或者自动侦测(在该方式中Spring选择自动装配一个构造器或者类型setter)。这些不同的选择确实提供了很大程度的灵活性,但它们中没有一个方法能够提供细粒度控制。换句话说,Spring2.5之前还不可能自动装配某个对象setter方法的特定子集,或者通过类型或名字来自动装配它的一些属性。结果,许多Spring用户意识到将自动装配应用到构建原型和测试中的好处,但当提到在产品中维护和支持系统时,大部分人认为,加入冗长的显式配置对于澄清它所担负的职责是非常值得的。

然而,Spring2.5大幅度地改变了布局。如上文所述,自动配置选项现在已经被扩展,支持JSR-250 @Resource注解来激活在每个方法或域基础上被命名资源的自动装配。然而,@Resource注解若单独使用的话有很多限制。因此,Sring2.5引进了一个名为@Autowired的注解进一步提高控制级别。为激活这里所讲的行为需要注册一个单独的bean定义:

另外如上文提到的,context命名空间提供了一个更简明的方法。它将激活本文所讨论的两个post-processor(AutowiredAnnotationBeanPostProcessor和CommonAnnotationBeanPostProcessor)和我们在Spring2.0中引入的基于注解的post-processor:RequiredAnnotationBeanPostProcessor和PersistenceAnnotationBeanPostProcessor。

利用@Autowired 注解可以对相应类型注入依赖。域、构造器和方法都可以激活此行为。实际上,aotowired方法并不一定要是setter方法,且可以接受多个参数。下面这个例子是完整的可接受的用法:
@Autowired
public void setup(DataSource dataSource, AnotherObject o) { … }

默认地,标有@Autowired注解的依赖被认为是必须的。然而,也可以将required属性值设置为false来声明它们中的任何一个。在下面这个例子中,DefaultStrategy只有在context命名空间中没有SomeStrategy类型的Spring管理对象时才能被使用。
@Autowired(required=false)
private SomeStrategy strategy = new DefaultStrategy();

通过类型进行的自动装配明显地在Spring context包含多于一个期望类型的对象的时候造成歧义。默认地,如果一个必须的依赖没不是恰好一个bean与之对应的话,自动装配机制就会失败。同样的,对于任何一个可选属性,如果它拥有一个以上的候选,也都会失败(如果属性可选且没有任何候选可用的话,该属性则会被简单地跳过)。有很多不同的配置选项可以避免这些冲突。

若Context中拥有一个指定类型的一个主关键实例,对这个类型定义的bean定义应该包含‘primary’属性。当Context中含有其他可用实例的时候这个方法就很适用,但那些非主关键实例总是显式配置的。

在需要更多控制的时候,任何autowired的域、构造参数、或者方法参数可以进一步加注@Qualifier注解。qualifier可以包含一个字符串值,在这种情况下,Spring会试图通过名字来找到对应的对象。
@Autowired
@Qualifier(”primaryDataSource”)
private DataSource dataSource;

@Qualifier作为一个独立注解存在的主要原因是它可以被应用在构造器参数或方法参数上,但上文提到的@Autowired注解只能运用在构造器或方法本身。
@Autowired
public void setup(@Qualifier(”primaryDataSource”) DataSource dataSource, AnotherObject o) { … }

事实上,@Qualifier作为一个单独的注解在定制化方面提供了更多的好处。用户自定义的注解在自动装配过程中也可以起到qualifier的作用,最简单的实现方式是在运用自定义注解的同时将@Qualifier作为它的元注解。
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface VetSpecialty { … }

自定义注解可以选择包含一个值来提供通过名字匹配的功能,但更普遍的用法是将它作为“标记”注解或定义一个对qualifier过程提供一些更多含义的值。例如,下面这个摘录则描绘了一个域,它应该和通过名字匹配得到的结果中合格的对象进行自动装配。
@Autowired
@VetSpecialty(”dentistry”)
private Clinic dentistryClinic;

在使用XML配置来达到依赖解析的目标时,’qualifier’ 子元素可以被加注到bean定义中。在下文的组件扫描部分,我们将呈现一个可供选择的非XML方法。


为了避免对@Qualifier注解的任何依赖性,可以在Spring context中提供一个CustomAutowireConfigurer的bean定义并直接注册所有自定义注解类型:


example.VetSpecialty

现在,自定义修饰符被显式声明了,就不再需要@Qualifier这个元注解符了。
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface VetSpecialty { … }

其实,在配置AutowiredAnnotationBeanPostProcessor的时候,取代@Autowired注解都是有可能的。

大部分情况下,定义自定义‘标记’注解的能力结合通过名字或其他文法值进行匹配选项,足以完成自动装配过程的细粒度控制。但Spring还支持在qualifier注解上任意数目的任意属性。比如,下面是一个极为细粒度修饰的例子。
@SpecializedClinic(species=”dog”, breed=”poodle”)
private Clinic poodleClinic;

自定义修饰符的实现应该定义这些属性:
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface SpecializedClinic {

String species();

String breed();

}

自定义修饰符属性可以匹配那些XML中bean定义的qualifier注解的属性子元素。这些元素通常以键/值对方式提供。





目前为止,关于autowire的描述都只是针对单独的实例,其实也支持集合。在任何需要得到所有context中某种特定类型的Spring管理对象的时候,只需要简单地在一个强类型(strongly-typed)集合上加注@Autowired 注解。
@Autowired
private List allClinics;

本章节最后一个值得指出的特性是自动装配的使用替代了Spring的Aware接口。在Spring2.5之前,如果某个对象需要一个Spring context的ResourceLoader的引用,它可以通过实现ResourceLoaderAware的方式使得Spring通过setResourceLoader(ResourceLoader resourceLoader)方法来提供该依赖。借助同样的方法可以得到Spring管理的MessageSource的引用,甚至可以得到ApplicationContext本身。对于Spring2.5用户而言,这个行为现在通过autowiring得到全面支持(需要指出的是包含这些Spring特定依赖的时候应该考虑周到,特别是它们只能用于从业务逻辑清楚地分割出来的基础构架代码中)。
@Autowired
private MessageSource messageSource;

@Autowired
private ResourceLoader resourceLoader;

@Autowired
private ApplicationContext applicationContext;

自动侦测Spring组件

从2.0版本开始,Spring引入了构造型(stereotype)注解的概念以及将@Repository注解作为数据访问代码的标记的方法。在此基础上,Spring2.5又加入了两个新的注解 —— @Service和@Controller 来完成为通常的三层架构(数据访问对象、服务、web控制器)角色委任。Spring2.5也引入了泛型@Component注解,其他构造型可从逻辑上对其进行扩展。通过清晰地指明应用程序的角色,这些构造型方便了Spring AOP和post-processor的使用,这些post-processor给基于这些角色的加了注解的对象提供了附加行为。比如,Spring2.0引入了PersistenceExceptionTranslationPostProcessor对任何带有@Repository 注解的对象自动激活其数据访问异常转换。

这些注解同样可以结合Spring2.5其他一些新性能来使用:自动侦测classpath上的组件。尽管XML已经成为最常见的Spring元数据的格式,但它决不是唯一选择。实际上,Spring容器内的元数据是由纯Java来表示的,当XML被用来定义Spring管理对象时,在实例化过程之前,那些定义会被解析并转化成Java对象。Spring2.5的一个巨大的新功能是支持从源码层注解读取元数据。因而,上文描述的自动装配机制使用注解的元数据来注入依赖,但它仍然需要注册至少一个bean定义以便提供每个Spring管理对象的实现类。组件扫描功能则使得这个XML中最起码的bean定义都不再存在需求性。

正如上面所示,Spring注解驱动的自动装配可以在不牺牲细粒度控制的前提下极大程度地减少XML的使用。组件侦测机制将这个优点更发扬光大。全面替代XML中的配置不再必要,组件扫描反而可以处理XML元数据来简化整体配置。结合XML和注解驱动技术可以得到一个平衡优化的方法,这在2.5版本的PetClinic范例中有详细阐述。在该范例中,基础构架组件(数据源、事务管理等)结合上文提到的外化属性在XML中定义。数据访问层对象也有部分在XML中定义,它们的配置也都利用了@Autowired注解来简化依赖注入。最后,web层控制器完全不在XML中显式定义,相反,下面提供的这段配置被用来触发所有web控制器的自动侦测:

需要注意到的是这段示例中使用到了base-package属性。组件扫描的默认匹配规则会递归侦测该包(多个包可以以逗号分隔的list方式提供)内的所有类的所有Spring构造型注解。正因为如此,PetClinic应用程序范例中的各类控制器的实现都采用了@Controller注解(Spring的内置构造型之一)。请看下面这个例子:
@Controller
public class ClinicController {

private final Clinic clinic;

@Autowired
public ClinicController(Clinic clinic) {
this.clinic = clinic;
}

自动侦测组件在Spring容器中注册,就像它们在XML中被定义一样。如上所示,那些对象可以轮流利用注解驱动的自动装配。

组件扫描的匹配规则可以通过过滤器(filter)来自定义,以根据类型、AspectJ表达式、或针对命名模式的正则表达式来决定包含或不包含哪些组件。默认的构造型也可以被禁用。比如这里有一个配置的例子,这个配置会忽略默认的构造型,但会自动侦测名字以Stub打头或者包含@Mock注解的所有类:



类型匹配的限制性也可以用排他的过滤器控制。例如,除了@Repository注解外其他都依赖于默认过滤器,那么就需要加入一个排他过滤器(exclude-filter)。


很明显,有很多方法可以扩展组件扫描来注册自定义的类型。构造型注解是最简单的选择,所以构造型概念本身也是可扩展的。像先前提到的,@Component是泛型模型,@Repository、@Service,和@Controller注解都从该构造型逻辑扩展而得。正因为如此,@Component可被用来作为元注解(也就是说,在另外的注解上声明的注解),所有具有@Component元注解的自定义注解都会被默认扫描匹配规则自动侦测到。一个例子就有希望让你领会到其实它根本没有听起来那么难。

让我们回想一下在讲@PostConstruct和@PreDestroy生命周期注解的时候的假想的后台任务。也许一个应用程序有很多很多这样的后台任务,这些任务实例需要XML bean定义以便在Spring context里注册并使它们自己的生命周期方法在正确时候被调用。利用组件扫描就不再需要这些显式的XML bean定义。如果这些后台任务都实现一个相同的接口或者都沿用同样的命名惯例,那么可以用include-filters。然而,更简单的方法是为这些任务对象创建一个注解并提供@Component元注解。
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface BackgroundTask {
String value() default “”;
}

然后在所有后台任务的类定义中提供自定义构造型注解。
@BackgroundTask
public class FilePoller {

@PostConstruct
public void startPolling() {

}

@PreDestroy
public void stopPolling() {

}

}

泛型@Component注解可以像例子中提供的那样简单使用,自定义注解技术则提供了一个使用更具涵义的、领域特定的名字的机会。这些领域特定注解提供更深入的机会,比如使用AspectJ切点表达式来识别所有后台任务,以便增加advice来监控这些任务的活动性。

默认的,组件被侦测到的时候,Spring会自动生成一个没有修饰符的类名作为bean名字。上一个例子中,生成的bean名字会是filePoller。但是,任何加注了Spring构造型注解(@Component、@Repository、@Service或 @Controller)或是加注了其他的以@Component作为元注解的注解(比如上面例子中的@BackgroundTask )的类,构造型注解的value属性可以被显式指定,实例将该值作为它的bean名字注册到context中。接下来的例子里,实例名应该是petClinic而不是默认生成的名字simpleJdbcClinic。
@Service(”petClinic”)
public class SimpleJdbcClinic {

}

同样的,在下面修正版的FilePoller例子里,生成的bean名字应该是poller而不是filePoller。
@BackgroundTask(”poller”)
public class FilePoller {

}

虽然所有Spring管理对象都被默认地当作单例实例来处理,但有些时候还是有必要为某个对象指明一个备用的范围(scope)。举个例子来说,在web层,一个Spring管理对象可能捆绑到request或session的范围。对于2.0版本,Spring的scope机制更具延展性,这样一来,自定义scope可以被注册到应用程序上下文(application context)。在XML配置中,仅仅是简单地包含进scope属性及该scope的名字就可以了。


Spring2.5中,为被扫描的组件提供@Scope注解可以起到同样的作用。
@Component
@Scope(”session”)
public class ShoppingCart {

}

这里要指出的最后一点是使用组件扫描时qualifier注解应用是多么的简单。在上一节,下面这个对象曾被作为使用自定义qualifier注解进行自动装配的例子:
@VetSpecialty(”dentistry”)
private Clinic dentistryClinic;

同样的例子接着展现了在XML内使用‘qualifier’元素为依赖提供指定目标bean定义。在使用组件扫描时,XML元数据不是必须的。但自定义修饰符也许在目标类定义中被作为类型层注解而引入。另一个将被扫描的@Repository实例作为依赖的例子如下:
@Repository
@VetSpecialty(”dentistry”)
public class DentistryClinic implements Clinic {

}

最终,因为前面的例子展现了自定义注解及其属性的例子,相等同的非XML表示依赖目标的方法如下:
@Repository
@SpecializedClinic(species=”dog”, breed=”poodle”)
public class PoodleClinic implements Clinic {

}
小结

Spring2.5在很多方面都提供了很有意义的新功能。本文主要关注于怎样通过掌控Java注解的力量将配置简化。就如在JSR-250中定义的那样,Spring支持公共注解(Common Annotations),同时为自动装配过程的更细粒度的控制提供了额外注解。Spring2.5也扩展了从Spring2.0的@Repository就开始的构造型(stereotype)注解,并且所有这些构造型注解都可以和新的组件扫描功能结合使用。Spring2.5仍然全面支持基于XML的配置,同时它又引进了一个新的context命名空间对常见配置场景提供更精要的文法。实际上,支持XML和基于注解配置的无缝结合最终产生一个更为平衡的全面的方法。基本构架的复杂配置可以在模块XML文件中定义,而应用程序栈日益增多地更高层配置可以更多的从基于注解的技术中获益——前提是都在同一个Spring2.5应用程序context内。

在接下来的文章中,我们将讨论到在Spring web层强大的基于注解的新功能项。敬请关注该系列的下一篇文章。
查看英文原文:What’s New in Spring 2.5: Part 1

steel stock

March 9, 2007

drop table if exists Product;

drop table if exists Spec;

drop table if exists Staff;

drop table if exists Stock;

drop table if exists Unit;

/*==============================================================*/
/* Table: Product */
/*==============================================================*/
create table Product
(
PId int not null auto_increment,
PName varchar(100) not null,
PDesc varchar(200),
primary key (PId)
);

/*==============================================================*/
/* Table: Spec */
/*==============================================================*/
create table Spec
(
SpecId int not null auto_increment,
SpecName varchar(100) not null,
primary key (SpecId)
);

/*==============================================================*/
/* Table: Staff */
/*==============================================================*/
create table Staff
(
StaffId int not null auto_increment,
StaffName varchar(50),
Password varchar(50),
primary key (StaffId)
);

/*==============================================================*/
/* Table: Stock */
/*==============================================================*/
create table Stock
(
SId int not null auto_increment,
ProductId int not null,
SpecId int,
UnitId int,
StockType int comment ‘1 入库
2 出库’,
PNumber int default 0,
PPrice numeric(12,2) default 0,
STime datetime default ‘now() ‘,
StaffId int,
primary key (SId)
);

/*==============================================================*/
/* Table: Unit */
/*==============================================================*/
create table Unit
(
UnitId int not null auto_increment,
UnitName varchar(100) not null,
primary key (UnitId)
);

TREO600以Handspring为同步名的一些注册码

February 4, 2007

TREO600以Handspring为同步名的一些注册码

请注意,要使用以下注册码,必须以Handspring为同步名
————————————————————————————————

—LauncherX—
8281282524C07CBD
______________________________

—Butler—
58528
___________________________________

—CJK—
10e7c1eae7de
__________________________
—Pocket Tunes—

ptx36520525591
_____________________________

—Butler—
58528
____________________________

—巨硬—
2069740095 1865687451
219177273 1827710726
_______________________________

—Bike—
42129
________________________________
CJK
10e7c1eae7de
________________________________

—Penp—
4OCB2ZVWL7T1
_____________________________

—TiBR—
0GOSC00000U60II00000
_____________________________
—iSilo—
TAW3-8MZN-KIP4-Z8QE
____________________________________
—Uninstall—
x45Fo2rDhYZFoD++
____________________________

—Xiino—
78900-310000-70000
________________________________

—CE—
V8N46-P84GW-U43PN-YJZFY
________________________________

—Seastrike—
ABCD-QXHY-PVMV-PDNK
_______________________________

—Ptunes3.1.1—
ptx37086202251
___________________________

LifeBalance
LBPA-1257-NURNQHL
_____________________________
BackupMan
31737897
__________________________

—Technician—
14554
_________________________

—Megabowling—
2549-3934
______________________________

—RescoExplorer—
12062
_____________________________

—Agendus—
UIB3B-UHPHJ-67PCG-HAJDJ
_______________________________

—PuzzleBobble —
49782
____________________________

—PlantTycoon —
11928
________________________________

—Astraware —
PKXC6649
________________________________

—ClipPRO—
1510
_____________________________

—mRSS —
3C07BC65
__________________________

—Penp —
4OCB2ZVWL7T1
__________________________

—Billiards—
765483297542
__________________________

—Exact—
25122110
________________________

—Wizard—
17934862
___________________________

—Monopoly—
306524
___________________________

—Resco Backup —
04950
______________________________

—Handbase—
2029 9115 3709 8302
_____________________________

—TealMaster—
BW7B BW8Z
______________________________
—BugMe—
2285
____________________________

—TealLock—
BW8D BW8Q
_____________________________

—TealLauncher—
em04 dscX
___________________________

—Adarian Money
7775517027954851
___________________________

—DTG 8.001—
4101748-5397
____________________________

—DBK6—
3CQ36C
_______________________________________________________________________________

pockettunes: ptx32500376092
megaclock: 2617-3568
isilo: QUVI-M4TO-YVXA-LABB
softtickPPP: 380A-017K-2EJF-2SEF
handbase3.0k: 2029911537098302
cardexport: anyword
comic: UM7ZZ7G3MPC874785YN3
zlauncher: 48C75AD650CC31A533A7
cjk: 9f435ee7dd60
penpower: AV0AP7T3V7OM
Crash: anywords
DTG(Reg code: 4912026-0775
Activation code: 9AF3-4A006FCA6AF0)
JACKflash: 5505
jackspart: 27897
rexcoview: anywords
___________________________________________________________________________________

PMT:24543
rescobackup:04950
butler:58528
________________________________________________________________________

AudacityPro
SN:45229
_____________________________________________________________

—–Adarian Money 3 .7 ——-
7396-5228-9779-2176
_____________________________________________________

Phone Magic 1.33
sn:
Handspring
18lbn4ft

___________________________________________________________________

SnapperMail 2.3.3.04
提供一组注册帐号试用:
同步名:Handspring
注册码:1859f81e
___________________________________________________________

profilecare 49989 60337
_____________________________________________________

LightwavPRO v1.4

sn:
Handspring
4088sur

redhat bonding

October 19, 2006

参考 http://www.redhat.com.cn/kbase/6313.php
vi /etc/modprobe.conf
install bond0 /sbin/modprobe bonding -o bond0 miimon=100 mode=1

vi /etc/sysconfig/network-scripts/ifcfg-bond0
DEVICE=bond0
BOOTPROTO=none
ONBOOT=yes
NETWORK=192.168.0.0
NETMASK=255.255.255.0
IPADDR=192.168.0.10
USERCTL=no

vi /etc/sysconfig/network-scripts/ifcfg-eth0
DEVICE=eth0
BOOTPROTO=none
ONBOOT=yes
MASTER=bond0
SLAVE=yes
USERCTL=no

vi /etc/sysconfig/network-scripts/ifcfg-eth1
DEVICE=eth1
BOOTPROTO=none
ONBOOT=yes
MASTER=bond0
SLAVE=yes
USERCTL=no

service network restart

pg_restore

August 31, 2006

./pg_restore -i -U postgres -d Jedi_Storage -c Jedi_Storage.backup
-a
–data-only
只恢复数据,而不恢复表模式(数据定义)。
-c
–clean
创建数据库对象前先清理(删除)它们。
-C
–create
在恢复数据库之前先创建它。(如果出现了这个选项,和 -d 在一起的数据库名只是用于发出最初的CREATE DATABASE命令。 所有数据都恢复到名字出现在归档中的数据库中去。)
-d dbname
–dbname=dbname
与数据库 dbname 联接并且直接恢复到该数据库中。
-e
–exit-on-error
如果在向数据库发送 SQL 命令的时候碰到错误,则退出。 缺省是继续执行并且在恢复结束时显示一个错误计数。
-f filename
–file=filename
声明生成的脚本的输出文件,或者出现-l 选项时用于列表的文件,缺省是标准输出。
-F format
–format=format
声明备份文件的格式。因为pg_restore 会自动判断格式,所以如果声明了,它可以是下面之一:
t
备份是一个 tar 归档。 使用这个格式允许在恢复数据库的时候重新排序和/或把表模式元素排除出去。 同时还可能在恢复的时候限制装载的数据。
c
备份的格式是来自pg_dump的客户化格式。 这是最灵活的格式,因为它允许重新对数据排序,也允许重载表模式元素。 缺省时这个格式是压缩的。
-i
–ignore-version
忽略数据库版本检查。
-I index
–index=index
只恢复命名的索引。
-l
–list
列出备份的内容。这个操作的输出可以用 -L 选项限制和重排所恢复的项目。
-L list-file
–use-list=list-file
只恢复在 list-file 里面的元素,以它们在文件中出现的顺序。 你可以移动各个行并且也可以通过在行开头放 ‘;’ 的方式注释。(见下文获取例子。)
-O
–no-owner
不要输出设置对象的权限,以便与最初的数据库匹配的命令。 缺省时,pg_restore 发出 ALTER OWNER 或 SET SESSION AUTHORIZATION 语句设置创建出来的模式元素的所有者权限。 如果最初的数据库连接不是由超级用户(或者是拥有所有创建出来的对象的同一个用户)发起的,那么这些语句将失败。 使用 -O,那么任何用户都可以用于初始的连接,并且这个用户将拥有所有创建出来的对象。
-P function-name(argtype [, …])
–function=function-name(argtype [, …])
只恢复指定的命名函数。请注意仔细拼写函数名及其参数,应该和转储的内容列表中的完全一样。
-R
–no-reconnect
这个选项已经废弃了,但是为了保持向下兼容仍然接受。
-s
–schema-only
只恢复表结构(数据定义)。不恢复数据,序列值将重置。
-S username
–superuser=username
设置关闭触发器时声明超级用户的用户名。 只有在设置了 –disable-triggers 的时候才有用。
-t table
–table=table
只恢复表指定的表的定义和/或数据。
-T trigger
–trigger=trigger
只恢复指定的触发器。
-v
–verbose
声明冗余模式。
-x
–no-privileges
–no-acl
避免 ACL 的恢复(grant/revoke 命令)。
-X use-set-session-authorization
–use-set-session-authorization
输出 SQL 标准的 SET SESSION AUTHORIZATION 命令,而不是 OWNER TO 命令。 这样令转储与标准兼容的更好,但是根据转储中对象的历史,这个转储可能不能恰当地恢复。
-X disable-triggers
–disable-triggers
这个选项只有在执行仅恢复数据的时候才相关。它告诉 pg_restore 在装载数据的时候执行一些命令临时关闭在目标表上的触发器。 如果你在表上有完整性检查或者其它触发器, 而你又不希望在装载数据的时候激活它们,那么可以使用这个选项。
目前,为 –disable-triggers 发出的命令必须以超级用户发出。 因此,你应该也要用 -S 声明一个超级用户名,或者更好是设置 –use-set-session-authorization 并且以 PostgreSQL 超级用户身份运行 pg_restore。

pg_restore 还接受下面的命令行参数做为联接参数:
-h host
–host=host
声明服务器运行的机器的主机名。 如果数值以斜杠开头,那么它被用做 Unix 域套接字的目录。 缺省是从 PGHOST 环境变量中获取的(如果设置了), 否则将尝试进行 Unix 域套接字。
-p port
–port=port
声明服务器侦听的 TCP 端口或者本地的 Unix 域套接字文件扩展。 缺省是环境变量 PGPORT 的值(如果设置了的话), 否则就说编译的缺省。
-U username
以给出用户身分联接。
-W
强制给出口令提示。如果服务器要求口令认证,那么这个应该自动发生。

INIT: Cannot create /var/adm/utmp

August 30, 2006

INIT: Cannot create /var/adm/utmp or /var/adm/utmpx
===================================================

This console message indicates that init(1M) cannot write in the
/var directory, which is usually part of the / (root) filesystem.
Some other messages follow, andthe system usually comes up
single-user. The problem is often that / or /var is mounted
read-only. Sometimes a brief power outage leaves the system
believing that many filesystems are still mounted.

If /var is a separate filesystem on the machine, andis not yet
not mounted, mount it now. If the filesystem containing /var is
mounted read-only, remount it read-write with a command similar
to this:

# mount -o rw,remount /

Then type Control-d and try to bring up the system multi-user. If
that fails, the root filesystem is probably corrupted. Run
fsck(1M) on the root filesystem, halt the machine, power cycle
the CPU, and wait for the system to reboot. Should this problem
still occur, restore the root filesystem from backup tapes, or
re-install the system from net or CDROM to replace the root
filesystem.

裸设备问答汇总 转载

August 29, 2006

裸设备问答汇总
【2006-08-17 15:06】【IT专家网】【网络整理】

  1.什么叫做裸设备?   
裸设备,也叫裸分区(原始分区),是一种没有经过格式化,不被Unix通过文件系统来读取的特殊字符设备。它由应用程序负责对它进行读写操作。不经过文件系统的缓冲。

  2.如何辨别裸设备?
  在Unix的/dev 目录下,有许多文件,其中有两个大类:字符设备文件和块设备文件。
  字符设备特殊文件进行I/O操作不经过操作系统的缓冲区,而块设备特殊文件用来同外设进行定长的包传输。字符特殊文件与外设进行I/o操作时每次只传输一个字符。而对于块设备特殊文件来说,它用了cache机制,在外设和内存之间一次可以传送一整块数据。裸设备使用字符特殊文件。在/dev 目录下,你可以看到许多这样的文件。

  3.使用裸设备的好处
  因为使用裸设备避免了再经过Unix操作系统这一层,数据直接从Disk到Oracle进行传输,所以使用裸设备对于读写频繁的数据库应用来说,可以极大地提高数据库系统的性能。当然,这是以磁盘的I/O 非常大,磁盘I/O已经称为系统瓶颈的情况下才成立。如果磁盘读写确实非常频繁,以至于磁盘读写成为系统瓶颈的情况成立,那么采用裸设备确实可以大大提高性能,最大甚至可以提高至40%,非常明显。
  而且,由于使用的是原始分区,没有采用文件系统的管理方式,对于Unix维护文件系统的开销也都没有了,比如不用再维护I-node,空闲块等,这也能够导致性能的提高。

  4.如何决定是否应该使用裸设备?
  判断是否使用裸设备要从以下方面进行考虑:首先,数据库系统本身需要已经被比较好的经过了优化。优化是一门很有些技术的话题,很难简单地讲述。其次,使用Unix命令来辨别是否存在磁盘读写瓶颈。比如Unix的vmstat, sar 等命令都可以较好的进行鉴别。如果决定采用裸设备,需要磁盘上还有空闲的分区。否则,就要新添磁盘,或者对原有系统重新规划。

  5.什么系统必须使用裸设备?
  如果使用了Oracle 并行服务器选项,则必须采用裸设备来存放所有的数据文件,控制文件,重做日志文件。只有把这些文件放到裸设备上,才能保证所有Oracle 实例都可以读取这个数据库的文件。这是由Unix操作系统的特性决定的。
  还有一种情况是,如果你想使用异步I/O,那么在有些Unix上也必须采用裸设备。这个需要参考具体Unix的相关文档。

  6.能够使用一个磁盘的第一个分区作为裸设备吗?
可以,但是不推荐。在Unix的比较旧的版本是银行,磁盘的第一个分区常常包含这个磁盘的一些信息,以及逻辑卷的一些控制信息。若这些部分被裸设备覆盖的话,磁盘就会变得不可识别,导致系统崩溃。
  较新的Unix版本不会发生这样的情况,因为它们采用了更复杂的技术来管理磁盘,逻辑卷的一些信息。   但是,除非很确信不要使用磁盘的第一个分区来作为裸设备。

  7.我可以把整个裸设备都作为Oracle的数据文件吗?
  不行。必须让数据文件的大小稍微小于该裸设备的实际大小。至少要空出两个oracle块的大小来。

  8.裸设备应该属于那个用户?
   应该由root来创建裸设备,然后再分配给Oracle用户以供使用。同时还要把它归入Oracle用户所在的那个组里边(通常都是DBA)。

  9.在创建数据文件时如何指定裸设备?
   和普通文件没有什么太大的区别,一样都是在单引号里边写上裸设备的详细路径就可以了。举一个例子:要在创建一个表空间,使用两个裸设备,每个分别为30M的大小,Oracle块的大小为4K,可以用下面的命令:
  CREATE TABLESPACE RAW_TS
  DATAFILE /dev/raw1 size 30712k
  DATAFILE /dev/raw2 size 30712k;

  10.Oracle块的大小和裸设备有什么关系吗?
  Oracle会必须是裸设备上物理块大小的倍数。

  11.如何在裸设备上进行备份?
  在裸设备上,不能使用Unix实用程序来进行备份,唯一的办法是使用最基本的Unix命令:DD来进行备份。比如:dd if=/dev/raw1 of=/dev/rmt0 bs=16k。dd的具体语法可以参考unix手册,或者联机帮助。你也可以先用dd把裸设备上的数据文件备份到磁盘上,然后再利用Unix实用程序进一步处理。

  12.如果我没有使用Oracle并行服务器选项,我可以在数据库上让一部分数据文件使用文件系统,另一部分使用裸设备吗?
  可以。但是这样的话,会使备份过程更加复杂。

  13.我应该把联机重做日志文件放到裸设备上吗?
  这是一个极好的选择。联机重做日志文件是写操作非常频繁的文件,放到裸设备上非常合适。如果你使用了并行服务器选项,那么联机重做日志文件必须放到裸设备上面。

  14.可以把归档日志文件放到裸设备上吗?
  不行。归档日志文件必须放到常规的Unix文件系统上面,或者直接放到磁带上面去。

  15.我可以在裸设备上边放置多个数据文件吗?
  不行。所以你必须在设置裸设备时非常小心。太小的话,会导致空间很快用完,太大的话,空间就白白浪费了。

  16.因应该把几个裸设备放到同一个物理磁盘上吗?
  这样做不好。因为使用裸设备就是为了提高磁盘读写速度。而把多个裸设备放到同一个物理磁盘上会导致读写竞争,这样对于提高I/O速度是不利的。应该尽量分散裸设备到不同的物理磁盘上,最好是分散到不同的磁盘控制器上。这是最佳选择。

  17.需要把所有裸设备都定义成同样的大小吗?
  这不是必须得,但是划分成同样的大小对于管理数据库比较有利。

  18.为了在Unix上使用裸设备,我需要改变Unix核心参数吗?
  不需要。但可以选择减小缓冲区的大小,如果没有别的应用也在同一台Unix机器上运行。因为运用了裸设备以后,不再使用Unix的系统缓冲区。

  19.为了提高读写速度,在操作系统级别上,还有什么办法可以采取吗?
  使用RAID(廉价冗余磁盘阵列)也是非常有效的办法,尤其实那种读写非常频繁的系统。

  20.在考虑了以上所有方面后,还能有什么办法可以提高性能的吗?
  这就需要对Oracle 进行优化,并且购买更多的磁盘和磁盘控制器,来分散I/O到不同的磁盘上。

Mahler Das Lied Von Der Erde

August 17, 2006

Mahler 马勒 -《大地之歌》(Das Lied Von Der Erde)Barenboim, CSO[APE] | 音乐 → 经典音乐 | VeryCD → 下载