Posts Tagged ‘技巧’

在seam中使用spring

July 17th, 2008

选择seam并不代表要放弃spring, 两者并不互斥,相反,可以很好的协作。seam对spring提供了很好的兼容性。那么在seam里如何使用spring里的代码呢?

POJO代码的重用

正如spring管理的bean是POJO一样,seam管理的组件,也是POJO的,而且连ejb3也是POJO的,所以直接的重用以前用在 spring里的代码的方法,就是直接重用POJO了。以前我们就applicationContext.xml来配置bean,现在只需要换一个语法就 能把spring的POJO bean变成seam的component。例如,对于spring的bean:

<bean id=”testBean” class=”org.test.TestBean”>
<property name=”stringProperty” value=”this is a string” />
<property name=”intProperty” value=”3″ />
<property name=”anotherBean” ref=”anotherBean” />
</bean>

对应到seam里就是:

<component name=”testBean” class=”org.test.TestBean”>
<property name=”stringProperty”>this is a string</property>
<property name=”intProperty”>3</property>
<property name=”anotherBean”>#{anotherBean}</property>
</component>

大部分的POJO可能这就可以搞定了。但是要注意:
假如这个POJO依赖于spring容器,比如它实现了spring的bean生命周期回调方法,类似于  afterPropertiesSet() , 那么你也得让seam去模仿spring容器,在适应的时候,去调用这些回调方法。比如:

public class TestBeanAdapter extends TestBean {
@Create
public void afterPropertiesSet() {
super.afterPropertiesSet();
}
}


通JSF EL Resolver来桥接

只要实现了EL Resolver, 并在faces-config.xml里注册它,那么在JSF里使用EL表达式时,就会自动地调用EL Resolver来寻找这个EL表达式对应的对象等。seam当然实现了它自己的Resolver,而spring也实了这个Resolver,如果把它 们都注册上,那么JSF EL 将变成seam与spring的一座桥梁。用下面代码注册spring EL Resolver:

<faces-config>
<application>         
<el-resolver>
org.springframework.web.jsf.el.SpringBeanFacesELResolver 
</el-resolver>
</application>
</faces-config>

