DCI的AspectJ实现
11-03-17
banq
文章作者写了使用多个框架实现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> |
原文:
案例代码:http://sourceforge.net/projects/dci-in-aspectj/files/dci_in_aspectj-1.0.0-src.zip/download
banq
2011-03-17 11:25
请注意,文中使用配置了实体类User等创建时,并给给User对象赋值为"Rickard",这只是一个演示,关键是:实战中:User或Project的数据是从数据库中获得的。
关键是:我们已经注意到,在Spring管理的业务层,已经对实体类加了@AssignmentsRol之类元注解,也就是不能不管模型实体类了,下面的问题是:模型实体类的对象生存在哪里?
猜你喜欢