DCI的AspectJ實現

banq發表於2011-03-17

文章作者寫了使用多個框架實現DCI模式(Data Context Interaction)的文章,這次他使用aspectJ(Spring)談如何實現DCI,他的結論是比Qi4j要清晰一些。

下面是Qi4j的實現程式碼:

SingletonAssembler assembler = new SingletonAssembler() {
    public void assemble(ModuleAssembly module) throws AssemblyException {
        module.addEntities(TaskEntity.class, UserEntity.class);//加入任務資料實體  和使用者資料實體
        module.addServices(MemoryEntityStoreService.class, UuidIdentityGeneratorService.class);//加入服務
    }
};

UnitOfWork uow = assembler.unitOfWorkFactory().newUnitOfWork();

TaskEntity task = uow.newEntity(TaskEntity.class);

EntityBuilder<UserEntity> builder = uow.newEntityBuilder(UserEntity.class);
builder.instanceFor(AssigneeData.class).name().set("Rickard");
UserEntity user = builder.newInstance();

{
    //根據使用者名稱為"Rickard "產生一個場景
    InboxContext inbox = new InboxContext(user, user);
    //與任務結合
    inbox.assign(task);
}

uow.complete();
<p>

以上程式碼主要表達意思是:給一個名叫"Rickard "的使用者分配一個任務。作者認為上面程式碼很多嚴重依賴反射,影響效能,而且這些實體類不是普通的POJO類,和Spring之類框架整合起來困難。

下面是和aspectJ的過程,第一步定義幾種分配行為,作為實體的元註解使用:

public interface Assignments {

    void assign(Assignable assignable, Assignee assignee);

    List<Assignable> assignments();
}

public interface Assignable {

    void assignTo(Assignee assignee);
}

public interface Assignee {

    String assigneeName();
}
<p>

以下是參與者的實體資料:

@AssignmentsRole //分配者
public class Project {
}

@AssignableRole  //被分配者
public class Task {
}
    
@AssignmentsRole
@AssigneeRole
public class User {

    public User(String name) {
        setName(name);
    }
}
<p>

下面是關鍵的建立一個aspect類:

aspect AssignableImpl {

    declare parents: (@AssignableRole *) implements Assignable;

    private Assignee Assignable.assignee;

    //分配動作 
   public void Assignable.assignTo(Assignee assignee) {
 // No object schizophrenia - this reference is to the entity itself.
        this.assignee = assignee;
        System.out.println(assignee.assigneeName());
    }
}
<p>

下面是場景物件

public class InboxContext {

    private Assignments assignments;
    private Assignee assignee;

    public InboxContext(Assignments assignments, Assignee assignee) {
        this.assignments = assignments;
        this.assignee = assignee;
    }

    public void assign(Assignable assignable) {
        assignments.assign(assignable, assignee);
    }
}
<p>

(banq疑問:一般DCI有了場景 資料就可以了,這裡多出一個aspectj,難道比qi4j要簡單嗎?)

最後是實現DCI混合客戶端程式碼:

Task task = new Task();
User user = new User("Rickard");

InboxContext inbox = new InboxContext(user, user);
//給使用者Rickard分配任務
inbox.assign(task);

System.out.println("Nr of assignments: " + user.assignments().size());

Project project = new Project();
Task task2 = new Task();

//獲得場景
inbox = new InboxContext(project, user);
//給某個專案中的使用者Rickard分配任務
inbox.assign(task2);

System.out.println("Nr of assignments: " + project.assignments().size());
<p>

User Task都是沒有繼承任何類的POJO,可以被序列化,也可以在spring.xml配置中配置。

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="userRickard" class="net.sourceforge.dciaspectj.example1.entity.User">
        <constructor-arg index="0" value="Rickard" />
    </bean>

    <bean id="project" class="net.sourceforge.dciaspectj.example1.entity.Project" />

    <bean id="task1" class="net.sourceforge.dciaspectj.example1.entity.Task" />

    <bean id="task2" class="net.sourceforge.dciaspectj.example1.entity.Task" />

    <bean id="userInbox" class="net.sourceforge.dciaspectj.example1.context.InboxContext">
        <constructor-arg index="0" ref="userRickard" />
        <constructor-arg index="1" ref="userRickard" />
    </bean>

    <bean id="projectInbox" class="net.sourceforge.dciaspectj.example1.context.InboxContext">
        <constructor-arg index="0" ref="project" />
        <constructor-arg index="1" ref="userRickard" />
    </bean>
</beans>
<p>

原文:

DCI in AspectJ | Javalobby

案例程式碼:http://sourceforge.net/projects/dci-in-aspectj/files/dci_in_aspectj-1.0.0-src.zip/download

相關文章