如果你定义了spring bean testBean, 那么在seam组件里,你就可以通过 @In(“#{testBean}”) 来注入spring的bean。但是要记住,这种方法获得的对象,完全是由spring负责组装的地地道道的spring的bean, 所以它不具有seam component具有功能,比如双向注入,和seam的上下文完美一体,延长的持久化上下文(extended persistence context)。

seam里的spring

最完美的方案,我想你也想到了,就是让seam来管理spring容器,并加入seam的增强功能。这是可以做得到的,并且已经做到了,感谢spring的灵活性,和seam开发者们的努力。像下面那样在conponents.xml里加入spring名称空间:

<components xmlns=”http://jboss.com/products/seam/components”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xmlns:spring=”http://jboss.com/products/seam/spring”
xsi:schemaLocation=”
http://jboss.com/products/seam/components
http://jboss.com/products/seam/components-2.0.xsd
http://jboss.com/products/seam/spring
http://jboss.com/products/seam/spring-2.0.xsd”>
<!– component declarations –>
</components>

现在你可以在components.xml里使用<spring:context-loader />了:

<spring:context-loader>
<spring:config-locations>
<value>classpath:spring-beans-persistence.xml</value>
<value>classpath:spring-beans-service.xml</value>
</spring:config-locations>
</spring:context-loader>

好了,现在当你启动seam时,seam便会到你指定的位置去寻找spring的配置,并起动一个spring容器。为了能让seam知道要如何增强 spring里的bean,我们需要在spring那边做一些手脚。在spring的配置文件里加入seam的名称空间如下:

<beans xmlns=”http://www.springframework.org/schema/beans”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xmlns:seam=”http://jboss.com/products/seam/spring-seam”
xsi:schemaLocation=”
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://jboss.com/products/seam/spring-seam
http://jboss.com/products/seam/spring-seam-2.0.xsd”>
<!– bean definitions –>
</bean>

这样,你就可以在spring的配置文件里使用以下三种元素来定义如何增强spring bean了:

  1. <seam:conponent />  把一个spring bean变成seam component
  2. <seam:instance> 向一个spring bean里注入seam component
  3. <seam:configure-scopes> 定义一些默认的配置

看看下面的使用举例,我想你根本不需要解释就明白了:

<bean id=”aBean” class=”org.test.TestBean” scope=”prototype”>
<property name=”aString” value=”a string” />
<seam:component name=”testBean” scope=”CONVERSATION” auto-create=”true” />
</bean>

<bean id=”anotherBean” class=”org.test.AnotherBean” scope=”prototype”>
<property name=”aBean”>
<seam:instance name=”testBean” />
</property>
</bean>

<seam:configure-scopes default-auto-create=”true”/>

spring的 aBean在seam里被叫做 testBean, 并且它在 conversation scope里,spring的anotherBean在创建它时,会把testBean注入进去。非常简单吧?

但是,在使用过程中,要注意,seam不能对spring通过jdk 动态代理增强过的类进行再增强,所以如果要让一个spring的bean参予到seam里来,就不要对它使用动态代理的方式来实现AOP,你需要在spring的配置文件里做如下配置:

<aop:config proxy-target-class=”true”>
……
</aop:config>

好了,至此,在seam中使用spring的方法就介绍完了。

  • Share/Bookmark

十六个快捷键让你用eclipse写java如飞一般

January 17th, 2008

常用快捷键

熟练使用快捷键,加速编码速度:

  1. CTRL + 1 智能提示和代码修正
  2. ALT + / 代码补全
  3. CTRL + o 快速显示类里的成员
  4. CTRL + e 快速选取当前打开的文件
  5. CTRL + l 转到指定行
  6. F3 转到代码声明定义部分
  7. CTRL + t 显示类型继承树
  8. CTRL + d 删除,连换行符一起删掉
  9. CTRL + f 文档内的查找与替换
  10. CTRL + h 全工作空间内的查找与替换
  11. CTRL + / 注释选中代码
  12. CTRL + SHIFT + o 自动导入修正
  13. CTRL + SHIFT + r 打开文件
  14. CTRL + SHIFT + t 打开类型
  15. ALT + SHIFT + r 重命名
  16. ALT + SHIFT + m 移动
  • Share/Bookmark

当return遇到finally

December 24th, 2007

猜猜下面java程序分别会有什么样的输出?

程序:

public class Test {

    public static void main(String[] args) {
        System.out.println("=============test1==================");
        System.out.println(test1());
        System.out.println("===============================");

        System.out.println("=============test1_1==================");
        System.out.println(test1_1());
        System.out.println("===============================");

        System.out.println("\n============test2===================");
        System.out.println(test2());
        System.out.println("===============================");

        System.out.println("\n============test2_1===================");
        System.out.println(test2_1());
        System.out.println("===============================");

        System.out.println("\n============test3===================");
        System.out.println(test3());
        System.out.println("===============================");

        System.out.println("\n============test3_1===================");
        System.out.println(test3_1());
        System.out.println("===============================");
    }

    public static String test1() {
        String a = "in try";

        try{
            return a;
        } catch ( Exception e ) {

        } finally {
            a = "in finally";
            System.out.println("do finally");
        }

        return a;
    }

    public static String test1_1() {
        String a = "in try";

        try{
            return a;
        } catch ( Exception e ) {

        } finally {
            a = "in finally";
            System.out.println("do finally");
            return a;
        }
    }

    public static int test2() {
        int a = 1;

        try{
            return a;
        } catch ( Exception e ) {

        } finally {
            a = 2;
            System.out.println("do finally");
        }

        return a;
    }

    public static int test2_1() {
        int a = 1;

        try{
            return a;
        } catch ( Exception e ) {

        } finally {
            a = 2;
            System.out.println("do finally");
            return a;
        }
    }

    public static Helper test3() {
        Helper a = new Helper();
        a.a = 1;

        try{
            return a;
        } catch ( Exception e ) {

        } finally {
            a.a = 2;
            System.out.println("do finally");
        }

        return a;
    }

    public static Helper test3_1() {
        Helper a = new Helper();
        a.a = 1;

        try{
            return a;
        } catch ( Exception e ) {

        } finally {
            a.a = 2;
            System.out.println("do finally");
            return a;
        }
    }

    static class Helper {
        int a;

        public String toString() {
            return String.valueOf(a);
        }
    }
}

结果:

=============test1==================
do finally
in try
===============================
=============test1_1==================
do finally
in finally
===============================

============test2===================
do finally
1
===============================

============test2_1===================
do finally
2
===============================

============test3===================
do finally
2
===============================

============test3_1===================
do finally
2
===============================

结论:

  1. 在try catch块里return的时候,finally也会被执行。
  2. return 语句会把后面的值复制到一份用来返回,如果return的是基本类型的,finally里对变量的改动将不起效果,如果return 的是引用类型的,改动将可以起效果。
  3. finally里的return语句会把try catch块里的return语句效果给覆盖掉。

看来return语句并不一定都是函数的出口,执行return时,只是把return后面的值复制了一份到返回值变量里去了。看来最佳实践是:

  1. 最好把return放到方法尾而不要在try cath 里return
  2. 不要在try catch块和finally块里都包含return
  3. 如果在try catch块里return, 则不要在finally块里操作被return的变量
  • Share/Bookmark