• Spring Boot 2.x实战


    领域事件

    由于在DDD中采用了“设计小聚合”的原则,因此避免了领域模型的相互关联,从而避免了在应用演进中形成“大泥球”(Big Ball of Mud),也因为上述的原因,本书将不讲解@OneToMany、@ManyToMany等关联注解。聚合之间在没有了关联关系后,聚合之间的数据通讯通过领域事件来完成,领域事件是由聚合根发出的。

    Spring Data对领域事件做了专门的支持,使用@DomainEvents注解注册领域事件或者继承AbstractAggregateRoot使用它的registerEvent方法注册事件。

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Entity
    public class Person {
        @DomainEvents // 使用集合类注册事件列表
        Collection<Object> domainEvents(){
            List<Object> events= new ArrayList<Object>();
            events.add(new PersonSaved(this.id, this.name, this.age));
            return events;
        }
    
        @AfterDomainEventPublication //所有事件发布完成后调用,一般用来清空事件列表
        void callbackMethod() {
           domainEvents().clear(); 
        }
    }

    当Repository每一次调用save方法时,领域事件都会被发布。

    我们的领域事件定义:

    import lombok.Value;
    @Value
    public class PersonSaved {
        private Long id;
        private String name;
        private Integer age;
    }

    我们现在定义另外一个聚合根,为雇员(Employee),它和Person是一一对应的关系,但是多了公司的信息。基于设计小聚合的原则,我们没有给他们配置@OneToOne,而是当Person保存成功后发布领域事件PersonSaved,在事件监听的位置我们在另外一个事务中新建对应的Employee。小聚合的另外一个好处就是将事务边界变小从而有更快的速度和更好的性能。

    新的雇员聚合:

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Entity
    public class Employee {
          @Id
        private Long id;
        private String name;
        private Integer age;
        @Embedded
        private Company company;
    }
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Embeddable
    public class Company {
        private String name;
        private String city;
    }

    聚合的Repository:

    public interface EmployeeRepository extends JpaRepository<Employee, Long> {
       List<Employee> findByName(String name);
    }

    领域发送的事件是Spring事件,我们可以使用@EventListener来接受,Spring Data给我们提供了专门的事务监听注解@TransactionalEventListener,它组合了@EventListener

    @Component
    public class DomainEventListener {
    
        private EmployeeRepository employeeRepository;
    
        public DomainEventListener(EmployeeRepository employeeRepository) {
            this.employeeRepository = employeeRepository;
        }
    
        @Async //1
        @TransactionalEventListener
        public void handlePersonSavedEvent(PersonSaved personSaved){
            Company company = new Company("某某公司", "hefei");
            Optional<Employee> employeeOptional = employeeRepository.findById(personSaved.getId());
            employeeOptional.ifPresent(employee -> { //2
                employee.setName(personSaved.getName());
                employee.setAge(personSaved.getAge());
                  employeeRepository.save(employee);
                return;
            });
            employeeRepository.save(new Employee(personSaved.getId(), personSaved.getName(), personSaved.getAge(), company));//3
        }
    }

    使用@Async注解让处理在另外一个线程处理;需要在配置类启用异步支持@EnableAsync

    @SpringBootApplication
    @EnableAsync
    public class LearningSpringDataJpaApplication {}
    1. 若存在则更新雇员;

    2. 若不存在则保存新的雇员。

    3. 执行检验代码:
    4. @Bean
      CommandLineRunner domainEvents(PersonRepository personRepository,
                              EmployeeRepository employeeRepository){
         return args -> {
            Address address = new Address("nanjing","Jiangsu");
            Collection<Child> children = Arrays.asList(new Child("xxxx", Gender.FEMALE));
            Person savedPerson = personRepository.save(new Person("wwww", 33, address, children));
            Thread.sleep(100); //监听是在异步线程执行的,所以需等待
            List<Employee> employees1 = employeeRepository.findByName("wwww");
            employees1.forEach(System.out::println);
            savedPerson.setName("wwwww");
            personRepository.save(savedPerson);
               Thread.sleep(100);
            List<Employee> employees2 = employeeRepository.findByName("wwwww");
            employees2.forEach(System.out::println);
         };
      }

    5. 转自:https://blog.csdn.net/wiselyman/article/details/106563016
  • 相关阅读:
    企业如何推行白盒测试
    Java命名规范
    MobileVLC for iphoneos4.3
    用Android NDK编译FFmpeg
    Linux 下Android 开发环境搭建 ---CentOS
    为什么要做白盒测试
    vlc的第三方库contrib的修改之一:live库的修改
    VC命名规范
    POJ 1470 Closest Common Ancestors (LCA入门题)
    HDU 4407 Sum 第37届ACM/ICPC 金华赛区 第1008题 (容斥原理)
  • 原文地址:https://www.cnblogs.com/pypua/p/13814952.html
Copyright © 2020-2023  润新知