日期:2014-05-16  浏览次数:20337 次

JSF的加减法与Seam(二)之对java的改进
引用

题记:Seam对开发的简化,对各种不同软件的统一能力,我想其主要来源不是创造了conversation域,不是使用了元注解,不是依赖于JSF,不是使用了反射机制,而是一种更加全局的域管理机制。那些其它因素都是为了这一目的服务的,或多或少的使这一目的的实现变得更加方便可靠。如果说Seam有什么决定性的区别于其它框架的东西,那就是它的全局域管理机制。

说明:1楼和2楼铺垫了很多基础的东西。如果没有耐性,可以把它们略过去,直接从第3楼读起。
另: 文章里的命,生命周期(lifecycle),上下文(context),域(scope)在这里指同一内容,可以互相替换。


不说Seam诞生的大环境和Seam产生的语言基础,只是说Seam本身的功能,大概也可以,不过我认为非常多的外在功能都只是某些环境外在因素和基本内在因素所决定了的。大环境和内在可能定了之后,细节的东西只是做就可以了。所以没有办法,还是得绕开Seam本身说些题外话。

JSF的加减法与Seam(一)http://www.iteye.com/topic/137027大概说了一下 Seam诞生的环境,这是外在机会,是融合各种技术的可能性,是广的纬度。 这篇文章说说java上的可能性,是何让Seam具有了融合的本事,是内在能力,从深的纬度上说吧。

其实也不深,因为说JAVA,其实得从最基本的说起:

1. Java 对象的命

1.1 概述
这个命呢,就是生命周期,就是什么时候生下来可以用它,什么时候死了不能再用了。一个对象在内存中的时间和生命周期是不一定相等的,因为即使一个对象完全没有办法再用了,它仍然可能还在内存里。比如
void doIt() {
Object o = new Object();
o = null;
}

这个方法执行完了之后,o是没办法再用了,但是o可能仍然还在内存里,因为内存的垃圾回收有延时,术语叫做best effort,意思就是我尽我最大能力去回收了,但是回收回得来回不来,得看情况。这篇文章里说到的生命周期,是不考虑这个延时的,如果我没有办法再用这个对象了,我就认为它已经死掉了。

1.2 假如无状态
我举一个非常理想化的例子,假如java的所有的对象的都不能有状态,那对生命周期会有什么影响呢?
如果没有状态,那么所有对象都只能用方法调用。假设我有类A,B,C;而a,b,c是它们的对象。底下老这么说费事,凡是大写都是类,凡是小写都是对象。而a.getB()则假设a有属性b并且有它的getter和setter方法。
如果所有对象的状态不能改变,则只能是这样:

public static void main() {
  A a = new A();
  a.doSomthing();
}
class A() {
  doSomething() {
    B b = new B();
    b.doSomething();
  }
}
class B() {
  doSomehing() {
    C c = new C();
    c.doSomething;
  }
}


每个对象都得在某个方法里被创建(出生),而且必须在那个方法内被销毁(死亡)。那么所有的对象的生命都是和调用它的方法一样长的。这样产生了一个现象就是所有的被调用的对象一定比调用它的对象的命短,而且它出生于调用它的对象出生之后,死亡于调用它的对象死亡之前。 我们把一段生命周期称为“域”,则前者存在的域一定被包含在后者存在的域中。
如何断定的呢? 因为调用者的那个方法的域(也就是命,也就是生命周期)一定包含于调用者本身存在的域──因为任何时候我调用那个方法,拥有该方法的那个对象一定存在,否则该方法也就不能存在了(静态方法是特殊情况等会再说)。而被调用者存在的域一定被包含在调用者方法的域中,这刚才已经讨论了。所以:
对于任意 a通过它的方法doXYZ()来调用b来说:
b的域 包含于(被包含)  doXYZ()的域,  而 doXYZ() 的域 包含于 a的域。
由此可知 b的域包含于a的域。
以此类推,如果a调用b,b调用c,c调用d…… 那么后者的域总是被包含在前者的域里,也就是说越成为被调用者,命越短,越成为调用者,命越长。且被调用者存在时,调用者必然存在。
8 楼 d2up 2007-11-06  
分析得很不错,看了觉得有点矛塞顿开的感觉。
9 楼 zaya 2007-11-06  
dingyuan 写道

spring有生命周期的概念吧。。。spring容器管理对象的创建和消亡。。。。
我感觉最近多了很多seam的抢手啊



呵呵,那我就是其中之一了。

其实很多框架都有生命周期的概念,但是Seam所有的是“更全局化”的生命周期管理。

就像在Spring之前就已经有了反射机制,但是是Spring的大规模使用反射,才使EE世界向轻量级转变;在Seam之前也早已经有了生命周期管理,但是Seam对生命周期管理的大规模使用,同样会引发编程模式的变革。

新的东西往往未必最好,用得最好方是最好。


nihongye 写道
这么多种context,有点恐怖。虽然解决一些问题,但整个系统失去简单性。

正常使用,request,session,application,conversation就可以了。 前三个域别得系统都有,第四个域可以解决一些其它框架不能解决的问题,比如hibernate的OSIV问题,比如可以对浏览器的每个Tab分别保存状态,比如可以在一个用户session里面放置多个并行且相互独立的状态线,并且可以在这些状态线间随意切换,比如可以把对数据库的访问作更有效的缓存,减少hit。
10 楼 zaya 2007-11-06  
3.1.3 接口即类

在软件开发的时候,往往很难决定一项功能究竟是做成实实在在的类,还是做成接口以防以后的扩展或者替换。做成类得话能省去很多麻烦,但是会造成依赖它的类对该类的signature(类名,方法名等等)有绑死的依赖。如果被依赖类被非常多的类依赖得话,以后万一想作改动就会造成大面积的牵动。而如果对每个子功能都作成接口得话,则会大大增加系统的复杂度。

在以往应用的做法中,一般是只把预计以后可能变动的功能提出来被接口(或抽象类)封装,而对可能不会发生变动的功能就使用直接类的方式。这种方式是在过去的编程模式下比较好的一种折衷,但是它也有弊端。人的预计能力是有限的,很常见预计变动的功能最后没有变动,而预计不大可能发生变动的功能结果最后却发现需要替换。

在全局域管理下,有一种新的更方便的解决方法。对于代码:
@Name("config")
public class Config {
    @In Parser parser;
    private List<Module> modules;
    public void loadParser(){
        modules = parser.parser()
    }
    public String get(String moduleName, String configName) {
        //通过指定配置模块的名称和配置项的名称来查找某个配置的设定
    }
}

@Name("parser")
public class