文章作者写了使用多个框架实现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();
|
以上代码主要表达意思是:给一个名叫"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(); }
|
以下是参与者的实体数据:
@AssignmentsRole //分配者 public class Project { }
@AssignableRole //被分配者 public class Task { } @AssignmentsRole @AssigneeRole public class User {
public User(String name) { setName(name); } }
|
下面是关键的建立一个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()); } }
|
下面是场景对象
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); } }
|
(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());
|
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>
|
原文:
DCI in AspectJ | Javalobby
案例代码:http://sourceforge.net/projects/dci-in-aspectj/files/dci_in_aspectj-1.0.0-src.zip/download