论坛首页 Java企业应用论坛

关于设计一个容器过程中碰到的问题

浏览 10388 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2004-08-30  
在提出我的问题之前,先介绍一下问题的起因:


最近在写一个玩具叫做Jink Container,包括:
AOP框架,组件工厂,持续化层 等等。
此外,还有一个Security Module,和容器紧密结合,提供可自定义的安全控制。

使用这样的容器,编写B.O.就可以这样写:
(以下方法Copy自我的Demo App,是真实可运行的):

package demo;

import ...;
import ...;
import ...;
/**
 * <p>
 * </p>
 * 
 * <p>Copyright: Copyright (c); 2003-2004 NonSoft.com</p>
 * 
 * @author Shawn Chain
 * @version 2.0, rev $Revision: 1.5 $
 * 
 * @@InterceptorAttribute(name="com.nonsoft.aop.interceptor.CacheInterceptor",index=1,param="method=setName");
 * @@InterceptorAttribute(name="com.nonsoft.aop.interceptor.StoreInterceptor",index=2,param="method=set*|addMember");
 * @@ProxyAttribute(apply=true);; 
 */

public class Group implements BusinessObject{

  private GroupEntity entity = null;
  public Group();{
  }
  protected Group(GroupEntity entity);{
    this.entity = entity;
  }
  ...
  
  /**
   * @@CacheAttribute(type="demo.Group",value="this",action="invalid"); 
   * @@PersistenceAttribute("write");
   * @param name
   */
  public void setName(String name);{
    entity.setName(name);;
  }

  /**
   * @param user
   * @@PersistenceAttribute("write");;
   */
  public void addMember(User user);{
    User u = user;
    entity.getUsers();.add(u.getEntity(););;
  }
}


看到这里,也许有人会打断说,这样配置很麻烦,这个帖子先不讨论配置和注解的问题,请继续往下看再说。

上述Group.setName()和addMember()方法, 都可以自动的保存Entity,界面的Action也是非常的简洁的:

测试代码如下:
public void testAddGroupMember();throws Exception{

    ComponentContainer cc = ComponentContainer.getInstance(null);;    
    cc.registerComponentImplementation(UserManager.class,UserManager.class);;
    userManager = (UserManager);cc.getComponentInstance(UserManager.class);;        

    User user = userManager.getUser(new Long(10););;
    Group group = userManager.getGroup(new Long(10););;
    group.addMember(user);;
    
    // Check the calling object
	......    
  }

测试代码的前6行应该就是在界面Action中的主要代码了。


以上所有的功能都可以通过DynamicProxy来完成!

我目前的具体实现是:通过CGLib的DP,容器对构造出来的每一个BO Instance都会进行自动的进行wrap,每个DP instance都有一个Interceptor Chain,由这些Interceptor来完成诸如透明事务/Cache/Security等方面的事情。

比如我UesrManager.getGroup(Long)构造了一个Group Instance,但是Action代码中的Group其实是CGLib生成的一个Group的D.P. instance,因为userManager.getGroup()被我的ProxyInterceptor所拦截,自动的给Group Instance加上了Proxy,这样,所有的针对Group的调用,都会被
拦截,并且依次调用预先定义好的Interceptor Chain来完成各自的工作。
这里可能你又要打断说,这样效率是不是很差?也许你是对的,但是这里也先不讨论这个问题,请继续往下看。

到这里,我们可以想象出来,系统中,所有的B.O.组成了一个对象图,而由于Proxy Interceptor的作用,在这个对象图之外,各自的D.P. 又组成了一个Proxy的对象图!Proxy对象图是包裹在BO对象图外面的。

OK,感谢你有耐心读到这里,我提出我第一的问题:

如果B.O.(比如Group)的某个方法中调用了其他B.O.(比如User)的方法

就好比上面的Group.addMember(User)方法,可以肯定,Action代码中调用addMemeber()的时候传进来的user一定是一个DP,但是我们在编写addMember这个函数体的时候,思考的level应该是在第一个对象图层次上(这里我认为userManager不应该考虑是否有包裹层在外面,因为interceptor可以自由配置,即aspect instance是完全有可能事后绑定到pointCut的,如果我们在addMember中允许User的D.P. instance 传递进来,那就等于说,我们在编写addMember()的时候,就已经要“预先”考虑到了user.setFoo()上的interceptor会执行且必须执行什么操作了,如果事后Aspect配置文件一改变,除了影响user的行为,还影响到了group的行为,推想开去,配置文件一个小改动,都有可能影响整个系统的行为,甚至导致系统的瘫痪
),但是如果是Group的原始实例的话,在addMember()中调用的user.setFoo()又是一个功能上不完整的一个方法,不具备独立成为一个业务方法的资格,那么在addMember方法中的user应该是D.P. instance呢?还是unwrapped instance ??

假如说addMember这么写:
  public void addMember(User user){
    User u = user;
    entity.getUsers().add(u.getEntity());
    user.setFoo("Foo_Bar");
  }
  这里user.setFoo的场景和单纯的在Action中调用user.setFo()很有可能是不一样的,也许在Group.addMember()方法中,对于user.setFoo的要求是不需要自动保存,而对于Action中的调用场景来说,user.setFoo()是需要自动保存的,而也许对于其他的某个Bar.xxx(User)方法中,对user.setFoo()又是需要自动保存的了。

想听听大家的意见,你觉得addMember(User user)这样的方法中,user应该是怎样一个对象呢,一个经过容器增强的DP instance,还是一个干净的未经过容器处理的Group Instance ?
   发表时间:2004-08-30  
难道你拉拉喳喳了一堆, 就是在问:

因为StoreInterceptor + cascade update的作用, 所以在addMember中的user.set*是不需要被自动保存的, 而在其他应用中, user.set*又是有可能需要被StoreInterceptor 自动处理的?
0 请登录后投票
   发表时间:2004-08-30  
Readonly 写道
难道你拉拉喳喳了一堆, 就是在问:

因为StoreInterceptor + cascade update的作用, 所以在addMember中的user.set*是不需要被自动保存的, 而在其他应用中, user.set*又是有可能需要被StoreInterceptor 自动处理的?


group.addMember和user.setFoo()只是一个例子,请原谅我的概括能力的低下。

我想我的问题应该是:上述应用中,调用一个业务对象的方法,必须是aspect + bo method 结合起来才是一个真正有效的business method。但是如果bo对象之间互相调用的时候,按照我对DP和AOP的理解,被调用的bo(即group.addMember(User)方法中的user)应该unwrapped instance,这样aspect是不起作用的,而不起作用的bo method又不能成为一个完整的business method,这个矛盾如何解决?还请大家出出主意。
0 请登录后投票
   发表时间:2004-08-30  
AOP不是应该可以定义aspect的作用范围么(within/out method)?

不过, 用DP好像不能简单地做到这一点吧?

会的人继续了, 别理会偶这个AOP的抵制者.
0 请登录后投票
   发表时间:2004-08-30  
我没有用过Spring,Spring好象是用nanning的把?nanning好象是用CGLib的吧? 所以如果有谁用过Spring中的declarative security/transaction的,并且熟悉其中实现原理的,请给我一些实现上的提示,thanx。
0 请登录后投票
   发表时间:2004-08-30  
spring的aspect是自己做的一套东西。
0 请登录后投票
   发表时间:2004-08-30  
这个地方我认为,不应该纠缠于bo是否增强上,如果对这个有什么疑虑的话,问题就可能太复杂了,增强带来的副作用超出了其贡献的好处,AOP就是要显示出不耦合的效果才好。
如果实在需要解决问题最好对照设计需要的功能仔细考量可能才能有答案。看你的框架功能实在是“太强大”了,我大概是对付不了的,呵呵:)
0 请登录后投票
   发表时间:2004-08-31  
如果需要保存,你就传入自动保存的user,否则就传递进去不需要保存的。

你不能决定传递进去的实例是哪一个吗?
0 请登录后投票
   发表时间:2004-09-01  
ajoo 写道
如果需要保存,你就传入自动保存的user,否则就传递进去不需要保存的。

你不能决定传递进去的实例是哪一个吗?

针对不同的业务情况,我完全可以确定需要哪种类型的user,我可以通过定义一个新的注解,很方便的让AOP框架自动完成。这也是我目前使用的办法。
0 请登录后投票
   发表时间:2004-09-02  
作为一个容器,你认为这是一个什么feature呢?可以叫做运行时选择性注入吧,呵呵。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics