├── nest-demo ├── nest-demo-webapi-v1 │ ├── build.gradle │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── zhaofujun │ │ └── nest │ │ └── demo │ │ ├── dto │ │ └── UserDto.java │ │ └── UserController.java ├── nest-demo-app │ ├── build.gradle │ └── src │ │ └── main │ │ └── java │ │ └── com │ │ └── zhaofujun │ │ └── nest │ │ └── demo │ │ ├── Application.java │ │ ├── appservices │ │ ├── UserDto.java │ │ ├── model │ │ │ └── User.java │ │ └── UserAppservice.java │ │ ├── handlers │ │ ├── UserEventHandlerListener.java │ │ └── UserEventHandler.java │ │ ├── webapi │ │ └── UserController.java │ │ └── repositories │ │ └── UserRepository.java └── build.gradle ├── gradle ├── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties └── libs.versions.toml ├── version.gradle ├── nest-ddd ├── src │ ├── main │ │ └── java │ │ │ └── com │ │ │ └── zhaofujun │ │ │ └── nest │ │ │ ├── ddd │ │ │ ├── Query.java │ │ │ ├── DomainService.java │ │ │ ├── event │ │ │ │ ├── ProcessState.java │ │ │ │ ├── EventState.java │ │ │ │ ├── MessageAck.java │ │ │ │ ├── EventMessageQuery.java │ │ │ │ ├── EventMessageRepository.java │ │ │ │ ├── ChannelConsumer.java │ │ │ │ ├── ProcessIdentifier.java │ │ │ │ ├── EventProcessRecordModel.java │ │ │ │ ├── EventData.java │ │ │ │ ├── EventItem.java │ │ │ │ ├── PushChannelConsumer.java │ │ │ │ ├── EventChannelProvider.java │ │ │ │ ├── EventMessageModel.java │ │ │ │ ├── EventSenderWorker.java │ │ │ │ ├── EventHandlerWorker.java │ │ │ │ ├── PullChannelConsumer.java │ │ │ │ ├── MessageProcessor.java │ │ │ │ └── EventAppService.java │ │ │ ├── AppServiceIgnore.java │ │ │ ├── ApplicationService.java │ │ │ ├── ConsumeMode.java │ │ │ ├── context │ │ │ │ ├── MethodInvoker.java │ │ │ │ ├── Transaction.java │ │ │ │ ├── QueryMethodProcessor.java │ │ │ │ ├── QueryContext.java │ │ │ │ ├── QueryContextBox.java │ │ │ │ ├── ServiceContextBox.java │ │ │ │ ├── Comparators.java │ │ │ │ ├── ServiceMethodProcessor.java │ │ │ │ ├── QueryContextManager.java │ │ │ │ ├── ServiceContextManager.java │ │ │ │ ├── EntityLoader.java │ │ │ │ └── ServiceContext.java │ │ │ ├── Identifier.java │ │ │ ├── Enum.java │ │ │ ├── AggregateRoot.java │ │ │ ├── LongIdentifier.java │ │ │ ├── StringIdentifier.java │ │ │ ├── UUIDIdentifier.java │ │ │ ├── DomainObject.java │ │ │ ├── ValueObject.java │ │ │ ├── EventHandler.java │ │ │ ├── Repository.java │ │ │ └── Entity.java │ │ │ ├── config │ │ │ ├── EventHandlerConfig.java │ │ │ ├── EventSenderConfig.java │ │ │ └── EventConfig.java │ │ │ ├── exception │ │ │ ├── CustomExceptionable.java │ │ │ ├── SystemExceptionable.java │ │ │ ├── VerifyFailedException.java │ │ │ ├── SystemException.java │ │ │ └── CustomException.java │ │ │ ├── provider │ │ │ ├── Provider.java │ │ │ ├── LongGenerator.java │ │ │ ├── Container.java │ │ │ ├── LockProvider.java │ │ │ └── CacheProvider.java │ │ │ ├── utils │ │ │ ├── message │ │ │ │ ├── Listener.java │ │ │ │ └── MessageObserver.java │ │ │ ├── StringUtil.java │ │ │ ├── lock │ │ │ │ └── LockItem.java │ │ │ ├── EventUtil.java │ │ │ ├── cache │ │ │ │ ├── CacheClient.java │ │ │ │ └── CacheItem.java │ │ │ ├── json │ │ │ │ ├── EntityObjectWriterProvider.java │ │ │ │ ├── EntityObjectReaderProvider.java │ │ │ │ ├── EntityObjectReaderAdapter.java │ │ │ │ └── EntityObjectWriterAdapter.java │ │ │ ├── EntityUtil.java │ │ │ ├── LockUtil.java │ │ │ ├── MessageUtil.java │ │ │ ├── JsonUtil.java │ │ │ ├── AppServiceUtil.java │ │ │ └── SnowFlakeUtil.java │ │ │ ├── Lifecycle.java │ │ │ ├── NestConst.java │ │ │ ├── inner │ │ │ ├── DefaultLockProvider.java │ │ │ ├── DefaultRepository.java │ │ │ ├── DefaultEventInfoRepository.java │ │ │ ├── DefaultEventChannelProvider.java │ │ │ └── DefaultCacheProvider.java │ │ │ ├── NestParameterizedType.java │ │ │ └── manager │ │ │ ├── ProviderManager.java │ │ │ ├── RepositoryManager.java │ │ │ ├── EventManager.java │ │ │ ├── EventHandlerManager.java │ │ │ └── CacheManager.java │ └── test │ │ └── java │ │ └── com │ │ └── zhaofujun │ │ └── nest │ │ └── test │ │ ├── UserCreatedHandler.java │ │ ├── UserDto.java │ │ ├── User.java │ │ ├── DefaultUserAppService.java │ │ └── UserTest.java └── build.gradle ├── nest-spring-parent ├── nest-spring-boot-starter-redis │ ├── build.gradle │ └── src │ │ └── main │ │ ├── resources │ │ └── META-INF │ │ │ └── spring │ │ │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports │ │ └── java │ │ └── com │ │ └── zhaofujun │ │ └── nest │ │ └── boot │ │ └── redis │ │ ├── identifier │ │ ├── RedisLongGenerator.java │ │ ├── DailyRedisLongGenerator.java │ │ └── RedisSequenceFactory.java │ │ ├── RedisAutoConfiguration.java │ │ └── provider │ │ ├── RedisLockProvider.java │ │ ├── RedisHashCacheProvider.java │ │ └── RedisCacheProvider.java ├── nest-spring-boot-starter-activemq │ ├── build.gradle │ └── src │ │ └── main │ │ ├── resources │ │ └── META-INF │ │ │ └── spring.factories │ │ └── java │ │ └── com │ │ └── zhaofujun │ │ └── nest │ │ └── boot │ │ └── activemq │ │ ├── ActivemqAutoConfiguration.java │ │ ├── ActivemqPullConsumer.java │ │ ├── ActivemqChannelProvider.java │ │ └── ActivemqPushConsumer.java ├── nest-spring-boot-starter │ ├── build.gradle │ ├── src │ │ └── main │ │ │ ├── resources │ │ │ └── META-INF │ │ │ │ ├── spring │ │ │ │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports │ │ │ │ └── spring.factories │ │ │ └── java │ │ │ └── com │ │ │ └── zhaofujun │ │ │ └── nest │ │ │ └── boot │ │ │ ├── AppService.java │ │ │ ├── Cache.java │ │ │ ├── EventListener.java │ │ │ ├── SpringBeanContainer.java │ │ │ ├── ApplicationStartedListener.java │ │ │ ├── SpringTransaction.java │ │ │ ├── NestApplicationContextAware.java │ │ │ ├── NestAutoConfiguration.java │ │ │ ├── NestBeanScannerRegistrar.java │ │ │ ├── ListenerMethodLookup.java │ │ │ ├── NestBeanScanner.java │ │ │ └── NestAspect.java │ └── target │ │ └── classes │ │ ├── META-INF │ │ └── spring.factories │ │ └── com │ │ └── zhaofujun │ │ └── nest │ │ └── springboot │ │ ├── AppService.class │ │ ├── NestAspect.class │ │ ├── EventListener.class │ │ ├── MethodAdapter.class │ │ ├── test │ │ ├── EventDto.class │ │ ├── Application.class │ │ ├── ListenerTest.class │ │ ├── TestHandler.class │ │ ├── domain │ │ │ ├── User.class │ │ │ ├── Address.class │ │ │ ├── Teacher.class │ │ │ └── HomeAddress.class │ │ ├── repositories │ │ │ └── UserRepository.class │ │ └── application │ │ │ └── UserApplicationService.class │ │ ├── NestBeanScanner$1.class │ │ ├── NestBeanScanner.class │ │ ├── SpringTransaction.class │ │ ├── SpringBeanContainer.class │ │ ├── ListenerMethodLookup$1.class │ │ ├── ListenerMethodLookup.class │ │ ├── NestAutoConfiguration.class │ │ ├── NestBeanScannerRegistrar.class │ │ ├── ApplicationStartdListener.class │ │ └── NestAspect$AspectMethodInvoker.class └── build.gradle ├── nest-generator ├── src │ └── main │ │ └── java │ │ └── com │ │ └── zhaofujun │ │ └── nest │ │ └── generator │ │ ├── TemplateType.java │ │ ├── model │ │ ├── NVoid.java │ │ ├── NObject.java │ │ ├── NService.java │ │ ├── NValueObject.java │ │ ├── NIdentifier.java │ │ ├── NBaseClass.java │ │ ├── NAggregateRoot.java │ │ ├── NField.java │ │ ├── NEntity.java │ │ ├── NClass.java │ │ ├── NMethod.java │ │ └── NModel.java │ │ ├── parser │ │ ├── Parser.java │ │ ├── ClassParser.java │ │ └── TypeUtil.java │ │ ├── Main.java │ │ └── generator │ │ ├── DmoGenerator.java │ │ └── Generator.java └── build.gradle ├── .gitattributes ├── .gitignore ├── settings.gradle ├── publish.gradle └── gradlew.bat /nest-demo/nest-demo-webapi-v1/build.gradle: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /nest-demo/nest-demo-app/build.gradle: -------------------------------------------------------------------------------- 1 | 2 | dependencies { 3 | 4 | } 5 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovezhao/nest/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /version.gradle: -------------------------------------------------------------------------------- 1 | ext{ 2 | versions = { 3 | fastjson : "2.0.10" 4 | } 5 | dependencies={ 6 | 7 | } 8 | } -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/Query.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd; 2 | 3 | public interface Query { 4 | 5 | 6 | } 7 | -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter-redis/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | api 'org.springframework.boot:spring-boot-starter-data-redis' 3 | } -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter-activemq/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | api ('org.springframework.boot:spring-boot-starter-activemq') 3 | } -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | api("org.springframework:spring-tx") 3 | api 'org.aspectj:aspectjtools' 4 | } -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/config/EventHandlerConfig.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.config; 2 | 3 | public class EventHandlerConfig { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/DomainService.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd; 2 | 3 | public interface DomainService extends DomainObject{ 4 | 5 | } 6 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/exception/CustomExceptionable.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.exception; 2 | 3 | public interface CustomExceptionable { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/exception/SystemExceptionable.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.exception; 2 | 3 | public interface SystemExceptionable { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/event/ProcessState.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.event; 2 | 3 | public enum ProcessState { 4 | processing, 5 | completed 6 | } -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/provider/Provider.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.provider; 2 | 3 | public interface Provider { 4 | 5 | String getCode(); 6 | 7 | } 8 | -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports: -------------------------------------------------------------------------------- 1 | com.zhaofujun.nest.boot.NestAutoConfiguration -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/utils/message/Listener.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.utils.message; 2 | 3 | 4 | public interface Listener { 5 | void onReceived(T t); 6 | } -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.context.ApplicationListener=com.zhaofujun.nest.boot.ApplicationStartedListener 2 | -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/target/classes/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.zhaofujun.nest.springboot.NestAutoConfiguration -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter-redis/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports: -------------------------------------------------------------------------------- 1 | com.zhaofujun.nest.boot.redis.RedisAutoConfiguration -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/provider/LongGenerator.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.provider; 2 | 3 | public interface LongGenerator extends Provider { 4 | Long nextValue(String key); 5 | } 6 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/event/EventState.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.event; 2 | 3 | public enum EventState { 4 | preSend, 5 | sendFail, 6 | sent, 7 | sending 8 | 9 | } -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter-activemq/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.zhaofujun.nest.boot.activemq.ActivemqAutoConfiguration -------------------------------------------------------------------------------- /nest-generator/src/main/java/com/zhaofujun/nest/generator/TemplateType.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.generator; 2 | 3 | public enum TemplateType { 4 | Dmo, 5 | Dao, 6 | Converter, 7 | Repository 8 | } 9 | -------------------------------------------------------------------------------- /nest-generator/src/main/java/com/zhaofujun/nest/generator/model/NVoid.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.generator.model; 2 | 3 | public class NVoid extends NClass { 4 | public NVoid() { 5 | super(null, "void"); 6 | } 7 | } -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/utils/StringUtil.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.utils; 2 | 3 | public class StringUtil { 4 | public static boolean isEmpty(String str) { 5 | return str==null || str.isEmpty(); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /nest-generator/src/main/java/com/zhaofujun/nest/generator/parser/Parser.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.generator.parser; 2 | 3 | import com.zhaofujun.nest.generator.model.NModel; 4 | 5 | public interface Parser { 6 | NModel parse(); 7 | } 8 | 9 | -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/AppService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovezhao/nest/HEAD/nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/AppService.class -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/NestAspect.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovezhao/nest/HEAD/nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/NestAspect.class -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/EventListener.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovezhao/nest/HEAD/nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/EventListener.class -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/MethodAdapter.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovezhao/nest/HEAD/nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/MethodAdapter.class -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/test/EventDto.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovezhao/nest/HEAD/nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/test/EventDto.class -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/NestBeanScanner$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovezhao/nest/HEAD/nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/NestBeanScanner$1.class -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/NestBeanScanner.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovezhao/nest/HEAD/nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/NestBeanScanner.class -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/SpringTransaction.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovezhao/nest/HEAD/nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/SpringTransaction.class -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/test/Application.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovezhao/nest/HEAD/nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/test/Application.class -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/test/ListenerTest.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovezhao/nest/HEAD/nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/test/ListenerTest.class -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/test/TestHandler.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovezhao/nest/HEAD/nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/test/TestHandler.class -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/test/domain/User.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovezhao/nest/HEAD/nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/test/domain/User.class -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/SpringBeanContainer.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovezhao/nest/HEAD/nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/SpringBeanContainer.class -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/test/domain/Address.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovezhao/nest/HEAD/nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/test/domain/Address.class -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/test/domain/Teacher.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovezhao/nest/HEAD/nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/test/domain/Teacher.class -------------------------------------------------------------------------------- /nest-generator/src/main/java/com/zhaofujun/nest/generator/model/NObject.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.generator.model; 2 | 3 | public class NObject extends NClass{ 4 | public NObject(String packageName, String name ) { 5 | super(packageName, name); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/ListenerMethodLookup$1.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovezhao/nest/HEAD/nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/ListenerMethodLookup$1.class -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/ListenerMethodLookup.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovezhao/nest/HEAD/nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/ListenerMethodLookup.class -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/NestAutoConfiguration.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovezhao/nest/HEAD/nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/NestAutoConfiguration.class -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/NestBeanScannerRegistrar.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovezhao/nest/HEAD/nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/NestBeanScannerRegistrar.class -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/test/domain/HomeAddress.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovezhao/nest/HEAD/nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/test/domain/HomeAddress.class -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/provider/Container.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.provider; 2 | 3 | import java.util.Set; 4 | 5 | public interface Container { 6 | Set getInstances(Class clazz); 7 | 8 | // T getInstance(Class clazz); 9 | } 10 | -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/ApplicationStartdListener.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovezhao/nest/HEAD/nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/ApplicationStartdListener.class -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/Lifecycle.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest; 2 | 3 | public enum Lifecycle { 4 | Entity_New, 5 | Entity_Ready, 6 | Entity_Created, 7 | Entity_Updated, 8 | Entity_Deleted, 9 | 10 | Consume_Begin, 11 | Consume_End 12 | } -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/event/MessageAck.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.event; 2 | 3 | public enum MessageAck { 4 | 5 | /** 6 | * 反馈消息处理成功 7 | */ 8 | SUCCESS, 9 | 10 | /** 11 | * 拒绝消息,消息将回返回mq 下次再重新消费 12 | */ 13 | REFUSE; 14 | } -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/NestAspect$AspectMethodInvoker.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovezhao/nest/HEAD/nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/NestAspect$AspectMethodInvoker.class -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/test/repositories/UserRepository.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovezhao/nest/HEAD/nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/test/repositories/UserRepository.class -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/provider/LockProvider.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.provider; 2 | 3 | import java.util.function.Supplier; 4 | 5 | /** 6 | * 锁提供者 7 | */ 8 | public interface LockProvider extends Provider { 9 | T lock(String name, Supplier runnable); 10 | } 11 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/test/application/UserApplicationService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jovezhao/nest/HEAD/nest-spring-parent/nest-spring-boot-starter/target/classes/com/zhaofujun/nest/springboot/test/application/UserApplicationService.class -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/exception/VerifyFailedException.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.exception; 2 | 3 | public class VerifyFailedException extends CustomException { 4 | public VerifyFailedException(String message, Object... arguments) { 5 | super(10001, message, arguments); 6 | } 7 | 8 | } 9 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/AppServiceIgnore.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * 忽略应用服务 7 | */ 8 | @Target({ElementType.METHOD}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | @Documented 11 | @Inherited 12 | public @interface AppServiceIgnore { 13 | } 14 | -------------------------------------------------------------------------------- /nest-generator/src/main/java/com/zhaofujun/nest/generator/model/NService.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.generator.model; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public class NService extends NModel{ 7 | 8 | public NService(String packageName, String name ) { 9 | super(packageName, name); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # 2 | # https://help.github.com/articles/dealing-with-line-endings/ 3 | # 4 | # Linux start script should use lf 5 | /gradlew text eol=lf 6 | 7 | # These are Windows script files and should use crlf 8 | *.bat text eol=crlf 9 | 10 | # Binary files should be left untouched 11 | *.jar binary 12 | 13 | -------------------------------------------------------------------------------- /nest-generator/src/main/java/com/zhaofujun/nest/generator/model/NValueObject.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.generator.model; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public class NValueObject extends NModel{ 7 | 8 | public NValueObject(String packageName, String name ) { 9 | super(packageName, name); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /nest-spring-parent/build.gradle: -------------------------------------------------------------------------------- 1 | subprojects { 2 | 3 | dependencies{ 4 | api("org.springframework.boot:spring-boot-starter") 5 | api(project(":nest-ddd")) 6 | testImplementation('org.springframework.boot:spring-boot-starter-test') 7 | } 8 | 9 | apply from: "${rootProject.projectDir}/publish.gradle" 10 | } 11 | -------------------------------------------------------------------------------- /nest-generator/src/main/java/com/zhaofujun/nest/generator/model/NIdentifier.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.generator.model; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public class NIdentifier extends NValueObject{ 7 | 8 | public NIdentifier(String packageName, String name ) { 9 | super(packageName, name); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/ApplicationService.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd; 2 | 3 | import com.zhaofujun.nest.ddd.context.Transaction; 4 | 5 | public interface ApplicationService { 6 | default Class getTransactionClass() { 7 | return Transaction.DefaultTransaction.class; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/event/EventMessageQuery.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.event; 2 | 3 | import java.util.List; 4 | 5 | import com.zhaofujun.nest.ddd.Query; 6 | 7 | public interface EventMessageQuery extends Query { 8 | 9 | List getListToBeSent(int commonSize,int failSize, int maxFailTime); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/ConsumeMode.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd; 2 | 3 | /** 4 | * 消费模式枚举类 5 | * 用于定义数据消费的两种模式:推模式和拉模式 6 | */ 7 | public enum ConsumeMode { 8 | /** 9 | * 推模式 10 | * 数据由生产者主动发送给消费者 11 | */ 12 | PUSH, 13 | /** 14 | * 拉模式 15 | * 消费者主动从生产者那里获取数据 16 | */ 17 | PULL 18 | } -------------------------------------------------------------------------------- /nest-generator/src/main/java/com/zhaofujun/nest/generator/model/NBaseClass.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.generator.model; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * 基础类型,主要包括基础类型与包装类型和字符串类型 7 | */ 8 | @Getter 9 | public class NBaseClass extends NClass { 10 | 11 | public NBaseClass( String name) { 12 | super(null, name); 13 | } 14 | } -------------------------------------------------------------------------------- /nest-generator/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | // https://mvnrepository.com/artifact/org.freemarker/freemarker 3 | implementation 'org.freemarker:freemarker:2.3.31' 4 | implementation project(":nest-ddd") 5 | implementation 'org.reflections:reflections:0.10.2' 6 | 7 | compileOnly 'org.projectlombok:lombok' 8 | annotationProcessor 'org.projectlombok:lombok' 9 | 10 | } -------------------------------------------------------------------------------- /gradle/libs.versions.toml: -------------------------------------------------------------------------------- 1 | # This file was generated by the Gradle 'init' task. 2 | # https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format 3 | 4 | [versions] 5 | guava = "33.2.1-jre" 6 | junit = "4.13.2" 7 | 8 | [libraries] 9 | guava = { module = "com.google.guava:guava", version.ref = "guava" } 10 | junit = { module = "junit:junit", version.ref = "junit" } 11 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/context/MethodInvoker.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.context; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | public interface MethodInvoker { 6 | String getMethodName(); 7 | 8 | Object invoke() throws Throwable; 9 | 10 | Class getTargetClass(); 11 | 12 | Object getTarget(); 13 | 14 | Method getMethod(); 15 | } 16 | -------------------------------------------------------------------------------- /nest-generator/src/main/java/com/zhaofujun/nest/generator/model/NAggregateRoot.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.generator.model; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | @Getter 7 | @Setter 8 | public class NAggregateRoot extends NEntity{ 9 | 10 | public NAggregateRoot(String packageName, String name ) { 11 | super(packageName, name); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /nest-generator/src/main/java/com/zhaofujun/nest/generator/model/NField.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.generator.model; 2 | 3 | import lombok.Getter; 4 | 5 | @Getter 6 | public class NField{ 7 | private final String name; 8 | private final NClass nClass; 9 | public NField(String name, NClass nClass){ 10 | this.name = name; 11 | this.nClass = nClass; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /nest-demo/build.gradle: -------------------------------------------------------------------------------- 1 | subprojects{ 2 | dependencies { 3 | implementation('org.springframework.boot:spring-boot-starter-web') 4 | // implementation project(':nest-ddd') 5 | implementation project(':nest-spring-parent:nest-spring-boot-starter') 6 | // implementation('io.springfox:springfox-swagger2') 7 | // implementation('io.springfox:springfox-swagger-ui') 8 | } 9 | } -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter-activemq/src/main/java/com/zhaofujun/nest/boot/activemq/ActivemqAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.boot.activemq; 2 | 3 | import org.springframework.context.annotation.ComponentScan; 4 | import org.springframework.context.annotation.Configuration; 5 | 6 | 7 | @Configuration 8 | @ComponentScan 9 | public class ActivemqAutoConfiguration { 10 | 11 | 12 | } 13 | -------------------------------------------------------------------------------- /nest-demo/nest-demo-app/src/main/java/com/zhaofujun/nest/demo/Application.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.demo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class Application { 8 | public static void main(String[] args) { 9 | SpringApplication.run(Application.class, args); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | **/target/ 3 | pom.xml.tag 4 | pom.xml.releaseBackup 5 | pom.xml.versionsBackup 6 | pom.xml.next 7 | release.properties 8 | dependency-reduced-pom.xml 9 | buildNumber.properties 10 | .mvn/timing.properties 11 | *.iml 12 | .idea/ 13 | .idea 14 | .vscode/ 15 | .vscode 16 | modules/log 17 | modules/logs 18 | .project 19 | .settings 20 | .classpath 21 | #hu lue wenjian 22 | .gradle/ 23 | build/ 24 | **/build/ 25 | bin/ 26 | .gitee/ -------------------------------------------------------------------------------- /nest-generator/src/main/java/com/zhaofujun/nest/generator/model/NEntity.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.generator.model; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | @Getter 7 | @Setter 8 | public class NEntity extends NModel{ 9 | private NIdentifier nIdentifier; 10 | private boolean _abstract; 11 | public NEntity(String packageName, String name) { 12 | super(packageName, name); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | 2 | rootProject.name = 'nest' 3 | include(':nest-ddd') 4 | include(":nest-spring-parent") 5 | include(":nest-spring-parent:nest-spring-boot-starter") 6 | include(':nest-spring-parent:nest-spring-boot-starter-activemq') 7 | include(':nest-spring-parent:nest-spring-boot-starter-redis') 8 | 9 | include(':nest-demo') 10 | include(':nest-demo:nest-demo-webapi-v1') 11 | include(':nest-demo:nest-demo-app') 12 | include(':nest-generator') -------------------------------------------------------------------------------- /nest-generator/src/main/java/com/zhaofujun/nest/generator/model/NClass.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.generator.model; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * 定义类型 7 | */ 8 | @Getter 9 | public abstract class NClass { 10 | private final String packageName; 11 | private final String name; 12 | 13 | public NClass(String packageName, String name) { 14 | this.packageName = packageName; 15 | this.name = name; 16 | } 17 | } -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/Identifier.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd; 2 | 3 | /** 4 | * 标识符抽象类。 5 | */ 6 | public abstract class Identifier extends ValueObject { 7 | /** 8 | * 将标识符转换为字符串值。 9 | * 10 | * @return 字符串值 11 | */ 12 | public abstract String toValue(); 13 | 14 | @Override 15 | protected Object[] getPropertiesForComparison() { 16 | return new Object[] { toValue() }; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/src/main/java/com/zhaofujun/nest/boot/AppService.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.boot; 2 | 3 | import java.lang.annotation.*; 4 | import com.zhaofujun.nest.ddd.context.Transaction; 5 | 6 | /** 7 | * 标注为应用服务 8 | */ 9 | @Target({ ElementType.TYPE }) 10 | @Retention(RetentionPolicy.RUNTIME) 11 | @Documented 12 | @Inherited 13 | public @interface AppService { 14 | Class transaction() default Transaction.DefaultTransaction.class; 15 | } 16 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/exception/SystemException.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.exception; 2 | 3 | /** 4 | * 用于不可控但往往会影响业务流程的异常,常见于网络原因或第三方系统出现故障。 5 | * Created by zhaofujun on 2017/6/23. 6 | */ 7 | public class SystemException extends RuntimeException { 8 | 9 | public SystemException(String message) { 10 | super(message); 11 | } 12 | 13 | public SystemException(String message, Throwable cause) { 14 | super(message, cause); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/event/EventMessageRepository.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.event; 2 | 3 | import java.lang.reflect.Type; 4 | 5 | import com.zhaofujun.nest.ddd.LongIdentifier; 6 | import com.zhaofujun.nest.ddd.Repository; 7 | 8 | public abstract class EventMessageRepository implements EventMessageQuery, Repository, LongIdentifier> { 9 | @Override 10 | public Class getEntityClass() { 11 | return EventMessageModel.class; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /nest-generator/src/main/java/com/zhaofujun/nest/generator/Main.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.generator; 2 | 3 | import java.lang.reflect.Field; 4 | 5 | public class Main { 6 | private int aa; 7 | public static void main(String[] args) { 8 | System.out.println("Hello World"); 9 | for (Field field : Main.class.getDeclaredFields()) { 10 | System.out.println("name:"+field.getName()); 11 | System.out.println("type:"+field.getType()); 12 | 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /nest-demo/nest-demo-webapi-v1/src/main/java/com/zhaofujun/nest/demo/dto/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.demo.dto; 2 | 3 | public class UserDto { 4 | private String id; 5 | private String name; 6 | public String getId() { 7 | return id; 8 | } 9 | public void setId(String id) { 10 | this.id = id; 11 | } 12 | public String getName() { 13 | return name; 14 | } 15 | public void setName(String name) { 16 | this.name = name; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /nest-demo/nest-demo-app/src/main/java/com/zhaofujun/nest/demo/appservices/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.demo.appservices; 2 | 3 | public class UserDto { 4 | private String id; 5 | private String name; 6 | public String getId() { 7 | return id; 8 | } 9 | public void setId(String id) { 10 | this.id = id; 11 | } 12 | public String getName() { 13 | return name; 14 | } 15 | public void setName(String name) { 16 | this.name = name; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/context/Transaction.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.context; 2 | 3 | public interface Transaction { 4 | void commit(); 5 | 6 | void begin(); 7 | 8 | void rollback(); 9 | 10 | public class DefaultTransaction implements Transaction { 11 | 12 | @Override 13 | public void commit() { 14 | 15 | } 16 | 17 | @Override 18 | public void begin() { 19 | 20 | } 21 | 22 | @Override 23 | public void rollback() { 24 | 25 | } 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /nest-demo/nest-demo-webapi-v1/src/main/java/com/zhaofujun/nest/demo/UserController.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.demo; 2 | 3 | import org.springframework.web.bind.annotation.GetMapping; 4 | import org.springframework.web.bind.annotation.PathVariable; 5 | import org.springframework.web.bind.annotation.RestController; 6 | 7 | import com.zhaofujun.nest.demo.dto.UserDto; 8 | 9 | @RestController 10 | public class UserController { 11 | @GetMapping("/user/{id}") 12 | public UserDto getUser(@PathVariable String id) { 13 | return new UserDto(); 14 | } 15 | } -------------------------------------------------------------------------------- /nest-demo/nest-demo-app/src/main/java/com/zhaofujun/nest/demo/handlers/UserEventHandlerListener.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.demo.handlers; 2 | 3 | import org.springframework.stereotype.Component; 4 | import com.zhaofujun.nest.boot.EventListener; 5 | import com.zhaofujun.nest.demo.appservices.UserDto; 6 | 7 | @Component 8 | public class UserEventHandlerListener { 9 | @EventListener(eventDataClass = UserDto.class, eventName = "user_name_changed") 10 | public void userCreate(UserDto userDto) { 11 | System.out.println("event listener"); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/Enum.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd; 2 | 3 | import javax.validation.constraints.Email; 4 | 5 | /** 6 | * 表示枚举的接口。 7 | * 枚举是一种特殊的类型,它代表了一组命名的值。 8 | */ 9 | public interface Enum { 10 | 11 | /** 12 | * 获取枚举的标签。 13 | * 14 | * @return 枚举的标签。 15 | */ 16 | String getLabel(); 17 | 18 | /** 19 | * 获取枚举的值。 20 | * 21 | * @return 枚举的值。 22 | */ 23 | T getValue(); 24 | 25 | /** 26 | * 获取枚举的键。 27 | * 28 | * @return 枚举的键。 29 | */ 30 | String getKey(); 31 | } 32 | -------------------------------------------------------------------------------- /nest-ddd/build.gradle: -------------------------------------------------------------------------------- 1 | 2 | dependencies{ 3 | api("javax.validation:validation-api") 4 | api("com.alibaba:transmittable-thread-local") 5 | api("com.alibaba.fastjson2:fastjson2") 6 | api("net.sf.ehcache:ehcache-core") 7 | // implementation 'com.google.guava:guava:31.0.1-jre' 8 | api("cglib:cglib") 9 | 10 | testImplementation(platform('org.junit:junit-bom:5.11.3')) 11 | testImplementation('org.junit.jupiter:junit-jupiter') 12 | testRuntimeOnly('org.junit.platform:junit-platform-launcher') 13 | 14 | } 15 | 16 | apply from: "${rootProject.projectDir}/publish.gradle" 17 | -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/src/main/java/com/zhaofujun/nest/boot/Cache.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.boot; 2 | 3 | import java.lang.annotation.Documented; 4 | import java.lang.annotation.ElementType; 5 | import java.lang.annotation.Inherited; 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.RetentionPolicy; 8 | import java.lang.annotation.Target; 9 | 10 | /** 11 | * 对有返回参数的方法添加缓存注解。 12 | */ 13 | @Target({ ElementType.METHOD }) 14 | @Retention(RetentionPolicy.RUNTIME) 15 | @Documented 16 | @Inherited 17 | public @interface Cache { 18 | String name(); 19 | } 20 | -------------------------------------------------------------------------------- /nest-ddd/src/test/java/com/zhaofujun/nest/test/UserCreatedHandler.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.test; 2 | 3 | import com.zhaofujun.nest.ddd.EventHandler; 4 | 5 | public class UserCreatedHandler implements EventHandler { 6 | 7 | @Override 8 | public String getEventName() { 9 | return "user_created"; 10 | } 11 | 12 | @Override 13 | public Class getEventDataClass() { 14 | return UserDto.class; 15 | } 16 | 17 | @Override 18 | public void handle(UserDto eventData) { 19 | System.out.println("接收到用户创建成功的事件:" + eventData.toString()); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/AggregateRoot.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd; 2 | 3 | /** 4 | * 表示聚合根的抽象类,聚合根是领域驱动设计(DDD)中的一个模式。 5 | * 聚合根是一种特殊的实体,它作为一组相关对象的入口点,这些对象一起形成一个聚合。 6 | * 本抽象类主要定义了聚合根标识符的泛型类型。 7 | * 8 | * @param 标识符的类型,必须扩展Identifier类。 9 | * 10 | * @author zhaofujun 11 | * 12 | */ 13 | public abstract class AggregateRoot extends Entity { 14 | 15 | /** 16 | * 构造聚合根实例。 17 | * 18 | * @param id 聚合根的标识符,不能为null。 19 | * 20 | * @throws NullPointerException 如果id为null 21 | */ 22 | public AggregateRoot(T id) { 23 | super(id); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /nest-ddd/src/test/java/com/zhaofujun/nest/test/UserDto.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.test; 2 | 3 | public class UserDto { 4 | private String id; 5 | private String name; 6 | 7 | public String getId() { 8 | return id; 9 | } 10 | 11 | public void setId(String id) { 12 | this.id = id; 13 | } 14 | 15 | public String getName() { 16 | return name; 17 | } 18 | 19 | public void setName(String name) { 20 | this.name = name; 21 | } 22 | 23 | @Override 24 | public String toString() { 25 | return "UserDto [id=" + id + ", name=" + name + "]"; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/NestConst.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest; 2 | 3 | public class NestConst { 4 | public static final String defaultCacheProvider = "Default_Cache_Provider"; 5 | public static final String entityCache = "Cache_Item_Entity"; 6 | public static final String defaultCacheItem = "Cache_Item_Default"; 7 | public static final String defaultChannel = "Default_Channel"; 8 | public static final String defaultRepositoryCache = "Default_Repository_Cache"; 9 | public static final String defaultLockProvider="Default_Lock_Provider"; 10 | public static final String eventSenderLock="event_sender_lock"; 11 | } 12 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/event/ChannelConsumer.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.event; 2 | 3 | import java.util.Collection; 4 | import com.zhaofujun.nest.ddd.EventHandler; 5 | 6 | /** 7 | * 通道消费者接口,负责注册事件处理器和设置事件应用服务。 8 | */ 9 | public interface ChannelConsumer { 10 | 11 | /** 12 | * 注册事件处理器。 13 | * 14 | * @param eventName 事件名称 15 | * @param eventHandlers 事件处理器集合 16 | */ 17 | void register(String eventName, Collection eventHandlers); 18 | 19 | /** 20 | * 设置事件应用服务。 21 | * 22 | * @param appService 事件应用服务 23 | */ 24 | void setEventAppService(EventAppService appService); 25 | } 26 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/utils/lock/LockItem.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.utils.lock; 2 | 3 | /** 4 | * 锁配置项 5 | */ 6 | public class LockItem { 7 | /** 8 | * 锁名称 9 | */ 10 | private String name; 11 | /** 12 | * 锁提供者代号 13 | */ 14 | private String provider; 15 | 16 | public String getName() { 17 | return name; 18 | } 19 | 20 | public void setName(String name) { 21 | this.name = name; 22 | } 23 | 24 | public String getProvider() { 25 | return provider; 26 | } 27 | 28 | public void setProvider(String provider) { 29 | this.provider = provider; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /nest-generator/src/main/java/com/zhaofujun/nest/generator/generator/DmoGenerator.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.generator.generator; 2 | 3 | import com.zhaofujun.nest.generator.model.NEntity; 4 | import freemarker.template.Configuration; 5 | import freemarker.template.Template; 6 | 7 | import java.io.Writer; 8 | 9 | public class DmoGenerator extends Generator { 10 | 11 | 12 | @Override 13 | public Template getTemplate(Configuration cfg) { 14 | return null; 15 | } 16 | 17 | @Override 18 | public Object getDataModel(NEntity nEntity) { 19 | return null; 20 | } 21 | 22 | @Override 23 | public Writer getWriter() { 24 | return null; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /nest-ddd/src/test/java/com/zhaofujun/nest/test/User.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.test; 2 | 3 | import com.zhaofujun.nest.ddd.AggregateRoot; 4 | import com.zhaofujun.nest.ddd.StringIdentifier; 5 | 6 | public class User extends AggregateRoot { 7 | public User(StringIdentifier identifier) { 8 | super(identifier); 9 | } 10 | 11 | private String name; 12 | 13 | public String getName() { 14 | return name; 15 | } 16 | 17 | public void setName(String name) { 18 | this.name = name; 19 | } 20 | 21 | @Override 22 | public String toString() { 23 | return "User [name=" + name + ", id=" + id.toValue() + "]"+this.hashCode(); 24 | } 25 | 26 | 27 | } -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/provider/CacheProvider.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.provider; 2 | 3 | 4 | import java.util.Map; 5 | 6 | /** 7 | * 缓存策略 8 | * 9 | * @author Jove 10 | */ 11 | public interface CacheProvider extends Provider { 12 | 13 | String get(String groupName, String key); 14 | 15 | 16 | Map get(String groupName, String... keys); 17 | 18 | 19 | void put(String groupName, String key, String value, long idleSeconds); 20 | 21 | 22 | boolean remove(String groupName, String key); 23 | 24 | 25 | void removeAll(String groupName); 26 | 27 | 28 | boolean containsKey(String groupName, String key); 29 | 30 | 31 | String[] getKeys(String groupName); 32 | } 33 | -------------------------------------------------------------------------------- /nest-ddd/src/test/java/com/zhaofujun/nest/test/DefaultUserAppService.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.test; 2 | 3 | import com.zhaofujun.nest.ddd.ApplicationService; 4 | import com.zhaofujun.nest.ddd.StringIdentifier; 5 | import com.zhaofujun.nest.utils.EventUtil; 6 | 7 | public class DefaultUserAppService implements ApplicationService { 8 | public UserDto create(String id,String name) { 9 | User user = new User(new StringIdentifier(id)); 10 | user.setName(name); 11 | 12 | UserDto userDto = new UserDto(); 13 | userDto.setId(user.getId().toValue()); 14 | userDto.setName(user.getName()); 15 | EventUtil.publish("user_created", userDto, 100); 16 | 17 | return userDto; 18 | } 19 | } -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/src/main/java/com/zhaofujun/nest/boot/EventListener.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.boot; 2 | 3 | import java.lang.annotation.Target; 4 | 5 | import com.zhaofujun.nest.ddd.ConsumeMode; 6 | 7 | import java.lang.annotation.Documented; 8 | import java.lang.annotation.ElementType; 9 | import java.lang.annotation.Inherited; 10 | import java.lang.annotation.Retention; 11 | import java.lang.annotation.RetentionPolicy; 12 | 13 | @Target({ ElementType.METHOD }) 14 | @Retention(RetentionPolicy.RUNTIME) 15 | @Documented 16 | @Inherited 17 | public @interface EventListener { 18 | String eventName(); 19 | 20 | Class eventDataClass(); 21 | 22 | ConsumeMode consumeMode() default ConsumeMode.PUSH; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/event/ProcessIdentifier.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.event; 2 | 3 | import com.zhaofujun.nest.ddd.Identifier; 4 | 5 | public class ProcessIdentifier extends Identifier { 6 | 7 | private String messageId; 8 | private String handlerId; 9 | 10 | public ProcessIdentifier(String messageId, String handlerId) { 11 | this.messageId = messageId; 12 | this.handlerId = handlerId; 13 | } 14 | 15 | public String getMessageId() { 16 | return messageId; 17 | } 18 | 19 | public String getHandlerId() { 20 | return handlerId; 21 | } 22 | 23 | @Override 24 | public String toValue() { 25 | return messageId + "-" + handlerId; 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /nest-demo/nest-demo-app/src/main/java/com/zhaofujun/nest/demo/handlers/UserEventHandler.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.demo.handlers; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | import com.zhaofujun.nest.ddd.EventHandler; 6 | import com.zhaofujun.nest.demo.appservices.UserDto; 7 | @Component 8 | public class UserEventHandler implements EventHandler { 9 | 10 | @Override 11 | public String getEventName() { 12 | return "user_name_changed"; 13 | } 14 | 15 | @Override 16 | public Class getEventDataClass() { 17 | return UserDto.class; 18 | } 19 | 20 | @Override 21 | public void handle(UserDto eventData) { 22 | System.out.println("event handler"); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/utils/EventUtil.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.utils; 2 | 3 | import java.time.LocalDateTime; 4 | 5 | import com.zhaofujun.nest.ddd.LongIdentifier; 6 | import com.zhaofujun.nest.ddd.event.EventMessageModel; 7 | 8 | public class EventUtil { 9 | public static void publish(String eventName, Object eventData, long delaySecond) { 10 | long idLong = SnowFlakeUtil.nextLong(); 11 | LocalDateTime sendDateTime = LocalDateTime.now().plusSeconds(delaySecond); 12 | new EventMessageModel<>(new LongIdentifier(idLong), eventName, eventData, sendDateTime); 13 | } 14 | 15 | public static void publish(String eventName, Object eventData) { 16 | publish(eventName, eventData, 0); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /nest-demo/nest-demo-app/src/main/java/com/zhaofujun/nest/demo/appservices/model/User.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.demo.appservices.model; 2 | 3 | import com.zhaofujun.nest.ddd.AggregateRoot; 4 | import com.zhaofujun.nest.ddd.LongIdentifier; 5 | 6 | public class User extends AggregateRoot { 7 | private String name; 8 | private long age; 9 | 10 | public User(LongIdentifier longIdentifier){ 11 | super(longIdentifier); 12 | } 13 | public String getName() { 14 | return name; 15 | } 16 | public void setName(String name) { 17 | this.name = name; 18 | } 19 | public long getAge() { 20 | return age; 21 | } 22 | public void setAge(long age) { 23 | this.age = age; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/LongIdentifier.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd; 2 | 3 | /** 4 | * 长整型标识符类。 5 | */ 6 | public class LongIdentifier extends Identifier { 7 | 8 | /** 9 | * 标识符值。 10 | */ 11 | private long id; 12 | 13 | /** 14 | * 获取标识符值。 15 | * 16 | * @return 标识符值 17 | */ 18 | public long getId() { 19 | return id; 20 | } 21 | 22 | /** 23 | * 构造函数。 24 | * 25 | * @param id 标识符值 26 | */ 27 | public LongIdentifier(long id) { 28 | this.id = id; 29 | } 30 | 31 | @Override 32 | /** 33 | * 将标识符转换为字符串值。 34 | * 35 | * @return 字符串值 36 | */ 37 | public String toValue() { 38 | return String.valueOf(this.id); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/utils/cache/CacheClient.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.utils.cache; 2 | 3 | import java.util.Map; 4 | 5 | public interface CacheClient { 6 | 7 | 8 | String getCode(); 9 | 10 | T get(Class tClass, String key); 11 | 12 | String get(String key); 13 | 14 | Map get(Class tClass, String... keys); 15 | 16 | void put(String key, Object value, long idleSeconds); 17 | 18 | void put(String key, String value, long idleSeconds); 19 | 20 | void put(String key, Object value); 21 | 22 | void put(String key, String value); 23 | 24 | boolean remove(String key); 25 | 26 | void removeAll(); 27 | 28 | boolean containsKey(String key); 29 | 30 | String[] getKeys(); 31 | 32 | 33 | 34 | } -------------------------------------------------------------------------------- /nest-demo/nest-demo-app/src/main/java/com/zhaofujun/nest/demo/webapi/UserController.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.demo.webapi; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.web.bind.annotation.GetMapping; 5 | import org.springframework.web.bind.annotation.PathVariable; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | import com.zhaofujun.nest.demo.appservices.UserAppservice; 9 | import com.zhaofujun.nest.demo.appservices.UserDto; 10 | 11 | @RestController 12 | public class UserController { 13 | @Autowired 14 | private UserAppservice userAppservice; 15 | 16 | @GetMapping("/user/{id}") 17 | public UserDto changeName(@PathVariable Long id) { 18 | return userAppservice.changeName(id); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/StringIdentifier.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd; 2 | 3 | /** 4 | * 字符串标识符类,继承自 Identifier 类。 5 | */ 6 | public class StringIdentifier extends Identifier { 7 | 8 | /** 9 | * 标识符值。 10 | */ 11 | private String id; 12 | 13 | /** 14 | * 构造函数,初始化标识符值。 15 | * 16 | * @param id 标识符值 17 | */ 18 | public StringIdentifier(String id) { 19 | this.id = id; 20 | } 21 | 22 | /** 23 | * 将标识符值转换为字符串。 24 | * 25 | * @return 标识符值字符串 26 | */ 27 | @Override 28 | public String toValue() { 29 | return id.toString(); 30 | } 31 | 32 | /** 33 | * 获取标识符值。 34 | * 35 | * @return 标识符值 36 | */ 37 | public String getId() { 38 | return id; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/context/QueryMethodProcessor.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.context; 2 | 3 | public class QueryMethodProcessor { 4 | private MethodInvoker methodInvoker; 5 | 6 | public QueryMethodProcessor(MethodInvoker methodInvoker) { 7 | this.methodInvoker = methodInvoker; 8 | } 9 | 10 | public Object doInvoke() throws Throwable { 11 | 12 | QueryContext queryContext = QueryContextManager.newServiceContext(); 13 | 14 | Object result = null; 15 | 16 | queryContext.begin(); 17 | try { 18 | result = methodInvoker.invoke(); 19 | queryContext.submit(); 20 | } finally { 21 | queryContext.end(); 22 | QueryContextManager.pop(); 23 | } 24 | return result; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /nest-generator/src/main/java/com/zhaofujun/nest/generator/model/NMethod.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.generator.model; 2 | 3 | import lombok.Getter; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | @Getter 9 | public class NMethod{ 10 | private String name; 11 | private NClass returnType; 12 | private List parameters; 13 | 14 | public NMethod(String name, NClass returnType) { 15 | this.name = name; 16 | this.returnType = returnType; 17 | parameters = new ArrayList(); 18 | } 19 | public void addParameter(NField parameter) { 20 | parameters.add(parameter); 21 | } 22 | public void addParameters(NField... parameters) { 23 | for (NField parameter : parameters) { 24 | addParameter(parameter); 25 | } 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /nest-demo/nest-demo-app/src/main/java/com/zhaofujun/nest/demo/appservices/UserAppservice.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.demo.appservices; 2 | 3 | import com.zhaofujun.nest.boot.AppService; 4 | import com.zhaofujun.nest.ddd.LongIdentifier; 5 | import com.zhaofujun.nest.demo.appservices.model.User; 6 | import com.zhaofujun.nest.utils.EntityUtil; 7 | import com.zhaofujun.nest.utils.EventUtil; 8 | 9 | @AppService 10 | public class UserAppservice { 11 | 12 | public UserDto changeName(long id) { 13 | User user = EntityUtil.load(User.class, new LongIdentifier(id)); 14 | user.setName("name1"); 15 | 16 | var result = new UserDto(); 17 | result.setId(user.getId().toValue()); 18 | result.setName(user.getName()); 19 | 20 | EventUtil.publish("user_name_changed", result); 21 | 22 | return result; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/UUIDIdentifier.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd; 2 | 3 | import java.util.UUID; 4 | 5 | /** 6 | * UUID 标识符类,继承自 Identifier 类。 7 | */ 8 | public class UUIDIdentifier extends Identifier { 9 | /** 10 | * UUID 值。 11 | */ 12 | private UUID id; 13 | 14 | /** 15 | * 将 UUID 值转换为字符串。 16 | * 17 | * @return UUID 值字符串 18 | */ 19 | @Override 20 | public String toValue() { 21 | return id.toString(); 22 | } 23 | 24 | /** 25 | * 构造函数,初始化 UUID 值。 26 | * 27 | * @param id UUID 值 28 | */ 29 | public UUIDIdentifier(UUID id) { 30 | this.id = id; 31 | } 32 | 33 | /** 34 | * 创建一个新的 UUID 标识符。 35 | * 36 | * @return 新的 UUID 标识符 37 | */ 38 | private static UUIDIdentifier newId() { 39 | return new UUIDIdentifier(UUID.randomUUID()); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter-redis/src/main/java/com/zhaofujun/nest/boot/redis/identifier/RedisLongGenerator.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.boot.redis.identifier; 2 | 3 | import com.zhaofujun.nest.provider.LongGenerator; 4 | import org.springframework.data.redis.core.RedisTemplate; 5 | 6 | public class RedisLongGenerator implements LongGenerator { 7 | public final static String CODE = "RedisLongGenerator"; 8 | 9 | private RedisTemplate redisTemplate; 10 | private String prefix = "nest_redis_id_"; 11 | 12 | public RedisLongGenerator(RedisTemplate redisTemplate) { 13 | this.redisTemplate = redisTemplate; 14 | } 15 | 16 | @Override 17 | public String getCode() { 18 | return CODE; 19 | } 20 | 21 | @Override 22 | public Long nextValue(String key) { 23 | 24 | return redisTemplate.opsForValue().increment(prefix + key); 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/event/EventProcessRecordModel.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.event; 2 | 3 | import java.time.LocalDateTime; 4 | 5 | import com.zhaofujun.nest.ddd.AggregateRoot; 6 | 7 | public class EventProcessRecordModel extends AggregateRoot { 8 | 9 | private ProcessState processState; 10 | private LocalDateTime processTime; 11 | 12 | public EventProcessRecordModel(ProcessIdentifier processIdentifier) { 13 | super(processIdentifier); 14 | this.processState = ProcessState.processing; 15 | } 16 | 17 | public void process() { 18 | processState = ProcessState.completed; 19 | processTime = LocalDateTime.now(); 20 | } 21 | 22 | public ProcessState getProcessState() { 23 | return processState; 24 | } 25 | 26 | public LocalDateTime getProcessTime() { 27 | return processTime; 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/src/main/java/com/zhaofujun/nest/boot/SpringBeanContainer.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.boot; 2 | 3 | import org.springframework.context.ApplicationContext; 4 | import org.springframework.stereotype.Component; 5 | 6 | import com.zhaofujun.nest.provider.Container; 7 | 8 | import java.util.Set; 9 | import java.util.stream.Collectors; 10 | 11 | 12 | @Component 13 | public class SpringBeanContainer implements Container { 14 | public SpringBeanContainer(ApplicationContext applicationContext) { 15 | this.applicationContext = applicationContext; 16 | } 17 | 18 | private ApplicationContext applicationContext; 19 | 20 | @Override 21 | public Set getInstances(Class clazz) { 22 | return applicationContext.getBeansOfType(clazz).entrySet() 23 | .stream() 24 | .map(p -> p.getValue()) 25 | .collect(Collectors.toSet()); 26 | } 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/utils/message/MessageObserver.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.utils.message; 2 | 3 | import java.util.Vector; 4 | 5 | public class MessageObserver { 6 | private String name; 7 | 8 | public MessageObserver(String name) { 9 | this.name = name; 10 | } 11 | 12 | 13 | public String getName() { 14 | return name; 15 | } 16 | 17 | 18 | private Vector listeners = new Vector<>(); 19 | 20 | public void emit(Object Object) { 21 | listeners.forEach(p -> p.onReceived(Object)); 22 | } 23 | 24 | public void on(Class tClass, Listener listener) { 25 | listeners.add(listener); 26 | } 27 | public void on(Listener listener) { 28 | listeners.add(listener); 29 | } 30 | 31 | public void remove(Listener listener) { 32 | listeners.remove(listener); 33 | } 34 | 35 | public void removeAll() { 36 | listeners.clear(); 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/context/QueryContext.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.context; 2 | 3 | import java.util.HashSet; 4 | import java.util.Set; 5 | 6 | import com.zhaofujun.nest.ddd.Entity; 7 | 8 | public class QueryContext { 9 | 10 | private Set entities = new HashSet<>(); 11 | 12 | public void begin() { 13 | entities.clear(); 14 | } 15 | 16 | public void submit() { 17 | 18 | // 将查询上下文的实体转移到服务上下文中 19 | // 让查询上下文中产生的对象都转换为准备状态 20 | ServiceContext serviceContext = ServiceContextManager.getCurrentContext(); 21 | if (serviceContext != null) { 22 | entities.forEach(entity -> { 23 | entity._ready(); 24 | serviceContext.addEntity(entity); 25 | }); 26 | } 27 | 28 | } 29 | 30 | public void end() { 31 | entities.clear(); 32 | } 33 | 34 | public void addEntity(Entity entity) { 35 | entities.add(entity); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/config/EventSenderConfig.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.config; 2 | 3 | public class EventSenderConfig { 4 | private int commonSize=20; 5 | private int failSize=10; 6 | private int maxFailTime=5; 7 | private int sleepTime=1000; 8 | public int getCommonSize() { 9 | return commonSize; 10 | } 11 | public void setCommonSize(int commonSize) { 12 | this.commonSize = commonSize; 13 | } 14 | public int getFailSize() { 15 | return failSize; 16 | } 17 | public void setFailSize(int failSize) { 18 | this.failSize = failSize; 19 | } 20 | public int getMaxFailTime() { 21 | return maxFailTime; 22 | } 23 | public void setMaxFailTime(int maxFailTime) { 24 | this.maxFailTime = maxFailTime; 25 | } 26 | public int getSleepTime() { 27 | return sleepTime; 28 | } 29 | public void setSleepTime(int sleepTime) { 30 | this.sleepTime = sleepTime; 31 | } 32 | 33 | } -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/utils/json/EntityObjectWriterProvider.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.utils.json; 2 | 3 | import com.alibaba.fastjson2.writer.ObjectWriter; 4 | import com.alibaba.fastjson2.writer.ObjectWriterProvider; 5 | import com.zhaofujun.nest.ddd.Entity; 6 | import com.zhaofujun.nest.ddd.Identifier; 7 | 8 | import java.lang.reflect.Type; 9 | @SuppressWarnings("rawtypes") 10 | public class EntityObjectWriterProvider extends ObjectWriterProvider { 11 | 12 | EntityObjectWriterAdapter objectWriterAdapter = new EntityObjectWriterAdapter<>(); 13 | 14 | @Override 15 | public ObjectWriter getObjectWriter(Type objectType, Class objectClass, boolean fieldBased) { 16 | ObjectWriter objectWriter = super.getObjectWriter(objectType, objectClass, fieldBased); 17 | if (Entity.class.isAssignableFrom(objectClass)) { 18 | objectWriterAdapter.setObjectWriter(objectWriter); 19 | return objectWriterAdapter; 20 | } 21 | return objectWriter; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/config/EventConfig.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.config; 2 | 3 | import java.util.List; 4 | 5 | import com.zhaofujun.nest.ddd.event.EventItem; 6 | 7 | public class EventConfig { 8 | private List eventItems; 9 | private EventHandlerConfig handlerConfig; 10 | private EventSenderConfig senderConfig; 11 | 12 | public List getEventItems() { 13 | return eventItems; 14 | } 15 | 16 | public void setEventItems(List eventItems) { 17 | this.eventItems = eventItems; 18 | } 19 | 20 | public EventHandlerConfig getHandlerConfig() { 21 | return handlerConfig; 22 | } 23 | 24 | public void setHandlerConfig(EventHandlerConfig handlerConfig) { 25 | this.handlerConfig = handlerConfig; 26 | } 27 | 28 | public EventSenderConfig getSenderConfig() { 29 | return senderConfig; 30 | } 31 | 32 | public void setSenderConfig(EventSenderConfig senderConfig) { 33 | this.senderConfig = senderConfig; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/event/EventData.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.event; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * 事件数据类,用于封装事件的数据。 7 | * 该类将被序列化后通过事件通道传送 8 | * 9 | * @param 事件数据类型 10 | */ 11 | public class EventData implements Serializable { 12 | /** 13 | * 事件ID。 14 | */ 15 | private String id; 16 | 17 | /** 18 | * 事件数据。 19 | */ 20 | private T data; 21 | 22 | /** 23 | * 获取事件ID。 24 | * 25 | * @return 事件ID 26 | */ 27 | public String getId() { 28 | return id; 29 | } 30 | 31 | /** 32 | * 设置事件ID。 33 | * 34 | * @param id 事件ID 35 | */ 36 | public void setId(String id) { 37 | this.id = id; 38 | } 39 | 40 | /** 41 | * 获取事件数据。 42 | * 43 | * @return 事件数据 44 | */ 45 | public T getData() { 46 | return data; 47 | } 48 | 49 | /** 50 | * 设置事件数据。 51 | * 52 | * @param data 事件数据 53 | */ 54 | public void setData(T data) { 55 | this.data = data; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/event/EventItem.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.event; 2 | 3 | /** 4 | * 事件项,定义一个事件将要使用什么通道传输 5 | */ 6 | public class EventItem { 7 | /** 8 | * 事件名称。 9 | */ 10 | private String eventName; 11 | 12 | /** 13 | * 通道代码。 14 | */ 15 | private String channelCode; 16 | 17 | /** 18 | * 获取事件名称。 19 | * 20 | * @return 事件名称 21 | */ 22 | public String getEventName() { 23 | return eventName; 24 | } 25 | 26 | /** 27 | * 设置事件名称。 28 | * 29 | * @param eventName 事件名称 30 | */ 31 | public void setEventName(String eventName) { 32 | this.eventName = eventName; 33 | } 34 | 35 | /** 36 | * 获取通道代码。 37 | * 38 | * @return 通道代码 39 | */ 40 | public String getChannelCode() { 41 | return channelCode; 42 | } 43 | 44 | /** 45 | * 设置通道代码。 46 | * 47 | * @param channelCode 通道代码 48 | */ 49 | public void setChannelCode(String channelCode) { 50 | this.channelCode = channelCode; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/src/main/java/com/zhaofujun/nest/boot/ApplicationStartedListener.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.boot; 2 | 3 | import org.springframework.boot.context.event.ApplicationStartedEvent; 4 | import org.springframework.boot.context.logging.LoggingApplicationListener; 5 | import org.springframework.context.ApplicationListener; 6 | import org.springframework.core.Ordered; 7 | import org.springframework.stereotype.Component; 8 | 9 | import com.zhaofujun.nest.NestEngine; 10 | import com.zhaofujun.nest.ddd.event.EventAppService; 11 | import com.zhaofujun.nest.ddd.event.EventMessageRepository; 12 | import com.zhaofujun.nest.provider.Container; 13 | 14 | @Component 15 | public class ApplicationStartedListener implements ApplicationListener, Ordered { 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | @Override 24 | public void onApplicationEvent(ApplicationStartedEvent event) { 25 | 26 | 27 | } 28 | 29 | @Override 30 | public int getOrder() { 31 | return LoggingApplicationListener.DEFAULT_ORDER + 1; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/DomainObject.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd; 2 | 3 | /** 4 | * 表示领域对象的抽象类。 5 | * 领域对象是领域驱动设计(DDD)中的一个基本概念,它代表了业务领域中的一个实体或值对象。 6 | */ 7 | public interface DomainObject { 8 | /** 9 | * 获取当前对象的类名。 10 | * 11 | * @return 当前对象的类名。 12 | */ 13 | default String getClassName() { 14 | final String PROXY_SPLIT_STR = "$$"; 15 | final int BEGIN_INDEX = 0; 16 | 17 | String className = this.getClass().getName(); 18 | int endIndex = className.indexOf(PROXY_SPLIT_STR); 19 | return endIndex == -1 ? className : className.substring(BEGIN_INDEX, endIndex); 20 | } 21 | 22 | /** 23 | * 获取当前对象的简单类名。 24 | * 25 | * @return 当前对象的简单类名。 26 | */ 27 | default String getClassSimpleName() { 28 | final String PROXY_SPLIT_STR = "$$"; 29 | final int BEGIN_INDEX = 0; 30 | 31 | String className = this.getClass().getSimpleName(); 32 | int endIndex = className.indexOf(PROXY_SPLIT_STR); 33 | return endIndex == -1 ? className : className.substring(BEGIN_INDEX, endIndex); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/event/PushChannelConsumer.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.event; 2 | 3 | import java.util.Collection; 4 | import com.zhaofujun.nest.ddd.EventHandler; 5 | 6 | public abstract class PushChannelConsumer implements ChannelConsumer { 7 | 8 | private EventAppService appService; 9 | 10 | @Override 11 | public void setEventAppService(EventAppService appService) { 12 | this.appService = appService; 13 | } 14 | /** 15 | * 并且为每eventHandler创建一个EventConsumer, 16 | * 17 | * 18 | * @param eventName 19 | * @param eventHandlers 20 | */ 21 | public void register(String eventName, Collection eventHandlers) { 22 | for (EventHandler handler : eventHandlers) { 23 | MessageProcessor eventConsumer = new MessageProcessor<>(handler,appService); 24 | subscribe(eventConsumer); 25 | } 26 | } 27 | 28 | /** 29 | * 订阅 consumer,在回调中执行 consumer.invoke() 30 | * 根据 invoke 返回值处理消息确认方式 31 | * 32 | * @param consumer 33 | */ 34 | protected abstract void subscribe(MessageProcessor consumer); 35 | } -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/utils/EntityUtil.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.utils; 2 | 3 | import com.zhaofujun.nest.ddd.AggregateRoot; 4 | import com.zhaofujun.nest.ddd.Entity; 5 | import com.zhaofujun.nest.ddd.Identifier; 6 | import com.zhaofujun.nest.ddd.context.EntityLoader; 7 | 8 | import java.util.Collection; 9 | 10 | public class EntityUtil { 11 | 12 | public static , I extends Identifier> T load(Class clazz, I identifier) { 13 | T entity = EntityLoader.load(clazz, identifier); 14 | return entity; 15 | } 16 | 17 | public static String getKey(Class clazz, Identifier identifier) { 18 | final String PROXY_SPLIT_STR = "$$"; 19 | final int BEGIN_INDEX = 0; 20 | 21 | String className = clazz.getName(); 22 | int endIndex = className.indexOf(PROXY_SPLIT_STR); 23 | className = endIndex == -1 ? className : className.substring(BEGIN_INDEX, endIndex); 24 | return className + "_" + identifier.toValue(); 25 | } 26 | 27 | public static String getKey(Entity entity) { 28 | return getKey(entity.getClass(), entity.getId()); 29 | } 30 | 31 | } -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/utils/LockUtil.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.utils; 2 | 3 | import java.util.function.Supplier; 4 | import com.zhaofujun.nest.provider.LockProvider; 5 | import com.zhaofujun.nest.NestConst; 6 | import com.zhaofujun.nest.manager.ProviderManager; 7 | 8 | /** 9 | * 锁工具类。 10 | * 11 | * @author zhaofujun 12 | */ 13 | public class LockUtil { 14 | 15 | /** 16 | * 执行锁操作。 17 | * 18 | * @param name 锁名称 19 | * @param runnable 锁内执行的代码 20 | * @return 锁内执行的代码返回值 21 | */ 22 | public static T lock(String name, Supplier runnable) { 23 | return lock(name, NestConst.defaultLockProvider, runnable); 24 | } 25 | 26 | /** 27 | * 执行锁操作。 28 | * 29 | * @param name 锁名称 30 | * @param provider 锁提供者名称 31 | * @param supplier 锁内执行的代码 32 | * @return 锁内执行的代码返回值 33 | */ 34 | public static T lock(String name, String provider, Supplier supplier) { 35 | var lockProvider = ProviderManager.get(LockProvider.class, provider, NestConst.defaultLockProvider); 36 | return lockProvider.lock(name, () -> supplier.get()); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/src/main/java/com/zhaofujun/nest/boot/SpringTransaction.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.boot; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.transaction.PlatformTransactionManager; 5 | import org.springframework.transaction.TransactionDefinition; 6 | import org.springframework.transaction.TransactionStatus; 7 | import org.springframework.transaction.support.DefaultTransactionDefinition; 8 | 9 | import com.zhaofujun.nest.ddd.context.Transaction; 10 | 11 | 12 | public class SpringTransaction implements Transaction { 13 | 14 | @Autowired 15 | PlatformTransactionManager transcationManager; 16 | 17 | private TransactionStatus status; 18 | 19 | @Override 20 | public void commit() { 21 | transcationManager.commit(status); 22 | } 23 | 24 | @Override 25 | public void begin() { 26 | TransactionDefinition def = new DefaultTransactionDefinition(); 27 | status = transcationManager.getTransaction(def); 28 | } 29 | 30 | @Override 31 | public void rollback() { 32 | transcationManager.rollback(status); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/event/EventChannelProvider.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.event; 2 | 3 | import com.zhaofujun.nest.ddd.ConsumeMode; 4 | import com.zhaofujun.nest.provider.Provider; 5 | 6 | /** 7 | * 事件通道提供者接口 8 | * 每一个事件通道对应一个第三方消息中间件的接入方式 9 | */ 10 | public interface EventChannelProvider extends Provider { 11 | 12 | /** 13 | * 提交事件数据到事件通道。 14 | * 15 | * @param messageGroup 事件组名称 16 | * @param dataObject 事件数据对象 17 | */ 18 | void commit(String messageGroup, EventData dataObject); 19 | 20 | /** 21 | * 获取事件通道消费者。 22 | * 23 | * @param mode 消费模式 24 | * @return 事件通道消费者 25 | */ 26 | default ChannelConsumer getConsumer(ConsumeMode mode) { 27 | if (mode == ConsumeMode.PULL) 28 | return getPullChannelConsumer(); 29 | else 30 | return getPushChannelConsumer(); 31 | } 32 | 33 | /** 34 | * 获取拉取模式的事件通道消费者。 35 | * 36 | * @return 拉取模式的事件通道消费者 37 | */ 38 | PullChannelConsumer getPullChannelConsumer(); 39 | 40 | /** 41 | * 获取推送模式的事件通道消费者。 42 | * 43 | * @return 推送模式的事件通道消费者 44 | */ 45 | PushChannelConsumer getPushChannelConsumer(); 46 | 47 | } 48 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/context/QueryContextBox.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.context; 2 | 3 | import java.util.Stack; 4 | 5 | public class QueryContextBox { 6 | private long threadId; 7 | private Stack stack; 8 | private QueryContextBox parent; 9 | 10 | public QueryContextBox(QueryContext queryContext, QueryContextBox parent) { 11 | this.threadId = Thread.currentThread().getId(); 12 | this.stack = new Stack<>(); 13 | this.stack.push(queryContext); 14 | this.parent = parent; 15 | } 16 | 17 | public boolean onlyOne() { 18 | return stack.size() == 1; 19 | } 20 | 21 | public QueryContext get() { 22 | return stack.peek(); 23 | } 24 | 25 | public QueryContext pop() { 26 | return stack.pop(); 27 | } 28 | 29 | public QueryContext push(QueryContext queryContext) { 30 | return stack.push(queryContext); 31 | } 32 | 33 | public long getThreadId() { 34 | return threadId; 35 | } 36 | 37 | public boolean owner(){ 38 | return this.threadId==Thread.currentThread().getId(); 39 | } 40 | 41 | public QueryContextBox getParent() { 42 | return parent; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /nest-generator/src/main/java/com/zhaofujun/nest/generator/model/NModel.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.generator.model; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | @Getter 10 | @Setter 11 | public class NModel extends NClass { 12 | private final List methods; 13 | private final List fields; 14 | private NModel parent; 15 | private final List children; 16 | 17 | public NModel(String packageName, String name ) { 18 | super(packageName, name); 19 | this.methods = new ArrayList(); 20 | this.fields = new ArrayList<>(); 21 | this.children = new ArrayList<>(); 22 | } 23 | 24 | public void addMethod(NMethod method) { 25 | methods.add(method); 26 | } 27 | 28 | public void addMethods(NMethod... methods) { 29 | for (NMethod method : methods) { 30 | addMethod(method); 31 | } 32 | } 33 | 34 | public void addField(NField field) { 35 | fields.add(field); 36 | } 37 | 38 | public void addFields(NField... fields) { 39 | for (NField field : fields) { 40 | addField(field); 41 | } 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter-redis/src/main/java/com/zhaofujun/nest/boot/redis/identifier/DailyRedisLongGenerator.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.boot.redis.identifier; 2 | 3 | import com.zhaofujun.nest.provider.LongGenerator; 4 | import org.springframework.data.redis.core.RedisTemplate; 5 | 6 | import java.time.LocalDate; 7 | import java.time.ZoneOffset; 8 | import java.util.concurrent.TimeUnit; 9 | 10 | public class DailyRedisLongGenerator implements LongGenerator { 11 | 12 | public final static String CODE = "DailyRedisLongGenerator"; 13 | 14 | private RedisTemplate redisTemplate; 15 | private String prefix="nest_redis_id_daily_"; 16 | 17 | public DailyRedisLongGenerator(RedisTemplate redisTemplate) { 18 | this.redisTemplate = redisTemplate; 19 | } 20 | 21 | @Override 22 | public String getCode() { 23 | return CODE; 24 | } 25 | 26 | @Override 27 | public Long nextValue(String key) { 28 | Long expireTime = LocalDate.now().atTime(23, 59, 59, 999).toInstant(ZoneOffset.of("+8")).toEpochMilli() - System.currentTimeMillis(); 29 | redisTemplate.expire(prefix+key, expireTime, TimeUnit.MILLISECONDS); 30 | return redisTemplate.opsForValue().increment(prefix+key); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/context/ServiceContextBox.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.context; 2 | 3 | import java.util.Stack; 4 | 5 | public class ServiceContextBox { 6 | private long threadId; 7 | private Stack stack; 8 | private ServiceContextBox parent; 9 | 10 | public ServiceContextBox(ServiceContext serviceContext, ServiceContextBox parent) { 11 | this.threadId = Thread.currentThread().getId(); 12 | this.stack = new Stack<>(); 13 | this.stack.push(serviceContext); 14 | this.parent = parent; 15 | } 16 | 17 | public boolean onlyOne() { 18 | return stack.size() == 1; 19 | } 20 | 21 | public ServiceContext get() { 22 | return stack.peek(); 23 | } 24 | 25 | public ServiceContext pop() { 26 | return stack.pop(); 27 | } 28 | 29 | public ServiceContext push(ServiceContext serviceContext) { 30 | return stack.push(serviceContext); 31 | } 32 | 33 | public long getThreadId() { 34 | return threadId; 35 | } 36 | 37 | public boolean owner(){ 38 | return this.threadId==Thread.currentThread().getId(); 39 | } 40 | 41 | public ServiceContextBox getParent() { 42 | return parent; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /nest-demo/nest-demo-app/src/main/java/com/zhaofujun/nest/demo/repositories/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.demo.repositories; 2 | 3 | import java.lang.reflect.Type; 4 | import org.springframework.stereotype.Component; 5 | 6 | import com.zhaofujun.nest.ddd.LongIdentifier; 7 | import com.zhaofujun.nest.ddd.Repository; 8 | import com.zhaofujun.nest.demo.appservices.model.User; 9 | 10 | @Component 11 | public class UserRepository implements Repository { 12 | 13 | @Override 14 | public void insert(User t) { 15 | System.out.println("新增 User,可以使用 DAO 方式操作数据库"); 16 | } 17 | 18 | @Override 19 | public void update(User t) { 20 | System.out.println("修改 User,可以使用 DAO 方式操作数据库"); 21 | 22 | } 23 | 24 | @Override 25 | public void delete(User t) { 26 | 27 | } 28 | 29 | @Override 30 | public Class getEntityClass() { 31 | return User.class; 32 | } 33 | 34 | @Override 35 | public User getEntityById(Class tClass, LongIdentifier identifier) { 36 | System.out.println("直接创建一个 User 类,模拟数据库查询"); 37 | 38 | User user = new User((LongIdentifier) identifier); 39 | user.setName("test"); 40 | user.setAge(10); 41 | return user; 42 | 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/ValueObject.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd; 2 | 3 | import java.io.Serializable; 4 | import java.util.Arrays; 5 | import java.util.Objects; 6 | 7 | /** 8 | * 值对象抽象类,继承自 DomainObject 类。 9 | */ 10 | public abstract class ValueObject implements DomainObject , Serializable { 11 | protected abstract Object[] getPropertiesForComparison(); 12 | 13 | @Override 14 | public boolean equals(Object o) { 15 | if (this == o) 16 | return true; 17 | if (o == null || !(o instanceof ValueObject)) 18 | return false; 19 | 20 | ValueObject other = (ValueObject) o; 21 | 22 | Object[] thisProperties = this.getPropertiesForComparison(); 23 | Object[] otherProperties = other.getPropertiesForComparison(); 24 | if (thisProperties.length != otherProperties.length) 25 | return false; 26 | for (int i = 0; i < thisProperties.length; i++) { 27 | if (!Objects.equals(thisProperties[i], otherProperties[i])) 28 | return false; 29 | } 30 | return true; 31 | 32 | } 33 | 34 | @Override 35 | public int hashCode() { 36 | Object[] properties = this.getPropertiesForComparison(); 37 | return Arrays.hashCode(properties); 38 | } 39 | } -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/EventHandler.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd; 2 | 3 | import com.zhaofujun.nest.exception.CustomException; 4 | 5 | /** 6 | * 事件处理器接口。 7 | * 8 | * @param 事件数据类型 9 | */ 10 | public interface EventHandler { 11 | /** 12 | * 获取事件名称。 13 | * 14 | * @return 事件名称 15 | */ 16 | String getEventName(); 17 | 18 | /** 19 | * 获取事件数据类。 20 | * 21 | * @return 事件数据类 22 | */ 23 | Class getEventDataClass(); 24 | 25 | /** 26 | * 获取消费模式。默认为PUSH。 27 | * 28 | * @return 消费模式 29 | */ 30 | default ConsumeMode getConsumeMode() { 31 | return ConsumeMode.PUSH; 32 | } 33 | 34 | /** 35 | * 处理事件数据。 36 | * 37 | * @param eventData 事件数据 38 | */ 39 | void handle(T eventData); 40 | 41 | /** 42 | * 处理系统异常。 43 | * 44 | * @param context 异常上下文 45 | * @param ex 异常对象 46 | */ 47 | default void onSystemException(Object context, Throwable ex) { 48 | ex.printStackTrace(); 49 | } 50 | 51 | /** 52 | * 处理自定义异常。 53 | * 54 | * @param context 异常上下文 55 | * @param ex 异常对象 56 | */ 57 | default void onCustomException(Object context, CustomException ex) { 58 | ex.printStackTrace(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/exception/CustomException.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.exception; 2 | 3 | 4 | /** 5 | * 自定义异常,与业务相关,如用户名或密码不匹配等 6 | * Created by zhaofujun on 2017/6/23. 7 | */ 8 | public abstract class CustomException extends RuntimeException { 9 | private int errorCode; 10 | 11 | public CustomException(int errorCode, String message, Object... arguments) { 12 | super(message); 13 | this.errorCode = errorCode; 14 | Object[] arguments1 = arguments; 15 | } 16 | 17 | public CustomException(int errorCode, String message, Throwable cause, Object... arguments) { 18 | super(message, cause); 19 | this.errorCode = errorCode; 20 | Object[] arguments1 = arguments; 21 | } 22 | 23 | public int getErrorCode() { 24 | return errorCode; 25 | } 26 | 27 | // public String toString() { 28 | // StringBuilder stringBuilder = new StringBuilder(this.getMessage() + "\r\n"); 29 | // stringBuilder.append("errorCode:" + errorCode + "\r\n"); 30 | // stringBuilder.append("输入参数:\r\n"); 31 | // for (Object argument : arguments) { 32 | // stringBuilder.append("\t" + JsonUtils.toJsonString(argument) + "\r\n"); 33 | // } 34 | // return stringBuilder.toString(); 35 | // } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /nest-generator/src/main/java/com/zhaofujun/nest/generator/generator/Generator.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.generator.generator; 2 | 3 | import com.zhaofujun.nest.generator.model.NEntity; 4 | import freemarker.template.Configuration; 5 | import freemarker.template.Template; 6 | import freemarker.template.TemplateException; 7 | 8 | import java.io.File; 9 | import java.io.IOException; 10 | import java.io.Writer; 11 | 12 | public abstract class Generator { 13 | public abstract Template getTemplate(Configuration cfg); 14 | 15 | public abstract Object getDataModel(NEntity nEntity); 16 | 17 | public abstract Writer getWriter(); 18 | 19 | 20 | public void generate(NEntity nEntity) throws IOException, TemplateException { 21 | //配置freemarker 22 | Configuration cfg = new Configuration(Configuration.VERSION_2_3_31); 23 | cfg.setDirectoryForTemplateLoading(new File("./templates")); 24 | cfg.setDefaultEncoding("UTF-8"); 25 | // cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW); 26 | 27 | //生成数据模型 28 | Object dataModel = getDataModel(nEntity); 29 | //读取模板 30 | Template temp = getTemplate(cfg); 31 | try (Writer writer = getWriter()) { 32 | temp.process(dataModel, writer); 33 | } 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/inner/DefaultLockProvider.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.inner; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import java.util.function.Supplier; 6 | 7 | import com.zhaofujun.nest.NestConst; 8 | import com.zhaofujun.nest.provider.LockProvider; 9 | 10 | /** 11 | * 默认的本地锁实现方式 12 | * 该方式会为每一个锁维护创建一个静态对象,并且使用该静态对象进行排他处理方式 13 | */ 14 | public class DefaultLockProvider implements LockProvider { 15 | 16 | private static Map lockMap = new HashMap<>(); 17 | 18 | /*** 19 | * 当存在对象的时候, 直接返回对象,不存在的时候创建一个新对象并返回 20 | * 21 | * @param name 22 | * @return 23 | */ 24 | private Object getLockObject(String name) { 25 | Object lockObject = lockMap.get(name); 26 | if (lockObject == null) { 27 | lockObject = new Object(); 28 | lockMap.put(name, lockObject); 29 | } 30 | return lockObject; 31 | 32 | } 33 | 34 | @Override 35 | public String getCode() { 36 | return NestConst.defaultLockProvider; 37 | } 38 | 39 | @Override 40 | public T lock(String name, Supplier runnable) { 41 | Object lockObject = getLockObject(name); 42 | synchronized (lockObject) { 43 | return runnable.get(); 44 | } 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/NestParameterizedType.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest; 2 | 3 | import java.lang.reflect.ParameterizedType; 4 | import java.lang.reflect.Type; 5 | 6 | public class NestParameterizedType implements ParameterizedType { 7 | private Type[] actualTypeArguments; 8 | private Type rawType; 9 | private Type ownerType; 10 | 11 | private NestParameterizedType(Type rawType, Type[] actualTypeArguments, Type ownerType) { 12 | this.actualTypeArguments = actualTypeArguments; 13 | this.rawType = rawType; 14 | this.ownerType = ownerType; 15 | } 16 | 17 | @Override 18 | public Type[] getActualTypeArguments() { 19 | return this.actualTypeArguments; 20 | } 21 | 22 | @Override 23 | public Type getRawType() { 24 | return this.rawType; 25 | } 26 | 27 | @Override 28 | public Type getOwnerType() { 29 | return this.ownerType; 30 | } 31 | 32 | public static ParameterizedType make(Class rawType, Type... actualTypeArguments) { 33 | return new NestParameterizedType(rawType, actualTypeArguments, null); 34 | } 35 | 36 | public static ParameterizedType make(Class rawType, Type[] actualTypeArguments, Type ownerType) { 37 | return new NestParameterizedType(rawType, actualTypeArguments, ownerType); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/utils/MessageUtil.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.utils; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import com.zhaofujun.nest.utils.message.Listener; 7 | import com.zhaofujun.nest.utils.message.MessageObserver; 8 | 9 | public class MessageUtil { 10 | private static Map observerMap = new HashMap<>(); 11 | 12 | static MessageObserver getMessageObserver(String messageName) { 13 | MessageObserver observer = observerMap.get(messageName); 14 | if (observer == null) { 15 | observer = new MessageObserver(messageName); 16 | observerMap.put(messageName, observer); 17 | } 18 | return observer; 19 | } 20 | public static void emit(String messageName,Object object){ 21 | MessageObserver messageObserver = getMessageObserver(messageName); 22 | messageObserver.emit(object); 23 | } 24 | public static void on(String messageName,Listener listener){ 25 | MessageObserver messageObserver = getMessageObserver(messageName); 26 | messageObserver.on(listener); 27 | } 28 | public static void on(String messageName,Class tClass, Listener listener){ 29 | MessageObserver messageObserver = getMessageObserver(messageName); 30 | messageObserver.on(tClass,listener); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/src/main/java/com/zhaofujun/nest/boot/NestApplicationContextAware.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.boot; 2 | 3 | import com.zhaofujun.nest.NestEngine; 4 | import com.zhaofujun.nest.ddd.event.EventAppService; 5 | import com.zhaofujun.nest.ddd.event.EventMessageRepository; 6 | import com.zhaofujun.nest.provider.Container; 7 | import org.springframework.beans.BeansException; 8 | import org.springframework.context.ApplicationContext; 9 | import org.springframework.context.ApplicationContextAware; 10 | import org.springframework.stereotype.Component; 11 | 12 | @Component 13 | public class NestApplicationContextAware implements ApplicationContextAware { 14 | @Override 15 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 16 | EventAppService eventAppService = applicationContext.getBean(EventAppService.class); 17 | 18 | EventMessageRepository eventMessageRepository = applicationContext.getBean(EventMessageRepository.class); 19 | 20 | Container container = applicationContext.getBean(Container.class); 21 | 22 | // 容器启动成功后, 初始化 NestEngine 23 | NestEngine nestEngine = new NestEngine(); 24 | nestEngine.initEventEnvironment(eventAppService, eventMessageRepository); 25 | nestEngine.registerByContainer(container); 26 | nestEngine.start(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /nest-ddd/src/test/java/com/zhaofujun/nest/test/UserTest.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.test; 2 | 3 | import static org.junit.jupiter.api.Assertions.*; 4 | 5 | import org.junit.jupiter.api.BeforeAll; 6 | import org.junit.jupiter.api.Test; 7 | 8 | import com.zhaofujun.nest.NestEngine; 9 | import com.zhaofujun.nest.ddd.event.EventAppService; 10 | import com.zhaofujun.nest.inner.DefaultEventInfoRepository; 11 | import com.zhaofujun.nest.utils.AppServiceUtil; 12 | 13 | public class UserTest { 14 | 15 | @BeforeAll 16 | public static void initEngine() throws Throwable { 17 | NestEngine nestEngine = new NestEngine(); 18 | 19 | EventAppService eventAppService = AppServiceUtil.create(EventAppService.class); 20 | DefaultEventInfoRepository eventInfoRepository = new DefaultEventInfoRepository(); 21 | 22 | nestEngine.initEventEnvironment(eventAppService, eventInfoRepository); 23 | 24 | // 注册事件处理器 25 | nestEngine.registerEventHandler(new UserCreatedHandler()); 26 | 27 | // 启动引擎 28 | nestEngine.start(); 29 | } 30 | 31 | @Test 32 | public void createUser() throws Throwable { 33 | 34 | // 创建化用户应用服务 35 | DefaultUserAppService userAppService = AppServiceUtil.create(DefaultUserAppService.class); 36 | UserDto userDto = userAppService.create("1111", "Li lei"); 37 | 38 | assertEquals("111", userDto.getId()); 39 | assertEquals("Li lei", userDto.getName()); 40 | 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/manager/ProviderManager.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.manager; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collection; 5 | import java.util.List; 6 | import java.util.concurrent.CopyOnWriteArrayList; 7 | import java.util.stream.Collectors; 8 | 9 | import com.zhaofujun.nest.provider.Provider; 10 | 11 | public class ProviderManager { 12 | private static List providerList = new CopyOnWriteArrayList<>(); 13 | 14 | public static void addProvider(Collection providers) { 15 | providerList.addAll(providers); 16 | } 17 | 18 | public static void addProvider(Provider... providers) { 19 | providerList.addAll(Arrays.asList(providers)); 20 | } 21 | 22 | public static T get(Class tClass, String code) { 23 | return (T) providerList 24 | .stream() 25 | .filter(p -> tClass.isAssignableFrom(p.getClass()) && p.getCode().equals(code)) 26 | .findFirst() 27 | .orElse(null); 28 | } 29 | 30 | public static T get(Class tClass, String code, String elseCode) { 31 | T t = get(tClass, code); 32 | if (t == null) 33 | t = get(tClass, elseCode); 34 | return t; 35 | } 36 | 37 | public static List getList(Class tClass) { 38 | return providerList.stream() 39 | .filter(p -> tClass.isAssignableFrom(p.getClass())) 40 | .map(p -> (T) p) 41 | .collect(Collectors.toList()); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/manager/RepositoryManager.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.manager; 2 | 3 | import java.lang.reflect.Type; 4 | import java.util.Arrays; 5 | import java.util.Collection; 6 | import java.util.Map; 7 | import java.util.concurrent.ConcurrentHashMap; 8 | 9 | import com.zhaofujun.nest.ddd.Entity; 10 | import com.zhaofujun.nest.ddd.Identifier; 11 | import com.zhaofujun.nest.ddd.Repository; 12 | 13 | public class RepositoryManager { 14 | 15 | private static Map> repositoryMap = new ConcurrentHashMap<>(); 16 | 17 | 18 | public static void addRepository(Repository... repositories) { 19 | addRepository(Arrays.asList(repositories)); 20 | } 21 | 22 | public static void addRepository(Collection repositories) { 23 | repositories.forEach(repository -> { 24 | repositoryMap.put(repository.getEntityClass(), repository); 25 | }); 26 | } 27 | 28 | public static , I extends Identifier> Repository getRepository(Class tClass) { 29 | 30 | 31 | Repository repository = (Repository) repositoryMap.get(tClass); 32 | 33 | if (repository == null) { 34 | // 如果当前类没有找到对应的Repository,尝试查找父类的Repository 35 | //这里会一直找到Entity类的Repository,系统需要默认配置一个EntityRepository 36 | Class superClass = tClass.getSuperclass(); 37 | if (superClass != null && Entity.class.isAssignableFrom(superClass)) { 38 | return getRepository((Class) superClass); 39 | } 40 | 41 | } 42 | return repository; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/utils/json/EntityObjectReaderProvider.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.utils.json; 2 | 3 | import com.alibaba.fastjson2.reader.ObjectReader; 4 | import com.alibaba.fastjson2.reader.ObjectReaderProvider; 5 | import com.zhaofujun.nest.ddd.Entity; 6 | 7 | import java.lang.reflect.Type; 8 | 9 | @SuppressWarnings("rawtypes") 10 | public class EntityObjectReaderProvider extends ObjectReaderProvider { 11 | EntityObjectReaderAdapter entityObjectReaderAdapter = new EntityObjectReaderAdapter(); 12 | 13 | @Override 14 | public ObjectReader getObjectReader(Type objectType, boolean fieldBased) { 15 | ObjectReader objectReader = super.getObjectReader(objectType, fieldBased); 16 | if (objectReader != null && objectReader.getObjectClass() != null 17 | && Entity.class.isAssignableFrom(objectReader.getObjectClass())) { 18 | entityObjectReaderAdapter.setObjectReader(objectReader); 19 | return entityObjectReaderAdapter; 20 | } 21 | return objectReader; 22 | } 23 | 24 | @Override 25 | public ObjectReader getObjectReader(long hashCode) { 26 | 27 | ObjectReader objectReader = super.getObjectReader(hashCode); 28 | if (objectReader == null) 29 | return null; 30 | 31 | if (objectReader != null && objectReader.getObjectClass() != null 32 | && Entity.class.isAssignableFrom(objectReader.getObjectClass())) { 33 | entityObjectReaderAdapter.setObjectReader(objectReader); 34 | return entityObjectReaderAdapter; 35 | } 36 | return objectReader; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/src/main/java/com/zhaofujun/nest/boot/NestAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.boot; 2 | 3 | import org.springframework.boot.autoconfigure.AutoConfiguration; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.ComponentScan; 6 | import org.springframework.context.annotation.Import; 7 | 8 | import com.zhaofujun.nest.ddd.context.Transaction; 9 | import com.zhaofujun.nest.ddd.event.EventAppService; 10 | import com.zhaofujun.nest.ddd.event.EventMessageQuery; 11 | import com.zhaofujun.nest.ddd.event.EventMessageRepository; 12 | import com.zhaofujun.nest.inner.DefaultEventInfoRepository; 13 | 14 | @Import(NestBeanScannerRegistrar.class) 15 | @AutoConfiguration 16 | @ComponentScan 17 | public class NestAutoConfiguration { 18 | 19 | public NestAutoConfiguration() { 20 | System.out.println("NestAutoConfiguration init"); 21 | } 22 | 23 | @Bean 24 | public EventMessageRepository eventInfoQuery() { 25 | return new DefaultEventInfoRepository(); 26 | } 27 | 28 | @Bean 29 | public EventAppService eventAppService(EventMessageQuery eventInfoQuery) { 30 | EventAppService eventAppService = new EventAppService(); 31 | eventAppService.setQuery(eventInfoQuery); 32 | return eventAppService; 33 | } 34 | 35 | @Bean 36 | public Transaction.DefaultTransaction defaultTransaction() { 37 | return new Transaction.DefaultTransaction(); 38 | } 39 | 40 | // @Bean 41 | // public SpringTransaction springTransaction(){ 42 | // return new SpringTransaction(); 43 | // } 44 | } 45 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/context/Comparators.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.context; 2 | 3 | import java.util.Comparator; 4 | 5 | import com.zhaofujun.nest.ddd.Entity; 6 | import com.zhaofujun.nest.ddd.Repository; 7 | 8 | public class Comparators { 9 | 10 | private static RepositoryComparator repositoryComparator = new RepositoryComparator(); 11 | private static EntityComparator entityComparator = new EntityComparator(); 12 | 13 | public static RepositoryComparator getRepositoryComparator() { 14 | return repositoryComparator; 15 | } 16 | 17 | public static EntityComparator getEntityComparator() { 18 | return entityComparator; 19 | } 20 | 21 | public static class RepositoryComparator implements Comparator { 22 | 23 | @Override 24 | public int compare(Repository o1, 25 | Repository o2) { 26 | if (o1 == null && o2 != null) 27 | return -1; 28 | if (o1 != null && o2 == null) 29 | return 1; 30 | if (o1 == null && o2 == null) 31 | return 0; 32 | return o1.hashCode() - o2.hashCode(); 33 | } 34 | 35 | } 36 | 37 | public static class EntityComparator implements Comparator { 38 | 39 | @Override 40 | public int compare(Entity o1, Entity o2) { 41 | if (o1 == null && o2 != null) 42 | return -1; 43 | if (o1 != null && o2 == null) 44 | return 1; 45 | if (o1 == null && o2 == null) 46 | return 0; 47 | return o1.getId().toValue().compareTo(o2.getId().toValue()); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/context/ServiceMethodProcessor.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.context; 2 | 3 | import com.zhaofujun.nest.exception.CustomException; 4 | import com.zhaofujun.nest.exception.CustomExceptionable; 5 | import com.zhaofujun.nest.exception.SystemException; 6 | 7 | /** 8 | * 服务方法处理器,当执行应用服务方法后会执行本方法 9 | */ 10 | public class ServiceMethodProcessor { 11 | private MethodInvoker methodInvoker; 12 | private Transaction transaction; 13 | 14 | public ServiceMethodProcessor(MethodInvoker methodInvoker, Transaction transaction) { 15 | this.methodInvoker = methodInvoker; 16 | this.transaction = transaction; 17 | } 18 | 19 | public Object doInvoke() throws Throwable { 20 | 21 | ServiceContext serviceContext = ServiceContextManager.newServiceContext(); 22 | 23 | Object result = null; 24 | 25 | serviceContext.begin(); 26 | transaction.begin(); 27 | try { 28 | result = methodInvoker.invoke(); 29 | serviceContext.submit(); 30 | } catch (CustomException | SystemException ex) { 31 | transaction.rollback(); 32 | throw ex; 33 | } catch (Throwable ex) { 34 | transaction.rollback(); 35 | // 其它异常以系统异常抛出 36 | if (ex instanceof CustomExceptionable) { 37 | // 业务处理异常 38 | throw ex; 39 | } else { 40 | // 系统处理异常 41 | throw new SystemException("系统异常", ex); 42 | } 43 | } finally { 44 | serviceContext.end(); 45 | ServiceContextManager.pop(); 46 | } 47 | transaction.commit(); 48 | return result; 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/context/QueryContextManager.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.context; 2 | 3 | import com.alibaba.ttl.TransmittableThreadLocal; 4 | 5 | public class QueryContextManager { 6 | private static TransmittableThreadLocal threadLocal = new TransmittableThreadLocal<>(); 7 | 8 | public static QueryContext newServiceContext( ) { 9 | QueryContext queryContext = new QueryContext(); 10 | QueryContextBox queryContextBox = threadLocal.get(); 11 | if (queryContextBox == null) { 12 | queryContextBox = new QueryContextBox(queryContext, null); 13 | threadLocal.set(queryContextBox); 14 | } else { 15 | if (queryContextBox.owner()) { 16 | queryContextBox.push(queryContext); 17 | } else { 18 | QueryContextBox newBox = new QueryContextBox(queryContext, queryContextBox); 19 | threadLocal.set(newBox); 20 | } 21 | } 22 | return queryContext; 23 | } 24 | 25 | public static QueryContext getCurrentContext() { 26 | QueryContextBox queryContextBox = threadLocal.get(); 27 | if (queryContextBox == null) 28 | return null; 29 | return queryContextBox.get(); 30 | } 31 | 32 | public static void pop() { 33 | QueryContextBox queryContextBox = threadLocal.get(); 34 | if (queryContextBox == null) 35 | return; 36 | if (queryContextBox.owner()) { 37 | if (queryContextBox.onlyOne()) { 38 | threadLocal.set(queryContextBox.getParent()); 39 | } else { 40 | queryContextBox.pop(); 41 | } 42 | } 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/manager/EventManager.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.manager; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.Collection; 6 | import java.util.List; 7 | import java.util.stream.Collectors; 8 | 9 | import com.zhaofujun.nest.NestConst; 10 | import com.zhaofujun.nest.ddd.event.EventItem; 11 | 12 | public class EventManager { 13 | private static List eventList = new ArrayList<>(); 14 | 15 | public static void addEventItem(EventItem... eventItems) { 16 | addEventItem(Arrays.asList(eventItems)); 17 | } 18 | 19 | public static void checkEventName(String eventName) { 20 | // 检查事件,如果没有配置通道的话,自动配置到默认通道 21 | if (eventList.stream().filter(p -> p.getEventName().equals(eventName)).count() == 0) { 22 | var eventItem = new EventItem(); 23 | eventItem.setChannelCode(NestConst.defaultChannel); 24 | eventItem.setEventName(eventName); 25 | eventList.add(eventItem); 26 | } 27 | } 28 | 29 | public static void addEventItem(Collection eventItems) { 30 | eventList.addAll(eventItems); 31 | } 32 | 33 | public static List getEventNames(String channelCode) { 34 | return eventList.stream() 35 | .filter(p -> p.getChannelCode().equals(channelCode)) 36 | .map(p -> p.getEventName()) 37 | .collect(Collectors.toList()); 38 | } 39 | 40 | public static String getChannelCode(String eventName) { 41 | return eventList.stream() 42 | .filter(p -> p.getEventName().equals(eventName)) 43 | .map(p -> p.getChannelCode()) 44 | .findFirst() 45 | .orElse(NestConst.defaultChannel); 46 | } 47 | } -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/event/EventMessageModel.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.event; 2 | 3 | import java.time.LocalDateTime; 4 | 5 | import com.zhaofujun.nest.ddd.AggregateRoot; 6 | import com.zhaofujun.nest.ddd.LongIdentifier; 7 | 8 | /** 9 | * 事件消息,用于事件信息的存储,这是发送到消息仓储中的实体 10 | */ 11 | public class EventMessageModel extends AggregateRoot { 12 | private T eventData; 13 | private String eventName; 14 | private LocalDateTime sendTime; 15 | private EventState eventState; 16 | private int sendTimes; 17 | private LocalDateTime realTime; 18 | 19 | public EventMessageModel(LongIdentifier id, String eventName, T eventData, LocalDateTime sendTime) { 20 | super(id); 21 | this.eventData = eventData; 22 | this.eventName = eventName; 23 | this.sendTime = sendTime; 24 | eventState = EventState.preSend; 25 | } 26 | 27 | public T getEventData() { 28 | return eventData; 29 | } 30 | 31 | public String getEventName() { 32 | return eventName; 33 | } 34 | 35 | public LocalDateTime getSendTime() { 36 | return sendTime; 37 | } 38 | 39 | public EventState getEventState() { 40 | return eventState; 41 | } 42 | 43 | public int getSendTimes() { 44 | return sendTimes; 45 | } 46 | 47 | public LocalDateTime getRealTime() { 48 | return realTime; 49 | } 50 | 51 | public void publish() { 52 | this.realTime = LocalDateTime.now(); 53 | this.eventState=EventState.sent; 54 | } 55 | 56 | public void readyPublish() { 57 | this.eventState = EventState.sending; 58 | this.sendTimes++; 59 | } 60 | 61 | public void fail() { 62 | this.eventState = EventState.sendFail; 63 | } 64 | } -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/context/ServiceContextManager.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.context; 2 | 3 | import com.alibaba.ttl.TransmittableThreadLocal; 4 | 5 | /** 6 | * 服务上下文管理器 7 | */ 8 | public class ServiceContextManager { 9 | 10 | private static TransmittableThreadLocal threadLocal = new TransmittableThreadLocal<>(); 11 | 12 | public static ServiceContext newServiceContext( ) { 13 | ServiceContext serviceContext = new ServiceContext(); 14 | ServiceContextBox serviceContextBox = threadLocal.get(); 15 | if (serviceContextBox == null) { 16 | serviceContextBox = new ServiceContextBox(serviceContext, null); 17 | threadLocal.set(serviceContextBox); 18 | } else { 19 | if (serviceContextBox.owner()) { 20 | serviceContextBox.push(serviceContext); 21 | } else { 22 | ServiceContextBox newBox = new ServiceContextBox(serviceContext, serviceContextBox); 23 | threadLocal.set(newBox); 24 | } 25 | } 26 | return serviceContext; 27 | } 28 | 29 | public static ServiceContext getCurrentContext() { 30 | ServiceContextBox serviceContextBox = threadLocal.get(); 31 | if (serviceContextBox == null) 32 | return null; 33 | return serviceContextBox.get(); 34 | } 35 | 36 | public static void pop() { 37 | ServiceContextBox serviceContextBox = threadLocal.get(); 38 | if (serviceContextBox == null) 39 | return; 40 | if (serviceContextBox.owner()) { 41 | if (serviceContextBox.onlyOne()) { 42 | threadLocal.set(serviceContextBox.getParent()); 43 | } else { 44 | serviceContextBox.pop(); 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter-activemq/src/main/java/com/zhaofujun/nest/boot/activemq/ActivemqPullConsumer.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.boot.activemq; 2 | 3 | import org.apache.activemq.command.ActiveMQQueue; 4 | import org.springframework.jms.core.JmsTemplate; 5 | 6 | import com.zhaofujun.nest.ddd.event.EventData; 7 | import com.zhaofujun.nest.ddd.event.MessageAck; 8 | import com.zhaofujun.nest.ddd.event.MessageProcessor; 9 | import com.zhaofujun.nest.ddd.event.PullChannelConsumer; 10 | import com.zhaofujun.nest.utils.JsonUtil; 11 | 12 | import jakarta.jms.JMSException; 13 | import jakarta.jms.Message; 14 | import jakarta.jms.Queue; 15 | import jakarta.jms.Session; 16 | import jakarta.jms.TextMessage; 17 | 18 | public class ActivemqPullConsumer extends PullChannelConsumer { 19 | 20 | private JmsTemplate jmsTemplate; 21 | 22 | public ActivemqPullConsumer(JmsTemplate jmsTemplate) { 23 | this.jmsTemplate = jmsTemplate; 24 | } 25 | 26 | @Override 27 | public boolean pull(MessageProcessor eventConsumer) { 28 | Queue queue = new ActiveMQQueue( 29 | "Consumer." + eventConsumer.getHandlerId() + ".VirtualTopic." + eventConsumer.getEventName()); 30 | jmsTemplate.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE); 31 | try { 32 | Message message = jmsTemplate.receive(queue); 33 | TextMessage textMessage = (TextMessage) message; 34 | EventData eventData = JsonUtil.parseObject(textMessage.getText(), EventData.class); 35 | MessageAck messageAck = eventConsumer.invoke(eventData); 36 | if (messageAck.equals(MessageAck.SUCCESS)) { 37 | message.acknowledge(); 38 | return true; 39 | } 40 | return false; 41 | } catch (JMSException ex) { 42 | return false; 43 | } 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/event/EventSenderWorker.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.event; 2 | 3 | import java.util.List; 4 | 5 | import com.zhaofujun.nest.config.EventSenderConfig; 6 | import com.zhaofujun.nest.ddd.LongIdentifier; 7 | import com.zhaofujun.nest.utils.LockUtil; 8 | import com.zhaofujun.nest.NestConst; 9 | 10 | public class EventSenderWorker extends Thread { 11 | 12 | private int commonSize; 13 | private int failSize; 14 | private int maxFailTime; 15 | private int sleepTime; 16 | private EventAppService appService; 17 | 18 | public EventSenderWorker(EventSenderConfig sendConfig, 19 | EventAppService appService) { 20 | super("事件发布工作线程"); 21 | this.commonSize = sendConfig.getCommonSize(); 22 | this.failSize = sendConfig.getFailSize(); 23 | this.maxFailTime = sendConfig.getMaxFailTime(); 24 | this.sleepTime = sendConfig.getSleepTime(); 25 | this.appService = appService; 26 | } 27 | 28 | @SuppressWarnings("static-access") 29 | @Override 30 | public void run() { 31 | 32 | while (!Thread.currentThread().isInterrupted()) { 33 | 34 | // 从仓储获取EventInfo(待发送20条,失败信息10条,失败次数超过5次后将不再处理) 35 | // 增加处理次数,状态设置为处理中 36 | // 本过程可能存同步问题,需要使用锁/分布式锁 37 | List identifiers = LockUtil.lock(NestConst.eventSenderLock, () -> { 38 | return appService.getEventInfoList(commonSize, failSize, maxFailTime); 39 | }); 40 | 41 | // 通过事件通道发送事件,并更新仓储中的 EventInfo状态为已完成或失败,新增推送时间 42 | identifiers.forEach(id -> appService.sendEventInfo(id)); 43 | 44 | try { 45 | Thread.currentThread().sleep(sleepTime); 46 | } catch (InterruptedException e) { 47 | Thread.currentThread().interrupt(); 48 | } 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/Repository.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd; 2 | 3 | import java.io.Serializable; 4 | import java.lang.reflect.Type; 5 | import java.util.Collection; 6 | 7 | /** 8 | * 仓储接口,定义了对实体的基本 CRUD 操作。 9 | * 10 | * @param 实体类型 11 | */ 12 | public interface Repository, I extends Identifier> extends Query { 13 | 14 | /** 15 | * 获取实体类型。 16 | * 17 | * @return 实体类型 18 | */ 19 | Class getEntityClass(); 20 | 21 | /** 22 | * 根据 ID 获取实体。 23 | * 24 | * @param tClass 实体类 25 | * @param identifier ID 26 | * @return 实体 27 | */ 28 | T getEntityById(Class tClass, I identifier); 29 | 30 | default Collection getEntityByIds(Class tClass, Collection identifiers) { 31 | return identifiers.stream().map(p -> getEntityById(tClass, p)).toList(); 32 | } 33 | 34 | /** 35 | * 插入实体。 36 | * 37 | * @param t 实体 38 | */ 39 | void insert(T t); 40 | 41 | /** 42 | * 更新实体。 43 | * 44 | * @param t 实体 45 | */ 46 | void update(T t); 47 | 48 | /** 49 | * 删除实体。 50 | * 51 | * @param t 实体 52 | */ 53 | void delete(T t); 54 | 55 | /** 56 | * 批量插入实体。 57 | * 58 | * @param ts 实体集合 59 | */ 60 | default void batchInsert(Collection ts) { 61 | for (T t : ts) { 62 | insert(t); 63 | } 64 | } 65 | 66 | /** 67 | * 批量更新实体。 68 | * 69 | * @param ts 实体集合 70 | */ 71 | default void batchUpdate(Collection ts) { 72 | for (T t : ts) { 73 | update(t); 74 | } 75 | } 76 | 77 | /** 78 | * 批量删除实体。 79 | * 80 | * @param ts 实体集合 81 | */ 82 | default void batchDelete(Collection ts) { 83 | for (T t : ts) { 84 | delete(t); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter-redis/src/main/java/com/zhaofujun/nest/boot/redis/RedisAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.boot.redis; 2 | 3 | import com.zhaofujun.nest.boot.redis.identifier.DailyRedisLongGenerator; 4 | import com.zhaofujun.nest.boot.redis.identifier.RedisLongGenerator; 5 | import com.zhaofujun.nest.boot.redis.identifier.RedisSequenceFactory; 6 | import com.zhaofujun.nest.boot.redis.provider.RedisCacheProvider; 7 | import com.zhaofujun.nest.boot.redis.provider.RedisLockProvider; 8 | import org.springframework.cache.annotation.EnableCaching; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.context.annotation.Configuration; 11 | import org.springframework.data.redis.core.RedisTemplate; 12 | import org.springframework.data.redis.core.StringRedisTemplate; 13 | 14 | @Configuration 15 | @EnableCaching 16 | public class RedisAutoConfiguration { 17 | 18 | @Bean 19 | public RedisCacheProvider cacheProvider(StringRedisTemplate stringRedisTemplate) { 20 | return new RedisCacheProvider(stringRedisTemplate); 21 | } 22 | @Bean 23 | public RedisSequenceFactory redisSequenceFactory(StringRedisTemplate stringRedisTemplate) { 24 | return new RedisSequenceFactory(stringRedisTemplate); 25 | } 26 | @Bean 27 | public RedisLockProvider lockProvider(StringRedisTemplate stringRedisTemplate) { 28 | return new RedisLockProvider(stringRedisTemplate); 29 | } 30 | @Bean(RedisLongGenerator.CODE) 31 | public RedisLongGenerator redisLongIdentifierGenerator(RedisTemplate redisTemplate){ 32 | return new RedisLongGenerator(redisTemplate); 33 | } 34 | 35 | @Bean(DailyRedisLongGenerator.CODE) 36 | public DailyRedisLongGenerator dailyRedisLongIdentifierGenerator(RedisTemplate redisTemplate){ 37 | return new DailyRedisLongGenerator(redisTemplate); 38 | } 39 | } -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/src/main/java/com/zhaofujun/nest/boot/NestBeanScannerRegistrar.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.boot; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.beans.factory.BeanFactory; 5 | import org.springframework.beans.factory.BeanFactoryAware; 6 | import org.springframework.beans.factory.support.BeanDefinitionRegistry; 7 | import org.springframework.boot.autoconfigure.AutoConfigurationPackages; 8 | import org.springframework.context.ResourceLoaderAware; 9 | import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; 10 | import org.springframework.core.io.ResourceLoader; 11 | import org.springframework.core.type.AnnotationMetadata; 12 | import org.springframework.util.StringUtils; 13 | 14 | import java.util.List; 15 | 16 | public class NestBeanScannerRegistrar implements BeanFactoryAware, ImportBeanDefinitionRegistrar, ResourceLoaderAware { 17 | private BeanFactory beanFactory; 18 | private ResourceLoader resourceLoader; 19 | 20 | @Override 21 | public void setBeanFactory(BeanFactory beanFactory) throws BeansException { 22 | this.beanFactory = beanFactory; 23 | } 24 | 25 | @Override 26 | public void setResourceLoader(ResourceLoader resourceLoader) { 27 | this.resourceLoader = resourceLoader; 28 | } 29 | 30 | @Override 31 | public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { 32 | NestBeanScanner scanner = new NestBeanScanner(registry); 33 | scanner.setAnnotationClass(AppService.class); 34 | if (resourceLoader != null) 35 | scanner.setResourceLoader(resourceLoader); 36 | 37 | 38 | // scanner.setMarkerInterface(ApplicationService.class); 39 | List packages = AutoConfigurationPackages.get(beanFactory); 40 | 41 | scanner.doScan(StringUtils.toStringArray(packages)); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter-redis/src/main/java/com/zhaofujun/nest/boot/redis/provider/RedisLockProvider.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.boot.redis.provider; 2 | 3 | import org.springframework.data.redis.core.StringRedisTemplate; 4 | 5 | import com.zhaofujun.nest.provider.LockProvider; 6 | 7 | import java.util.UUID; 8 | import java.util.concurrent.TimeUnit; 9 | import java.util.function.Supplier; 10 | 11 | public class RedisLockProvider implements LockProvider { 12 | 13 | public final static String CODE = "RedisLockProvider"; 14 | 15 | private StringRedisTemplate redisTemplate; 16 | private Long expireTime = 3000L; 17 | 18 | public RedisLockProvider(StringRedisTemplate redisTemplate) { 19 | this.redisTemplate = redisTemplate; 20 | } 21 | 22 | private String prefix = "nest_redis_lock_"; 23 | 24 | @Override 25 | public String getCode() { 26 | return CODE; 27 | } 28 | 29 | @Override 30 | public T lock(String name, Supplier runnable) { 31 | /** 32 | * 生成一个随机数 33 | * 开启循环 34 | * 在循环中执行setIfAbsent 35 | * 如果执行成功,就执行 runable,执行 runnable 后移除 key 36 | * 如果执行失败,否则继续循环 37 | * 38 | */ 39 | String requestId = UUID.randomUUID().toString(); 40 | for (;;) { 41 | Boolean ret = redisTemplate.opsForValue().setIfAbsent(prefix + name, requestId, expireTime, 42 | TimeUnit.MILLISECONDS); 43 | if (ret != null && ret.booleanValue()) { 44 | try { 45 | return runnable.get(); 46 | } finally { 47 | redisTemplate.delete(prefix + name); 48 | } 49 | } else { 50 | try { 51 | Thread.sleep(100); 52 | } catch (InterruptedException e) { 53 | Thread.interrupted(); 54 | } 55 | } 56 | 57 | } 58 | 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/event/EventHandlerWorker.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.event; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | import com.zhaofujun.nest.config.EventHandlerConfig; 6 | import com.zhaofujun.nest.ddd.ConsumeMode; 7 | import com.zhaofujun.nest.ddd.EventHandler; 8 | import com.zhaofujun.nest.manager.EventHandlerManager; 9 | import com.zhaofujun.nest.manager.EventManager; 10 | 11 | /** 12 | * 事件处理器工作者线程,负责注册事件处理器并处理事件。 13 | */ 14 | public class EventHandlerWorker extends Thread { 15 | /** 16 | * 事件通道提供者。 17 | */ 18 | private EventChannelProvider provider; 19 | 20 | /** 21 | * 事件处理器配置。 22 | */ 23 | private EventHandlerConfig config; 24 | 25 | /** 26 | * 事件应用服务。 27 | */ 28 | private EventAppService appService; 29 | 30 | /** 31 | * 构造函数。 32 | * 33 | * @param provider 事件通道提供者 34 | * @param config 事件处理器配置 35 | * @param appService 事件应用服务 36 | */ 37 | public EventHandlerWorker(EventChannelProvider provider, EventHandlerConfig config, EventAppService appService) { 38 | super("消息处理器-" + provider.getCode()); 39 | this.provider = provider; 40 | this.config = config; 41 | this.appService = appService; 42 | } 43 | 44 | /** 45 | * 运行方法,负责注册事件处理器并处理事件。 46 | */ 47 | @Override 48 | public void run() { 49 | 50 | // 找到所有事件 51 | List eventNames = EventManager.getEventNames(provider.getCode()); 52 | 53 | eventNames.forEach(eventName -> { 54 | // 找到事件下所有 eventHandler 55 | Map> eventHandlers = EventHandlerManager.getEventHandlers(eventName); 56 | eventHandlers.forEach((p, q) -> { 57 | ChannelConsumer consumer = provider.getConsumer(p); 58 | consumer.setEventAppService(appService); 59 | consumer.register(eventName, q); 60 | }); 61 | }); 62 | 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/manager/EventHandlerManager.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.manager; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collection; 5 | import java.util.HashMap; 6 | import java.util.HashSet; 7 | import java.util.List; 8 | import java.util.Map; 9 | import java.util.Set; 10 | import java.util.stream.Collectors; 11 | 12 | import com.zhaofujun.nest.ddd.ConsumeMode; 13 | import com.zhaofujun.nest.ddd.EventHandler; 14 | 15 | /* 16 | * 管理所有事件处理器 17 | */ 18 | public class EventHandlerManager { 19 | @SuppressWarnings("rawtypes") 20 | private static Map> handlerMap = new HashMap<>(); 21 | 22 | @SuppressWarnings("rawtypes") 23 | public static void addEventHandler(EventHandler... eventHandlers) { 24 | addEventHandler(Arrays.asList(eventHandlers)); 25 | } 26 | 27 | @SuppressWarnings("rawtypes") 28 | public static void addEventHandler(Collection eventHandlers) { 29 | eventHandlers.stream() 30 | .collect(Collectors.groupingBy(p -> p.getEventName())) 31 | .forEach((eventName, handlers) -> { 32 | 33 | // 将没有配置通道的事件放入默认通道 34 | EventManager.checkEventName(eventName); 35 | 36 | var handlerSet = handlerMap.get(eventName); 37 | if (handlerSet == null) { 38 | handlerSet = new HashSet<>(); 39 | handlerMap.put(eventName, handlerSet); 40 | } 41 | handlerSet.addAll(handlers); 42 | }); 43 | } 44 | 45 | @SuppressWarnings("rawtypes") 46 | public static Map> getEventHandlers(String eventName) { 47 | Set handlerSet = handlerMap.get(eventName); 48 | if (handlerSet == null) 49 | handlerSet = new HashSet<>(); 50 | return handlerSet.stream().collect(Collectors.groupingBy(p -> p.getConsumeMode())); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/utils/json/EntityObjectReaderAdapter.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.utils.json; 2 | 3 | import java.lang.reflect.Type; 4 | 5 | import com.alibaba.fastjson2.JSONObject; 6 | import com.alibaba.fastjson2.JSONReader; 7 | import com.alibaba.fastjson2.reader.ObjectReader; 8 | import com.zhaofujun.nest.ddd.Entity; 9 | import com.zhaofujun.nest.ddd.Identifier; 10 | import com.zhaofujun.nest.ddd.context.EntityLoader; 11 | 12 | public class EntityObjectReaderAdapter implements ObjectReader { 13 | 14 | private ObjectReader objectReader; 15 | 16 | public void setObjectReader(ObjectReader objectReader) { 17 | this.objectReader = objectReader; 18 | } 19 | 20 | @Override 21 | public Entity readObject(JSONReader jsonReader, Type fieldType, Object fieldName, 22 | long features) { 23 | 24 | Entity entity = null; 25 | JSONObject objectMap = (JSONObject) jsonReader.readObject(); 26 | try (JSONReader entityReader = JSONReader.of(jsonReader.getContext(), objectMap.toString())) { 27 | if (!objectMap.containsKey("__shorthand__")) { 28 | entity = objectReader.readObject(entityReader, fieldType, fieldName, 29 | features); 30 | } else { 31 | String idTypeName = objectMap.getJSONObject("id").getString("@type"); 32 | Identifier identifier = (Identifier) objectMap.getObject("id", new NameType(idTypeName), 33 | JSONReader.Feature.FieldBased, JSONReader.Feature.SupportAutoType); 34 | entity = EntityLoader.load(objectReader.getObjectClass(), identifier); 35 | } 36 | } 37 | 38 | return entity; 39 | } 40 | } 41 | 42 | class NameType implements Type { 43 | private String name; 44 | 45 | public NameType(String name) { 46 | this.name = name; 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | return this.name; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /nest-generator/src/main/java/com/zhaofujun/nest/generator/parser/ClassParser.java: -------------------------------------------------------------------------------- 1 | // package com.zhaofujun.nest.generator.parser; 2 | 3 | // import com.zhaofujun.nest.generator.model.*; 4 | 5 | // import java.lang.reflect.Field; 6 | // import java.lang.reflect.Modifier; 7 | 8 | // public class ClassParser { 9 | 10 | // protected NModel parseModel(Class clazz) { 11 | // String packageName = clazz.getPackage().getName(); 12 | // String className = clazz.getSimpleName(); 13 | // NIdentifier nIdentifier = null; 14 | // boolean isAbstract = Modifier.isAbstract(clazz.getModifiers()); 15 | // if (TypeUtil.isAggregateRoot(clazz)) { 16 | // return new NAggregateRoot(packageName, className, nIdentifier, isAbstract); 17 | // } else if (TypeUtil.isEntity(clazz)) { 18 | // return new NEntity(packageName, className, nIdentifier, isAbstract); 19 | // } else if (TypeUtil.isIdentifier(clazz)) { 20 | // return new NIdentifier(packageName, className); 21 | // } else if (TypeUtil.isValueObject(clazz)) { 22 | // return new NValueObject(packageName, className); 23 | // } else { 24 | // return new NObject(packageName, className); 25 | // } 26 | // } 27 | 28 | // protected NField parseFiled(Field field) { 29 | // String fieldName = field.getName(); 30 | // Class fieldType = field.getType(); 31 | // NClass fieldClass = parseModel(fieldType); 32 | // if (fieldClass == null) { 33 | // //不是模型类型,需要解析是否是基础类型和包装类型 34 | // if (TypeUtil.isPrimitive(fieldType) || TypeUtil.isWrapper(fieldType)) { 35 | // fieldClass = new NClass(null, fieldType.getSimpleName()); 36 | // } else { 37 | // //其它可能为对象类型 38 | // fieldClass = new NObject(fieldType.getPackageName(), fieldType.getSimpleName()); 39 | // } 40 | // } 41 | 42 | // return new NField(fieldName, fieldClass); 43 | // } 44 | 45 | // } 46 | 47 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/utils/json/EntityObjectWriterAdapter.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.utils.json; 2 | 3 | import com.alibaba.fastjson2.JSONWriter; 4 | import com.alibaba.fastjson2.writer.ObjectWriter; 5 | import com.zhaofujun.nest.ddd.Entity; 6 | import com.zhaofujun.nest.ddd.Identifier; 7 | 8 | import java.lang.reflect.Type; 9 | 10 | public class EntityObjectWriterAdapter implements ObjectWriter { 11 | 12 | private ObjectWriter objectWriter; 13 | 14 | public void setObjectWriter(ObjectWriter objectWriter) { 15 | this.objectWriter = objectWriter; 16 | } 17 | 18 | @Override 19 | public void write(JSONWriter jsonWriter, Object object, Object fieldName, Type fieldType, long features) { 20 | 21 | /** 22 | * 23 | * 根据jsonWriter.eleve()级别, 24 | * 如果当前级别为顶级level==0,使用默认方式生成json 25 | * 如果当前级别为非顶级level>0,则使用简单模式,只保留id与类型即可。 26 | * 27 | */ 28 | Entity entity = (Entity) object; 29 | if (jsonWriter.level() > 0) { 30 | jsonWriter.startObject(); 31 | writeKeyValue(jsonWriter, "@type", entity.getClassName()); 32 | writeKeyValue(jsonWriter, "id", entity.getId()); 33 | writeKeyValue(jsonWriter, "__shorthand__", true); 34 | jsonWriter.endObject(); 35 | 36 | } else { 37 | objectWriter.write(jsonWriter, object, fieldName, fieldType, features); 38 | } 39 | 40 | } 41 | 42 | private final void writeKeyValue(JSONWriter jsonWriter, String key, Object value) { 43 | boolean ref = jsonWriter.containsReference(value); 44 | jsonWriter.writeName(key); 45 | jsonWriter.writeColon(); 46 | jsonWriter.writeAny(value); 47 | if (!ref) { 48 | jsonWriter.removeReference(value); 49 | } 50 | } 51 | 52 | private final void writeKeyValue(JSONWriter jsonWriter, String key, String value) { 53 | jsonWriter.writeName(key); 54 | jsonWriter.writeColon(); 55 | jsonWriter.writeString(value); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/inner/DefaultRepository.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.inner; 2 | 3 | import java.lang.reflect.Type; 4 | 5 | import com.zhaofujun.nest.NestConst; 6 | import com.zhaofujun.nest.ddd.Entity; 7 | import com.zhaofujun.nest.ddd.Identifier; 8 | import com.zhaofujun.nest.ddd.Repository; 9 | import com.zhaofujun.nest.manager.CacheManager; 10 | import com.zhaofujun.nest.utils.EntityUtil; 11 | import com.zhaofujun.nest.utils.JsonUtil; 12 | import com.zhaofujun.nest.utils.StringUtil; 13 | import com.zhaofujun.nest.utils.cache.CacheClient; 14 | 15 | public class DefaultRepository implements Repository, Identifier> { 16 | private CacheClient cacheClient = CacheManager.getCacheClient(NestConst.defaultRepositoryCache); 17 | 18 | @Override 19 | public Class getEntityClass() { 20 | return Entity.class; 21 | } 22 | 23 | @Override 24 | public Entity getEntityById(Class> tClass, Identifier identifier) { 25 | String entityString = cacheClient.get(EntityUtil.getKey(tClass, identifier)); 26 | System.out.println("get" + tClass.getName() + ":" + entityString); 27 | if (StringUtil.isEmpty(entityString)) 28 | return null; 29 | return JsonUtil.parseObject(entityString, tClass); 30 | } 31 | 32 | @Override 33 | public void insert(Entity entity) { 34 | String entityString = JsonUtil.toJsonString(entity); 35 | System.out.println("insert "+ entity.getClass().getName() + ":" + entityString); 36 | cacheClient.put(EntityUtil.getKey(entity), entityString); 37 | } 38 | 39 | @Override 40 | public void update(Entity entity) { 41 | String entityString = JsonUtil.toJsonString(entity); 42 | System.out.println("update "+ entity.getClass().getName() + ":" + entityString); 43 | 44 | cacheClient.put(EntityUtil.getKey(entity), entityString); 45 | } 46 | 47 | @Override 48 | public void delete(Entity entity) { 49 | cacheClient.remove(EntityUtil.getKey(entity)); 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/utils/cache/CacheItem.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.utils.cache; 2 | 3 | /** 4 | * CacheItem 类 5 | * 用于表示缓存项的基本信息,包括缓存项的代码、缓存提供者的代码、最大存活时间以及是否禁用。 6 | */ 7 | public class CacheItem { 8 | /** 9 | * 缓存项的唯一标识代码 10 | */ 11 | private String code; 12 | 13 | /** 14 | * 缓存提供者的代码 15 | */ 16 | private String cacheProviderCode; 17 | 18 | /** 19 | * 缓存项的最大存活时间(秒) 20 | */ 21 | private long maxLiveSeconds; 22 | 23 | /** 24 | * 缓存项是否被禁用 25 | */ 26 | private boolean disabled; 27 | 28 | /** 29 | * 获取缓存项的唯一标识代码 30 | * 31 | * @return 缓存项的唯一标识代码 32 | */ 33 | public String getCode() { 34 | return code; 35 | } 36 | 37 | /** 38 | * 设置缓存项的唯一标识代码 39 | * 40 | * @param code 缓存项的唯一标识代码 41 | */ 42 | public void setCode(String code) { 43 | this.code = code; 44 | } 45 | 46 | /** 47 | * 获取缓存提供者的代码 48 | * 49 | * @return 缓存提供者的代码 50 | */ 51 | public String getCacheProviderCode() { 52 | return cacheProviderCode; 53 | } 54 | 55 | /** 56 | * 设置缓存提供者的代码 57 | * 58 | * @param cacheProviderCode 缓存提供者的代码 59 | */ 60 | public void setCacheProviderCode(String cacheProviderCode) { 61 | this.cacheProviderCode = cacheProviderCode; 62 | } 63 | 64 | /** 65 | * 获取缓存项的最大存活时间(秒) 66 | * 67 | * @return 缓存项的最大存活时间(秒) 68 | */ 69 | public long getMaxLiveSeconds() { 70 | return maxLiveSeconds; 71 | } 72 | 73 | /** 74 | * 设置缓存项的最大存活时间(秒) 75 | * 76 | * @param maxLiveSeconds 缓存项的最大存活时间(秒) 77 | */ 78 | public void setMaxLiveSeconds(long maxLiveSeconds) { 79 | this.maxLiveSeconds = maxLiveSeconds; 80 | } 81 | 82 | /** 83 | * 获取缓存项是否被禁用 84 | * 85 | * @return 缓存项是否被禁用 86 | */ 87 | public boolean isDisabled() { 88 | return disabled; 89 | } 90 | 91 | /** 92 | * 设置缓存项是否被禁用 93 | * 94 | * @param disabled 缓存项是否被禁用 95 | */ 96 | public void setDisabled(boolean disabled) { 97 | this.disabled = disabled; 98 | } 99 | } -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter-activemq/src/main/java/com/zhaofujun/nest/boot/activemq/ActivemqChannelProvider.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.boot.activemq; 2 | 3 | import org.apache.activemq.command.ActiveMQTopic; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.jms.core.JmsTemplate; 6 | import org.springframework.jms.core.MessageCreator; 7 | import org.springframework.stereotype.Component; 8 | 9 | import com.zhaofujun.nest.ddd.event.EventChannelProvider; 10 | import com.zhaofujun.nest.ddd.event.EventData; 11 | import com.zhaofujun.nest.ddd.event.PullChannelConsumer; 12 | import com.zhaofujun.nest.ddd.event.PushChannelConsumer; 13 | import com.zhaofujun.nest.utils.JsonUtil; 14 | 15 | import jakarta.jms.Topic; 16 | 17 | // import javax.jms.JMSException; 18 | // import javax.jms.Message; 19 | // import javax.jms.Session; 20 | // import javax.jms.Topic; 21 | 22 | import jakarta.jms.JMSException; 23 | import jakarta.jms.Message; 24 | import jakarta.jms.Session; 25 | 26 | @Component 27 | public class ActivemqChannelProvider implements EventChannelProvider { 28 | 29 | @Autowired 30 | private JmsTemplate jmsTemplate; 31 | 32 | 33 | @Override 34 | public String getCode() { 35 | return "ActivemqChannelProvider"; 36 | } 37 | 38 | @Override 39 | public void commit(String messageGroup, EventData dataObject) { 40 | Topic topic = new ActiveMQTopic("VirtualTopic." + messageGroup); 41 | 42 | String messageText = JsonUtil.toJsonString(dataObject); 43 | jmsTemplate.send(topic, new MessageCreator() { 44 | @Override 45 | public Message createMessage(Session session) throws JMSException { 46 | return session.createTextMessage(messageText); 47 | } 48 | }); 49 | } 50 | 51 | @Override 52 | public PullChannelConsumer getPullChannelConsumer() { 53 | return new ActivemqPullConsumer(jmsTemplate); 54 | } 55 | 56 | @Override 57 | public PushChannelConsumer getPushChannelConsumer() { 58 | return new ActivemqPushConsumer(jmsTemplate.getConnectionFactory()); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/inner/DefaultEventInfoRepository.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.inner; 2 | 3 | import java.time.LocalDateTime; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | import java.util.stream.Collectors; 7 | 8 | import com.zhaofujun.nest.ddd.Identifier; 9 | import com.zhaofujun.nest.ddd.LongIdentifier; 10 | import com.zhaofujun.nest.ddd.event.EventMessageRepository; 11 | import com.zhaofujun.nest.ddd.event.EventState; 12 | import com.zhaofujun.nest.ddd.event.EventMessageModel; 13 | 14 | public class DefaultEventInfoRepository extends EventMessageRepository { 15 | 16 | private static List> eventList = new ArrayList<>(); 17 | 18 | @Override 19 | public void insert(EventMessageModel t) { 20 | eventList.add(t); 21 | } 22 | 23 | @Override 24 | public void update(EventMessageModel t) { 25 | 26 | } 27 | 28 | @Override 29 | public void delete(EventMessageModel t) { 30 | eventList.remove(t); 31 | } 32 | 33 | @Override 34 | public List getListToBeSent(int commonSize, int failSize, int maxFailTime) { 35 | List resultList = new ArrayList<>(); 36 | var preList = eventList.stream() 37 | .filter(p -> p.getEventState().equals(EventState.preSend) 38 | && p.getSendTime().isBefore(LocalDateTime.now())) 39 | .limit(commonSize) 40 | .map(p -> p.getId().getId()) 41 | .collect(Collectors.toList()); 42 | resultList.addAll(preList); 43 | var failList = eventList.stream() 44 | .filter(p -> p.getEventState().equals(EventState.sendFail) 45 | && p.getSendTime().isBefore(LocalDateTime.now())) 46 | .limit(failSize) 47 | .map(p -> p.getId().getId()) 48 | .collect(Collectors.toList()); 49 | resultList.addAll(failList); 50 | return resultList; 51 | } 52 | 53 | @Override 54 | public EventMessageModel getEntityById(Class> tClass, LongIdentifier identifier) { 55 | return eventList.stream() 56 | .filter(p -> p.getClass().equals(tClass) && p.getId().equals(identifier)) 57 | .findFirst() 58 | .orElse(null); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter-activemq/src/main/java/com/zhaofujun/nest/boot/activemq/ActivemqPushConsumer.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.boot.activemq; 2 | 3 | import org.apache.activemq.command.ActiveMQQueue; 4 | import org.springframework.jms.listener.DefaultMessageListenerContainer; 5 | 6 | import com.zhaofujun.nest.ddd.event.EventData; 7 | import com.zhaofujun.nest.ddd.event.MessageAck; 8 | import com.zhaofujun.nest.ddd.event.MessageProcessor; 9 | import com.zhaofujun.nest.ddd.event.PushChannelConsumer; 10 | import com.zhaofujun.nest.utils.JsonUtil; 11 | 12 | import jakarta.jms.ConnectionFactory; 13 | import jakarta.jms.JMSException; 14 | import jakarta.jms.Message; 15 | import jakarta.jms.MessageListener; 16 | import jakarta.jms.Queue; 17 | import jakarta.jms.Session; 18 | import jakarta.jms.TextMessage; 19 | 20 | public class ActivemqPushConsumer extends PushChannelConsumer { 21 | 22 | private ConnectionFactory connectionFactory; 23 | 24 | public ActivemqPushConsumer(ConnectionFactory connectionFactory) { 25 | this.connectionFactory = connectionFactory; 26 | } 27 | 28 | @Override 29 | protected void subscribe(MessageProcessor consumer) { 30 | Queue queue = new ActiveMQQueue( 31 | "Consumer." + consumer.getHandlerId() + ".VirtualTopic." + consumer.getEventName()); 32 | 33 | DefaultMessageListenerContainer container = new DefaultMessageListenerContainer(); 34 | container.setConnectionFactory(connectionFactory); 35 | container.setDestination(queue); 36 | container.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE); 37 | container.setMessageListener(new MessageListener() { 38 | 39 | @Override 40 | public void onMessage(Message message) { 41 | TextMessage textMessage = (TextMessage) message; 42 | try { 43 | EventData eventData = JsonUtil.parseObject(textMessage.getText(), EventData.class); 44 | MessageAck messageAck = consumer.invoke(eventData); 45 | if (messageAck.equals(MessageAck.SUCCESS)) { 46 | message.acknowledge(); 47 | } 48 | } catch (JMSException ex) { 49 | 50 | } 51 | } 52 | }); 53 | container.start(); 54 | } 55 | 56 | } -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/utils/JsonUtil.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.utils; 2 | 3 | import com.alibaba.fastjson2.JSON; 4 | import com.alibaba.fastjson2.JSONReader; 5 | import com.alibaba.fastjson2.JSONWriter; 6 | import com.alibaba.fastjson2.reader.ObjectReader; 7 | import com.alibaba.fastjson2.writer.ObjectWriter; 8 | import com.zhaofujun.nest.ddd.Entity; 9 | import com.zhaofujun.nest.ddd.Identifier; 10 | import com.zhaofujun.nest.utils.json.EntityObjectReaderProvider; 11 | import com.zhaofujun.nest.utils.json.EntityObjectWriterProvider; 12 | 13 | import java.lang.reflect.Type; 14 | 15 | public class JsonUtil { 16 | 17 | public static String toJsonString(Entity entity) { 18 | JSONWriter.Context writerContext = new JSONWriter.Context(new EntityObjectWriterProvider()); 19 | writerContext.config(JSONWriter.Feature.FieldBased, JSONWriter.Feature.WriteClassName, 20 | JSONWriter.Feature.NotWriteRootClassName); 21 | try (JSONWriter writer = JSONWriter.of(writerContext)) { 22 | if (entity == null) { 23 | writer.writeNull(); 24 | } else { 25 | Class valueClass = entity.getClass(); 26 | var objectWriter = writer.getObjectWriter(valueClass, valueClass); 27 | writer.setRootObject(entity); 28 | objectWriter.write(writer, entity, null, null, 0); 29 | } 30 | return writer.toString(); 31 | } 32 | } 33 | 34 | public static String toJsonString(Object object) { 35 | return JSON.toJSONString(object); 36 | } 37 | 38 | public static T parseObject(String text, Type clazz) { 39 | // 40 | if (text == null || text.isEmpty()) { 41 | return null; 42 | } 43 | JSONReader.Context readerContext = new JSONReader.Context(new EntityObjectReaderProvider()); 44 | readerContext.config(JSONReader.Feature.FieldBased, JSONReader.Feature.SupportAutoType); 45 | try (JSONReader reader = JSONReader.of(readerContext, text)) { 46 | if (reader.nextIfNull()) 47 | return null; 48 | ObjectReader objectReader = reader.getObjectReader(clazz); 49 | T object = objectReader.readObject(reader); 50 | reader.handleResolveTasks(object); 51 | return object; 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/inner/DefaultEventChannelProvider.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.inner; 2 | 3 | import com.zhaofujun.nest.NestConst; 4 | import com.zhaofujun.nest.ddd.event.EventAppService; 5 | import com.zhaofujun.nest.ddd.event.EventChannelProvider; 6 | import com.zhaofujun.nest.ddd.event.EventData; 7 | import com.zhaofujun.nest.ddd.event.MessageAck; 8 | import com.zhaofujun.nest.ddd.event.MessageProcessor; 9 | import com.zhaofujun.nest.ddd.event.PullChannelConsumer; 10 | import com.zhaofujun.nest.ddd.event.PushChannelConsumer; 11 | import com.zhaofujun.nest.utils.JsonUtil; 12 | import com.zhaofujun.nest.utils.MessageUtil; 13 | 14 | /** 15 | * 使用 MessageUtil 模拟事件发布过程,请勿在生产环境中使用 16 | * 在生产环境中可以自定义并使用相同的code覆盖DefaultEventChannelProvider 17 | */ 18 | public class DefaultEventChannelProvider implements EventChannelProvider { 19 | 20 | @Override 21 | public String getCode() { 22 | return NestConst.defaultChannel; 23 | } 24 | 25 | @Override 26 | public void commit(String messageGroup, EventData eventData) { 27 | System.out.println("消息发布"); 28 | String messageInfoString = JsonUtil.toJsonString(eventData); 29 | MessageUtil.emit(messageGroup, messageInfoString); 30 | } 31 | 32 | @Override 33 | public PullChannelConsumer getPullChannelConsumer() { 34 | return new InnerPullConsumer(); 35 | } 36 | 37 | @Override 38 | public PushChannelConsumer getPushChannelConsumer() { 39 | return new InnerPushConsumer(); 40 | } 41 | 42 | public class InnerPullConsumer extends PullChannelConsumer { 43 | 44 | @Override 45 | public boolean pull(MessageProcessor eventConsumer) { 46 | throw new UnsupportedOperationException("Unimplemented method 'pull'"); 47 | } 48 | } 49 | 50 | public class InnerPushConsumer extends PushChannelConsumer { 51 | 52 | @Override 53 | protected void subscribe(MessageProcessor consumer) { 54 | MessageUtil.on(consumer.getEventName(), (String messageString) -> { 55 | // 获得事件字符串,进行反序列化 56 | // 调用 consumer.invoke 方法 处理业务 57 | EventData dataObject = consumer.toObject(messageString); 58 | MessageAck ack = consumer.invoke(dataObject); 59 | // 根据返回的 ack 进行信息确认 60 | }); 61 | } 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter-redis/src/main/java/com/zhaofujun/nest/boot/redis/provider/RedisHashCacheProvider.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.boot.redis.provider; 2 | 3 | import com.zhaofujun.nest.provider.CacheProvider; 4 | import org.springframework.data.redis.core.StringRedisTemplate; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | import java.util.concurrent.TimeUnit; 9 | 10 | public class RedisHashCacheProvider implements CacheProvider { 11 | public final static String CODE = "REDIS_HASH_CACHE_PROVIDER"; 12 | 13 | private StringRedisTemplate redisTemplate; 14 | 15 | public RedisHashCacheProvider(StringRedisTemplate redisTemplate) { 16 | this.redisTemplate = redisTemplate; 17 | } 18 | 19 | @Override 20 | public String getCode() { 21 | return CODE; 22 | } 23 | 24 | @Override 25 | public String get(String groupName, String key) { 26 | 27 | Object json = redisTemplate.opsForHash().get(groupName, key); 28 | if (json != null) 29 | return json.toString(); 30 | return null; 31 | 32 | } 33 | 34 | @Override 35 | public Map get(String groupName, String... keys) { 36 | 37 | 38 | Map result = new HashMap<>(); 39 | 40 | 41 | for (String key : keys) { 42 | String t = get(groupName, key); 43 | if (t != null) 44 | result.put(key, t); 45 | } 46 | 47 | return result; 48 | } 49 | 50 | @Override 51 | public void put(String groupName, String key, String value, long idleSeconds) { 52 | 53 | redisTemplate.opsForHash().put(groupName, key, value); 54 | redisTemplate.expire(groupName, idleSeconds, TimeUnit.SECONDS); 55 | } 56 | 57 | @Override 58 | public boolean remove(String groupName, String key) { 59 | 60 | return redisTemplate.opsForHash().delete(groupName, key) > 0; 61 | 62 | } 63 | 64 | @Override 65 | public void removeAll(String groupName) { 66 | 67 | redisTemplate.delete(groupName); 68 | } 69 | 70 | @Override 71 | public boolean containsKey(String groupName, String key) { 72 | 73 | return redisTemplate.opsForHash().hasKey(groupName, key); 74 | } 75 | 76 | @Override 77 | public String[] getKeys(String groupName) { 78 | 79 | return redisTemplate.opsForHash().keys(groupName).toArray(new String[]{}); 80 | 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter-redis/src/main/java/com/zhaofujun/nest/boot/redis/identifier/RedisSequenceFactory.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.boot.redis.identifier; 2 | 3 | import org.springframework.data.redis.core.StringRedisTemplate; 4 | import org.springframework.data.redis.support.atomic.RedisAtomicLong; 5 | 6 | import java.util.Calendar; 7 | import java.util.Date; 8 | import java.util.concurrent.TimeUnit; 9 | 10 | public class RedisSequenceFactory { 11 | private StringRedisTemplate redisTemplate; 12 | 13 | public RedisSequenceFactory(StringRedisTemplate redisTemplate) { 14 | this.redisTemplate = redisTemplate; 15 | } 16 | 17 | 18 | public void initKey(String key, int value, Date expireTime) { 19 | RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory()); 20 | counter.set(value); 21 | counter.expireAt(expireTime); 22 | } 23 | 24 | 25 | public void initKey(String key, int value, long timeout, TimeUnit unit) { 26 | RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory()); 27 | counter.set(value); 28 | counter.expire(timeout, unit); 29 | } 30 | 31 | public long generate(String key) { 32 | RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory()); 33 | return counter.incrementAndGet(); 34 | } 35 | 36 | 37 | public long generate(String key, Date expireTime) { 38 | RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory()); 39 | counter.expireAt(expireTime); 40 | return counter.incrementAndGet(); 41 | } 42 | 43 | 44 | public long generate(String key, int increment) { 45 | RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory()); 46 | return counter.addAndGet(increment); 47 | } 48 | 49 | public long generate(String key, int increment, Date expireTime) { 50 | RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory()); 51 | counter.expireAt(expireTime); 52 | return counter.addAndGet(increment); 53 | } 54 | 55 | public Date getTodayEndTime() { 56 | Calendar todayEnd = Calendar.getInstance(); 57 | todayEnd.set(Calendar.HOUR_OF_DAY, 23); 58 | todayEnd.set(Calendar.MINUTE, 59); 59 | todayEnd.set(Calendar.SECOND, 59); 60 | todayEnd.set(Calendar.MILLISECOND, 999); 61 | return todayEnd.getTime(); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /nest-generator/src/main/java/com/zhaofujun/nest/generator/parser/TypeUtil.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.generator.parser; 2 | 3 | import com.zhaofujun.nest.ddd.AggregateRoot; 4 | import com.zhaofujun.nest.ddd.Entity; 5 | import com.zhaofujun.nest.ddd.Identifier; 6 | import com.zhaofujun.nest.ddd.ValueObject; 7 | 8 | import java.time.LocalDate; 9 | import java.time.LocalDateTime; 10 | import java.time.ZonedDateTime; 11 | import java.util.Calendar; 12 | import java.util.Date; 13 | import java.util.HashSet; 14 | import java.util.Set; 15 | 16 | public class TypeUtil { 17 | private static final Set> WRAPPER = new HashSet>(); 18 | 19 | static { 20 | WRAPPER.add(Boolean.class); 21 | WRAPPER.add(Character.class); 22 | WRAPPER.add(Byte.class); 23 | WRAPPER.add(Short.class); 24 | WRAPPER.add(Integer.class); 25 | WRAPPER.add(Long.class); 26 | WRAPPER.add(Float.class); 27 | WRAPPER.add(Double.class); 28 | WRAPPER.add(Void.class); 29 | WRAPPER.add(String.class); 30 | } 31 | public static boolean isPrimitive(final Class clazz) { 32 | return clazz.isPrimitive(); 33 | } 34 | 35 | public static boolean isWrapper(Class clazz) { 36 | return WRAPPER.contains(clazz); 37 | } 38 | public static boolean isAggregateRoot(Class clazz) { 39 | return AggregateRoot.class.isAssignableFrom(clazz); 40 | } 41 | public static boolean isEntity(Class clazz) { 42 | return Entity.class.isAssignableFrom(clazz); 43 | } 44 | public static boolean isIdentifier(Class clazz) { 45 | return Identifier.class.isAssignableFrom(clazz); 46 | } 47 | public static boolean isValueObject(Class clazz) { 48 | return ValueObject.class.isAssignableFrom(clazz); 49 | } 50 | public static boolean isVoid(Class clazz) { 51 | return Void.class.isAssignableFrom(clazz); 52 | } 53 | public static boolean isObject(Class clazz) { 54 | return Object.class.isAssignableFrom(clazz); 55 | } 56 | private static boolean isEnum(final Class clazz) { 57 | return Enum.class.isAssignableFrom(clazz); 58 | } 59 | public static boolean isDate(Class clazz) { 60 | return Date.class.isAssignableFrom(clazz) 61 | || Calendar.class.isAssignableFrom(clazz) 62 | || LocalDate.class.isAssignableFrom(clazz) 63 | || LocalDateTime.class.isAssignableFrom(clazz) 64 | || ZonedDateTime.class.isAssignableFrom(clazz); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/src/main/java/com/zhaofujun/nest/boot/ListenerMethodLookup.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.boot; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | import java.lang.reflect.Method; 5 | 6 | import org.springframework.aop.framework.AopProxyUtils; 7 | import org.springframework.beans.BeansException; 8 | import org.springframework.beans.factory.config.BeanPostProcessor; 9 | import org.springframework.core.MethodIntrospector; 10 | import org.springframework.core.MethodIntrospector.MetadataLookup; 11 | import org.springframework.lang.Nullable; 12 | import org.springframework.stereotype.Component; 13 | 14 | import com.zhaofujun.nest.ddd.EventHandler; 15 | import com.zhaofujun.nest.manager.EventHandlerManager; 16 | 17 | @Component 18 | public class ListenerMethodLookup implements BeanPostProcessor { 19 | 20 | @Override 21 | @Nullable 22 | public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 23 | Class targetClass = AopProxyUtils.ultimateTargetClass(bean); 24 | MethodIntrospector.selectMethods(targetClass, new MetadataLookup() { 25 | @Override 26 | @Nullable 27 | public MethodAdapter inspect(Method method) { 28 | EventListener eventListener = method.getAnnotation(EventListener.class); 29 | if (eventListener == null) 30 | return null; 31 | return new MethodAdapter(bean, method, eventListener); 32 | } 33 | 34 | }).forEach((p, q) -> { 35 | EventHandlerManager.addEventHandler(q); 36 | }); 37 | return bean; 38 | } 39 | } 40 | 41 | class MethodAdapter implements EventHandler { 42 | private Object object; 43 | private Method method; 44 | private EventListener listener; 45 | 46 | public MethodAdapter(Object object, Method method, EventListener listener) { 47 | this.object = object; 48 | this.method = method; 49 | this.listener = listener; 50 | } 51 | 52 | @Override 53 | public String getEventName() { 54 | return listener.eventName(); 55 | } 56 | 57 | @Override 58 | public Class getEventDataClass() { 59 | return listener.eventDataClass(); 60 | } 61 | 62 | @Override 63 | public void handle(Object eventData) { 64 | 65 | try { 66 | method.invoke(object, eventData); 67 | } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { 68 | // 69 | } 70 | } 71 | 72 | } -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/event/PullChannelConsumer.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.event; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collection; 5 | import java.util.List; 6 | import com.zhaofujun.nest.ddd.EventHandler; 7 | 8 | public abstract class PullChannelConsumer implements ChannelConsumer { 9 | 10 | private List workers = new ArrayList<>(); 11 | private EventAppService appService; 12 | 13 | @Override 14 | public void setEventAppService(EventAppService appService) { 15 | this.appService = appService; 16 | } 17 | 18 | /** 19 | * 将每一个eventHandler 创建一个 eventConsumer 20 | * 为每一个 consumer启动一个子线程,并循环阻塞式拉取消息 21 | * 获取消息后调用 consumer.invoke() 22 | * 根据返回信息处理消息确认过程 23 | * 24 | * @param eventName 25 | * @param eventHandlers 26 | */ 27 | public void register(String eventName, Collection eventHandlers) { 28 | for (EventHandler handler : eventHandlers) { 29 | MessageProcessor eventConsumer = new MessageProcessor<>(handler,appService); 30 | ConsumerWorker consumerWorker = new ConsumerWorker(eventConsumer, this); 31 | workers.add(consumerWorker); 32 | consumerWorker.start(); 33 | } 34 | } 35 | 36 | // 拉取消息并使用 eventConsumer 处理消息,处理成功返回 true 37 | public abstract boolean pull(MessageProcessor eventConsumer); 38 | 39 | public class ConsumerWorker extends Thread { 40 | 41 | private MessageProcessor eventConsumer; 42 | private PullChannelConsumer consumer; 43 | 44 | public ConsumerWorker(MessageProcessor eventConsumer, PullChannelConsumer consumer) { 45 | super("消费者线程启动"); 46 | this.eventConsumer = eventConsumer; 47 | this.consumer = consumer; 48 | } 49 | 50 | @SuppressWarnings("static-access") 51 | @Override 52 | public void run() { 53 | while (!Thread.currentThread().interrupted()) { 54 | if (consumer.pull(eventConsumer)) { 55 | // 处理成功,休息100ms 56 | try { 57 | Thread.sleep(100); 58 | } catch (InterruptedException e) { 59 | Thread.interrupted(); 60 | } 61 | } else { 62 | // 处理失败,休息1000ms 63 | try { 64 | Thread.sleep(1000); 65 | } catch (InterruptedException e) { 66 | Thread.interrupted(); 67 | } 68 | } 69 | 70 | } 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/event/MessageProcessor.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.event; 2 | 3 | import java.lang.reflect.Type; 4 | 5 | import com.zhaofujun.nest.Lifecycle; 6 | import com.zhaofujun.nest.ddd.EventHandler; 7 | import com.zhaofujun.nest.exception.CustomException; 8 | import com.zhaofujun.nest.utils.JsonUtil; 9 | import com.zhaofujun.nest.utils.MessageUtil; 10 | import com.zhaofujun.nest.NestParameterizedType; 11 | 12 | /** 13 | * 消息处理器,处理从消息通道拿到的消息体,该消息体一定是 EventData 类型 14 | */ 15 | public class MessageProcessor { 16 | private EventHandler eventHandler; 17 | private EventAppService appService; 18 | 19 | public MessageProcessor(EventHandler eventHandler, EventAppService appService) { 20 | this.eventHandler = eventHandler; 21 | this.appService = appService; 22 | } 23 | 24 | private boolean idempotent(String messageId, String handlerId) { 25 | boolean tags = appService.isCompleted(new ProcessIdentifier(messageId, handlerId)); 26 | return tags; 27 | } 28 | 29 | private void complete(String messageId, String handlerId) { 30 | appService.complete(new ProcessIdentifier(messageId, handlerId)); 31 | } 32 | 33 | public EventData toObject(String messageString) { 34 | Type type = NestParameterizedType.make(EventData.class, eventHandler.getEventDataClass()); 35 | return JsonUtil.parseObject(messageString, type); 36 | } 37 | 38 | public MessageAck invoke(EventData eventObject) { 39 | 40 | MessageAck result = null; 41 | // 幂等验证 42 | if (idempotent(eventObject.getId(), getHandlerId())) { 43 | result = MessageAck.SUCCESS; 44 | } else { 45 | MessageUtil.emit(Lifecycle.Consume_Begin.name(), eventHandler); 46 | try { 47 | // 调用 eventHandler 48 | eventHandler.handle(eventObject.getData()); 49 | } catch (CustomException ex) { 50 | eventHandler.onCustomException(eventObject, ex); 51 | result = MessageAck.REFUSE; 52 | } catch (Throwable ex) { 53 | eventHandler.onSystemException(eventObject, ex); 54 | result = MessageAck.REFUSE; 55 | } finally { 56 | MessageUtil.emit(Lifecycle.Consume_End.name(), eventHandler); 57 | complete(eventObject.getId(), getHandlerId()); 58 | } 59 | } 60 | return result; 61 | } 62 | 63 | public String getEventName() { 64 | return eventHandler.getEventName(); 65 | } 66 | 67 | public String getHandlerId() { 68 | return eventHandler.getEventName() + "-" + eventHandler.getClass().getName(); 69 | } 70 | 71 | } -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter-redis/src/main/java/com/zhaofujun/nest/boot/redis/provider/RedisCacheProvider.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.boot.redis.provider; 2 | 3 | import com.zhaofujun.nest.provider.CacheProvider; 4 | import org.springframework.data.redis.core.StringRedisTemplate; 5 | 6 | import java.util.HashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | import java.util.Set; 10 | import java.util.concurrent.TimeUnit; 11 | import java.util.stream.Collectors; 12 | 13 | public class RedisCacheProvider implements CacheProvider { 14 | public final static String CODE = "REDIS_CACHE_PROVIDER"; 15 | 16 | private StringRedisTemplate redisTemplate; 17 | 18 | public RedisCacheProvider(StringRedisTemplate redisTemplate) { 19 | this.redisTemplate = redisTemplate; 20 | } 21 | 22 | @Override 23 | public String getCode() { 24 | return CODE; 25 | } 26 | 27 | private String getRedisKey(String groupName, String key) { 28 | return groupName + "_" + key; 29 | } 30 | 31 | @Override 32 | public String get(String groupName, String key) { 33 | String redisKey = getRedisKey(groupName, key); 34 | return redisTemplate.opsForValue().get(redisKey); 35 | 36 | } 37 | 38 | @Override 39 | public Map get(String groupName, String... keys) { 40 | 41 | Map result = new HashMap<>(); 42 | List values = redisTemplate.opsForValue().multiGet(List.of(keys)); 43 | if (values != null) { 44 | for (int i = 0; i < keys.length; i++) { 45 | result.put(keys[i], values.get(i)); 46 | } 47 | } 48 | return result; 49 | } 50 | 51 | @Override 52 | public void put(String groupName, String key, String value, long idleSeconds) { 53 | 54 | String redisKey = getRedisKey(groupName, key); 55 | redisTemplate.opsForValue().set(redisKey, value); 56 | redisTemplate.expire(redisKey, idleSeconds, TimeUnit.SECONDS); 57 | } 58 | 59 | @Override 60 | public boolean remove(String groupName, String key) { 61 | String redisKey = getRedisKey(groupName, key); 62 | return redisTemplate.delete(redisKey); 63 | } 64 | 65 | @Override 66 | public void removeAll(String groupName) { 67 | 68 | Set keys = redisTemplate.keys(groupName + "_*"); 69 | redisTemplate.delete(keys); 70 | } 71 | 72 | @Override 73 | public boolean containsKey(String groupName, String key) { 74 | String redisKey = getRedisKey(groupName, key); 75 | return redisTemplate.hasKey(redisKey); 76 | } 77 | 78 | @Override 79 | public String[] getKeys(String groupName) { 80 | return redisTemplate.keys(groupName + "_*").toArray(new String[]{}); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/inner/DefaultCacheProvider.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.inner; 2 | 3 | 4 | import net.sf.ehcache.Cache; 5 | import net.sf.ehcache.CacheManager; 6 | import net.sf.ehcache.Element; 7 | 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | 11 | import com.zhaofujun.nest.NestConst; 12 | import com.zhaofujun.nest.provider.CacheProvider; 13 | 14 | /** 15 | * EhCache 缓存提供者的实现 16 | * 17 | * @author Jove 18 | */ 19 | public class DefaultCacheProvider implements CacheProvider { 20 | 21 | @Override 22 | public String getCode() { 23 | return NestConst.defaultCacheProvider; 24 | } 25 | 26 | private CacheManager manager = CacheManager.create(); 27 | 28 | public String get(String groupName, String key) { 29 | if (!manager.cacheExists(groupName)) return null; 30 | Cache cache = manager.getCache(groupName); 31 | Element el = cache.get(key); 32 | if (el != null) { 33 | return el.getObjectValue().toString(); 34 | } 35 | return null; 36 | } 37 | 38 | public Map get(String groupName, String... keys) { 39 | Map result = new HashMap(); 40 | for (String key : keys) { 41 | String val = get(groupName, key); 42 | result.put(key, val); 43 | } 44 | return result; 45 | } 46 | 47 | 48 | public void put(String groupName, String key, String value, long idleSeconds) { 49 | if (!manager.cacheExists(groupName)) { 50 | manager.addCache(groupName); 51 | } 52 | Cache cache = manager.getCache(groupName); 53 | synchronized (value) { 54 | Element el = new Element(key, value, false, (int) idleSeconds, 0); 55 | cache.put(el); 56 | } 57 | 58 | } 59 | 60 | public boolean remove(String groupName, String key) { 61 | if (!manager.cacheExists(groupName)) 62 | return true; 63 | Cache cache = manager.getCache(groupName); 64 | return cache.remove(key); 65 | } 66 | 67 | public void removeAll(String groupName) { 68 | if (!manager.cacheExists(groupName)) 69 | return; 70 | Cache cache = manager.getCache(groupName); 71 | cache.removeAll(); 72 | } 73 | 74 | public boolean containsKey(String groupName, String key) { 75 | if (!manager.cacheExists(groupName)) 76 | return false; 77 | Cache cache = manager.getCache(groupName); 78 | return cache.isKeyInCache(key) && cache.get(key) != null; 79 | } 80 | 81 | @Override 82 | public String[] getKeys(String groupName) { 83 | if (!manager.cacheExists(groupName)) return null; 84 | Cache cache = manager.getCache(groupName); 85 | 86 | return (String[]) cache.getKeys().toArray(); 87 | } 88 | 89 | 90 | } 91 | -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/src/main/java/com/zhaofujun/nest/boot/NestBeanScanner.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.boot; 2 | 3 | import org.springframework.beans.factory.config.BeanDefinitionHolder; 4 | import org.springframework.beans.factory.support.BeanDefinitionRegistry; 5 | import org.springframework.context.annotation.ClassPathBeanDefinitionScanner; 6 | import org.springframework.core.type.filter.AnnotationTypeFilter; 7 | import org.springframework.core.type.filter.AssignableTypeFilter; 8 | 9 | import java.lang.annotation.Annotation; 10 | import java.util.Set; 11 | 12 | public class NestBeanScanner extends ClassPathBeanDefinitionScanner { 13 | private Class annotationClass; 14 | private Class markerInterface; 15 | 16 | public NestBeanScanner(BeanDefinitionRegistry registry) { 17 | super(registry, false); 18 | } 19 | 20 | public void setAnnotationClass(Class annotationClass) { 21 | this.annotationClass = annotationClass; 22 | } 23 | 24 | 25 | public void setMarkerInterface(Class markerInterface) { 26 | this.markerInterface = markerInterface; 27 | } 28 | 29 | private void registerFilters() { 30 | if (this.annotationClass != null) 31 | this.addIncludeFilter(new AnnotationTypeFilter(this.annotationClass)); 32 | if (this.markerInterface != null) 33 | this.addIncludeFilter(new AssignableTypeFilter(this.markerInterface) { 34 | @Override 35 | protected boolean matchClassName(String className) { 36 | return false; 37 | } 38 | }); 39 | } 40 | 41 | @Override 42 | protected Set doScan(String... basePackages) { 43 | registerFilters(); 44 | Set beanDefinitions = super.doScan(basePackages); 45 | // processBeanDefinition(beanDefinitions); 46 | return beanDefinitions; 47 | } 48 | 49 | // private void processBeanDefinition(Set beanDefinitions) { 50 | // beanDefinitions.forEach(beanDefinitionHolder -> { 51 | // GenericBeanDefinition beanDefinition = (GenericBeanDefinition) beanDefinitionHolder.getBeanDefinition(); 52 | // String beanClassName = beanDefinition.getBeanClassName(); 53 | // try { 54 | // Class t = Thread.currentThread().getContextClassLoader().loadClass(beanClassName); 55 | // beanDefinition.setBeanClass(ApplicationServiceFactoryBean.class); 56 | // beanDefinition.getPropertyValues().add("appServiceType", t); 57 | // beanDefinition.getPropertyValues().add("commitor", commitor); 58 | // } catch (ClassNotFoundException e) { 59 | // e.printStackTrace(); 60 | // } 61 | // }); 62 | // } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /publish.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'maven-publish' 2 | apply plugin: 'signing' 3 | 4 | task sourcesJar(type: Jar) { 5 | from sourceSets.main.allJava 6 | archiveClassifier = 'sources' 7 | } 8 | 9 | task javadocJar(type: Jar) { 10 | from javadoc 11 | archiveClassifier = 'javadoc' 12 | } 13 | 14 | javadoc { 15 | options{ 16 | encoding "UTF-8" 17 | charSet 'UTF-8' 18 | } 19 | } 20 | 21 | publishing { 22 | publications { 23 | mavenJava(MavenPublication) { 24 | groupId project.group 25 | artifactId project.name 26 | version "${version}" 27 | from components.java 28 | artifact sourcesJar 29 | artifact javadocJar 30 | versionMapping { 31 | usage('java-api') { 32 | fromResolutionOf('runtimeClasspath') 33 | } 34 | usage('java-runtime') { 35 | fromResolutionResult() 36 | } 37 | } 38 | // https://docs.gradle.org/current/dsl/org.gradle.api.publish.maven.MavenPublication.html 39 | pom { 40 | name = "Nest" 41 | description = "A framework for DDD" 42 | url = "https://github.com/jovezhao/nest" 43 | licenses { 44 | license { 45 | name = "The Apache License, Version 2.0" 46 | url = "http://www.apache.org/licenses/LICENSE-2.0.txt" 47 | } 48 | } 49 | developers { 50 | developer { 51 | id = "jovezhao" 52 | name = "zhaofujun" 53 | email = "jovezhao@foxmail.com" 54 | } 55 | } 56 | scm { 57 | connection = "scm:git:https://github.com/jovezhao/nest" 58 | developerConnection = "scm:git:https://github.com/jovezhao/nest" 59 | url = "https://github.com/jovezhao/nest" 60 | } 61 | } 62 | } 63 | } 64 | repositories { 65 | mavenLocal() 66 | maven { 67 | def releasesRepoUrl = "https://oss.sonatype.org/service/local/staging/deploy/maven2" 68 | def snapshotsRepoUrl = "https://oss.sonatype.org/content/repositories/snapshots" 69 | // 如果version以SNAPSHOT结尾就会上传到快照仓库,如果不是就上传到release仓库 70 | url = version.endsWith('SNAPSHOT') ? snapshotsRepoUrl : releasesRepoUrl 71 | credentials { 72 | username = project.properties.nexus_u 73 | password = project.properties.nexus_p 74 | } 75 | } 76 | 77 | } 78 | } 79 | 80 | signing { 81 | sign publishing.publications.mavenJava 82 | } -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | @rem SPDX-License-Identifier: Apache-2.0 17 | @rem 18 | 19 | @if "%DEBUG%"=="" @echo off 20 | @rem ########################################################################## 21 | @rem 22 | @rem Gradle startup script for Windows 23 | @rem 24 | @rem ########################################################################## 25 | 26 | @rem Set local scope for the variables with windows NT shell 27 | if "%OS%"=="Windows_NT" setlocal 28 | 29 | set DIRNAME=%~dp0 30 | if "%DIRNAME%"=="" set DIRNAME=. 31 | @rem This is normally unused 32 | set APP_BASE_NAME=%~n0 33 | set APP_HOME=%DIRNAME% 34 | 35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 37 | 38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 40 | 41 | @rem Find java.exe 42 | if defined JAVA_HOME goto findJavaFromJavaHome 43 | 44 | set JAVA_EXE=java.exe 45 | %JAVA_EXE% -version >NUL 2>&1 46 | if %ERRORLEVEL% equ 0 goto execute 47 | 48 | echo. 1>&2 49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 50 | echo. 1>&2 51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 52 | echo location of your Java installation. 1>&2 53 | 54 | goto fail 55 | 56 | :findJavaFromJavaHome 57 | set JAVA_HOME=%JAVA_HOME:"=% 58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 59 | 60 | if exist "%JAVA_EXE%" goto execute 61 | 62 | echo. 1>&2 63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 64 | echo. 1>&2 65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 66 | echo location of your Java installation. 1>&2 67 | 68 | goto fail 69 | 70 | :execute 71 | @rem Setup the command line 72 | 73 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 74 | 75 | 76 | @rem Execute Gradle 77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 78 | 79 | :end 80 | @rem End local scope for the variables with windows NT shell 81 | if %ERRORLEVEL% equ 0 goto mainEnd 82 | 83 | :fail 84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 85 | rem the _cmd.exe /c_ return code! 86 | set EXIT_CODE=%ERRORLEVEL% 87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 89 | exit /b %EXIT_CODE% 90 | 91 | :mainEnd 92 | if "%OS%"=="Windows_NT" endlocal 93 | 94 | :omega 95 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/event/EventAppService.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.event; 2 | 3 | import java.util.List; 4 | import java.util.stream.Collectors; 5 | 6 | import com.zhaofujun.nest.NestConst; 7 | import com.zhaofujun.nest.ddd.ApplicationService; 8 | import com.zhaofujun.nest.ddd.LongIdentifier; 9 | import com.zhaofujun.nest.manager.EventManager; 10 | import com.zhaofujun.nest.manager.ProviderManager; 11 | import com.zhaofujun.nest.utils.EntityUtil; 12 | 13 | /** 14 | * 事件应用服务类,负责事件的发送和处理。 15 | */ 16 | public class EventAppService implements ApplicationService { 17 | private EventMessageQuery query; 18 | 19 | /** 20 | * 设置事件信息查询对象。 21 | * 22 | * @param query 事件信息查询对象 23 | */ 24 | public void setQuery(EventMessageQuery query) { 25 | this.query = query; 26 | } 27 | 28 | /** 29 | * 获取事件信息列表。 30 | * 31 | * @param commonSize 普通事件大小 32 | * @param failSize 失败事件大小 33 | * @param maxFailTime 最大失败次数 34 | * @return 事件信息列表 35 | */ 36 | public List getEventInfoList(int commonSize, int failSize, int maxFailTime) { 37 | return query.getListToBeSent(commonSize, failSize, maxFailTime).stream() 38 | .map(p -> { 39 | EventMessageModel eventInfo = EntityUtil.load(EventMessageModel.class, new LongIdentifier(p)); 40 | eventInfo.readyPublish(); 41 | return eventInfo.getId(); 42 | }) 43 | .collect(Collectors.toList()); 44 | } 45 | 46 | /** 47 | * 发送事件信息。 48 | * 49 | * @param identifier 事件标识 50 | */ 51 | public void sendEventInfo(LongIdentifier identifier) { 52 | EventMessageModel eventInfo = EntityUtil.load(EventMessageModel.class, identifier); 53 | 54 | // 根据事件名找到通道 55 | String channelCode = EventManager.getChannelCode(eventInfo.getEventName()); 56 | EventChannelProvider eventChannelProvider = ProviderManager.get(EventChannelProvider.class, channelCode, 57 | NestConst.defaultChannel); 58 | 59 | EventData eventData = new EventData<>(); 60 | eventData.setData(eventInfo.getEventData()); 61 | eventData.setId(eventInfo.getId().toValue()); 62 | 63 | try { 64 | eventChannelProvider.commit(eventInfo.getEventName(), eventData); 65 | eventInfo.publish(); 66 | } catch (Exception ex) { 67 | eventInfo.fail(); 68 | } 69 | 70 | } 71 | 72 | /** 73 | * 检查是否处理过当前消息。 74 | * 75 | * @param processIdentifier 处理记录标识 76 | * @return true处理过,false 没有处理 77 | */ 78 | public boolean isCompleted(ProcessIdentifier processIdentifier) { 79 | EventProcessRecordModel eventProcessRecord = EntityUtil.load(EventProcessRecordModel.class, processIdentifier); 80 | if (eventProcessRecord == null) { 81 | eventProcessRecord = new EventProcessRecordModel(processIdentifier); 82 | } 83 | return eventProcessRecord.getProcessState().equals(ProcessState.completed); 84 | } 85 | 86 | /** 87 | * 完成事件处理。 88 | * 89 | * @param processIdentifier 处理记录标识 90 | */ 91 | public void complete(ProcessIdentifier processIdentifier) { 92 | EventProcessRecordModel eventProcessRecord = EntityUtil.load(EventProcessRecordModel.class, processIdentifier); 93 | eventProcessRecord.process(); 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/utils/AppServiceUtil.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.utils; 2 | 3 | import net.sf.cglib.proxy.Enhancer; 4 | import net.sf.cglib.proxy.MethodInterceptor; 5 | import net.sf.cglib.proxy.MethodProxy; 6 | 7 | import java.io.Serializable; 8 | import java.lang.reflect.InvocationTargetException; 9 | import java.lang.reflect.Method; 10 | import java.lang.reflect.Modifier; 11 | 12 | import com.zhaofujun.nest.ddd.AppServiceIgnore; 13 | import com.zhaofujun.nest.ddd.ApplicationService; 14 | import com.zhaofujun.nest.ddd.context.MethodInvoker; 15 | import com.zhaofujun.nest.ddd.context.ServiceMethodProcessor; 16 | import com.zhaofujun.nest.ddd.context.Transaction; 17 | 18 | public class AppServiceUtil { 19 | 20 | public static T create(Class tClass) throws InstantiationException, IllegalAccessException, 21 | IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException { 22 | 23 | Transaction transaction = new Transaction.DefaultTransaction(); 24 | 25 | Enhancer enhancer = new Enhancer(); 26 | // 设置需要创建子类的类 27 | enhancer.setSuperclass(tClass); 28 | enhancer.setCallback(new ApplicationServiceMethodInterceptor(transaction)); 29 | Object t = enhancer.create(); 30 | return (T) t; 31 | 32 | } 33 | 34 | private static class ApplicationServiceMethodInterceptor implements MethodInterceptor, Serializable { 35 | 36 | private class CglibMethodInvoker implements MethodInvoker { 37 | 38 | private MethodProxy methodProxy; 39 | private Object target; 40 | private Class targetClass; 41 | private Object[] args; 42 | private Method method; 43 | 44 | public CglibMethodInvoker(MethodProxy methodProxy, Method method, Object target, Class targetClass, 45 | Object[] args) { 46 | this.methodProxy = methodProxy; 47 | this.method = method; 48 | this.target = target; 49 | this.targetClass = targetClass; 50 | this.args = args; 51 | } 52 | 53 | @Override 54 | public String getMethodName() { 55 | return this.method.getName(); 56 | } 57 | 58 | @Override 59 | public Object invoke() throws Throwable { 60 | return methodProxy.invokeSuper(target, args); 61 | } 62 | 63 | @Override 64 | public Class getTargetClass() { 65 | return this.targetClass; 66 | } 67 | 68 | @Override 69 | public Object getTarget() { 70 | return this.target; 71 | } 72 | 73 | @Override 74 | public Method getMethod() { 75 | return this.method; 76 | } 77 | 78 | } 79 | 80 | private Transaction transaction; 81 | 82 | public ApplicationServiceMethodInterceptor(Transaction transaction) { 83 | this.transaction = transaction; 84 | } 85 | 86 | // 实现MethodInterceptor接口方法 87 | public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { 88 | 89 | AppServiceIgnore appServiceIgnore = method.getAnnotation(AppServiceIgnore.class); 90 | if (appServiceIgnore != null) 91 | return proxy.invokeSuper(obj, args); 92 | 93 | int modifiers = method.getModifiers(); 94 | if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers)) { 95 | MethodInvoker methodInvoker = new CglibMethodInvoker(proxy, method, obj, obj.getClass(), args); 96 | ServiceMethodProcessor intercept = new ServiceMethodProcessor(methodInvoker, transaction); 97 | return intercept.doInvoke(); 98 | } else { 99 | return proxy.invokeSuper(obj, args); 100 | } 101 | } 102 | 103 | } 104 | 105 | } 106 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/context/EntityLoader.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.context; 2 | 3 | import com.zhaofujun.nest.NestConst; 4 | import com.zhaofujun.nest.ddd.Entity; 5 | import com.zhaofujun.nest.ddd.Identifier; 6 | import com.zhaofujun.nest.ddd.Repository; 7 | import com.zhaofujun.nest.manager.CacheManager; 8 | import com.zhaofujun.nest.manager.RepositoryManager; 9 | import com.zhaofujun.nest.utils.EntityUtil; 10 | import com.zhaofujun.nest.utils.cache.CacheClient; 11 | 12 | import java.util.Arrays; 13 | import java.util.Collection; 14 | import java.util.HashMap; 15 | import java.util.Map; 16 | import java.util.stream.Collectors; 17 | 18 | public class EntityLoader { 19 | 20 | public static , I extends Identifier> T load(Class tClass, I identifier) { 21 | // 先通过上下文获取 22 | T entity = null; 23 | ServiceContext currentContext = ServiceContextManager.getCurrentContext(); 24 | if (currentContext != null) 25 | entity = currentContext.load(tClass, identifier); 26 | if (entity != null) 27 | return entity; 28 | 29 | // 启动查询上下文 30 | QueryContext queryContext = QueryContextManager.newServiceContext(); 31 | queryContext.begin(); 32 | try { 33 | // 再通过缓存获取 34 | CacheClient cacheClient = CacheManager.getCacheClient(NestConst.entityCache); 35 | entity = cacheClient.get(tClass, EntityUtil.getKey(tClass, identifier)); 36 | if (entity == null) { 37 | // 最后通过仓储获取 38 | Repository repository = RepositoryManager.getRepository(tClass); 39 | entity = repository.getEntityById(tClass, identifier); 40 | if (entity != null) 41 | // 获取成功后写入缓存 42 | cacheClient.put(EntityUtil.getKey(entity), entity); 43 | } 44 | // 提交上下文 45 | queryContext.submit(); 46 | } finally { 47 | // 清理上下文 48 | queryContext.end(); 49 | QueryContextManager.pop(); 50 | } 51 | return entity; 52 | } 53 | 54 | public static , I extends Identifier> Map load(Class tClass, Collection identifiers) { 55 | Map entityMap = new HashMap<>(); 56 | // 先通过上下文获取 57 | Collection ids = identifiers; 58 | if (!ids.isEmpty()) { 59 | ServiceContext currentContext = ServiceContextManager.getCurrentContext(); 60 | if (currentContext != null) { 61 | Map loadData = currentContext.load(tClass, ids); 62 | if (loadData != null) { 63 | loadData.values().forEach(entity -> entityMap.put(entity.getId(), entity)); 64 | ids = ids.stream().filter(p -> !entityMap.containsKey(p)).collect(Collectors.toList()); //将没有查到的对象ID过滤出来进一步查询 65 | } 66 | } 67 | } 68 | 69 | // 启动查询上下文 70 | QueryContext queryContext = QueryContextManager.newServiceContext(); 71 | queryContext.begin(); 72 | try { 73 | 74 | //再通过缓存获取 75 | if (!ids.isEmpty()) { 76 | CacheClient cacheClient = CacheManager.getCacheClient(NestConst.entityCache); 77 | String[] keys = ids.stream().map(p -> EntityUtil.getKey(tClass, p)).toArray(String[]::new); 78 | Map loadData = cacheClient.get(tClass, keys); 79 | loadData.values().forEach(entity -> entityMap.put(entity.getId(), entity)); 80 | ids = ids.stream().filter(p -> !entityMap.containsKey(p)).collect(Collectors.toList()); //将没有相到的对象ID过滤出来进一步查询 81 | } 82 | 83 | //最后通过仓储获取 84 | if (!ids.isEmpty()) { 85 | CacheClient cacheClient = CacheManager.getCacheClient(NestConst.entityCache); 86 | Repository repository = RepositoryManager.getRepository(tClass); 87 | Collection loadData = repository.getEntityByIds(tClass, ids); 88 | loadData.forEach(entity -> { 89 | //写回缓存 90 | if (entity != null) { 91 | entityMap.put(entity.getId(), entity); 92 | cacheClient.put(EntityUtil.getKey(entity), entity); 93 | } 94 | } 95 | ); 96 | 97 | } 98 | // 提交上下文 99 | queryContext.submit(); 100 | } finally { 101 | // 清理上下文 102 | queryContext.end(); 103 | QueryContextManager.pop(); 104 | } 105 | 106 | return entityMap; 107 | } 108 | 109 | } 110 | -------------------------------------------------------------------------------- /nest-spring-parent/nest-spring-boot-starter/src/main/java/com/zhaofujun/nest/boot/NestAspect.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.boot; 2 | 3 | import org.aspectj.lang.ProceedingJoinPoint; 4 | import org.aspectj.lang.annotation.Around; 5 | import org.aspectj.lang.annotation.Aspect; 6 | import org.aspectj.lang.reflect.MethodSignature; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.context.ApplicationContext; 9 | import org.springframework.stereotype.Component; 10 | 11 | import com.zhaofujun.nest.ddd.ApplicationService; 12 | import com.zhaofujun.nest.ddd.context.MethodInvoker; 13 | import com.zhaofujun.nest.ddd.context.QueryMethodProcessor; 14 | import com.zhaofujun.nest.ddd.context.ServiceMethodProcessor; 15 | import com.zhaofujun.nest.ddd.context.Transaction; 16 | 17 | import java.lang.reflect.Method; 18 | 19 | /** 20 | * NestAspect 类 21 | * 用于处理带有 @AppService 注解的方法的切面逻辑。 22 | * 主要功能包括事务管理和服务方法的拦截处理。 23 | */ 24 | @Component 25 | @Aspect 26 | public class NestAspect { 27 | 28 | /** 29 | * Spring 应用上下文 30 | * 用于获取事务管理器等 Bean 31 | */ 32 | @Autowired 33 | private ApplicationContext applicationContext; 34 | 35 | /** 36 | * 37 | * 处理带有 @AppService 注解的方法的执行逻辑。 38 | * 包括事务管理和服务方法的拦截处理。 39 | * 40 | * @param joinPoint 切入点 41 | * @return 方法的返回值 42 | * @throws Throwable 方法执行过程中可能抛出的异常 43 | */ 44 | @Around("execution(public * * (..)) && @within(com.zhaofujun.nest.boot.AppService)") 45 | public Object aroundFromAnnotationForAppService(ProceedingJoinPoint joinPoint) throws Throwable { 46 | MethodInvoker methodInvoker = new AspectMethodInvoker(joinPoint); 47 | // 从 appservice 注解中找到配置的事务管理器 48 | AppService appService = joinPoint.getTarget().getClass().getAnnotation(AppService.class); 49 | Class transactionClass = appService.transaction(); 50 | Transaction transaction = (Transaction) applicationContext.getBean(transactionClass); 51 | ServiceMethodProcessor intercept = new ServiceMethodProcessor(methodInvoker, transaction); 52 | return intercept.doInvoke(); 53 | } 54 | 55 | @Around("execution(public * com.zhaofujun.nest.ddd.ApplicationService+.* (..))") 56 | public Object aroundFromInterfaceForAppService(ProceedingJoinPoint joinPoint) throws Throwable { 57 | MethodInvoker methodInvoker = new AspectMethodInvoker(joinPoint); 58 | var appService = (ApplicationService) joinPoint.getTarget(); 59 | Class transactionClass = appService.getTransactionClass(); 60 | Transaction transaction = (Transaction) applicationContext.getBean(transactionClass); 61 | ServiceMethodProcessor intercept = new ServiceMethodProcessor(methodInvoker, transaction); 62 | return intercept.doInvoke(); 63 | } 64 | 65 | @Around("execution(public * com.zhaofujun.nest.ddd.Query+.* (..))") 66 | public Object aroundFromInterfaceForQuery(ProceedingJoinPoint joinPoint) throws Throwable { 67 | MethodInvoker methodInvoker = new AspectMethodInvoker(joinPoint); 68 | QueryMethodProcessor intercept = new QueryMethodProcessor(methodInvoker); 69 | return intercept.doInvoke(); 70 | } 71 | 72 | /** 73 | * 内部类 AspectMethodInvoker 74 | * 实现 MethodInvoker 接口,用于封装 AOP 切入点的相关信息。 75 | */ 76 | class AspectMethodInvoker implements MethodInvoker { 77 | private ProceedingJoinPoint joinPoint; 78 | 79 | /** 80 | * 构造函数 81 | * 82 | * @param joinPoint AOP 切入点 83 | */ 84 | public AspectMethodInvoker(ProceedingJoinPoint joinPoint) { 85 | this.joinPoint = joinPoint; 86 | } 87 | 88 | /** 89 | * 获取方法名称 90 | * 91 | * @return 方法名称 92 | */ 93 | @Override 94 | public String getMethodName() { 95 | return joinPoint.getSignature().getName(); 96 | } 97 | 98 | /** 99 | * 调用目标方法 100 | * 101 | * @return 方法的返回值 102 | * @throws Throwable 方法执行过程中可能抛出的异常 103 | */ 104 | @Override 105 | public Object invoke() throws Throwable { 106 | return joinPoint.proceed(); 107 | } 108 | 109 | /** 110 | * 获取目标类 111 | * 112 | * @return 目标类 113 | */ 114 | @Override 115 | public Class getTargetClass() { 116 | return joinPoint.getTarget().getClass(); 117 | } 118 | 119 | /** 120 | * 获取目标对象 121 | * 122 | * @return 目标对象 123 | */ 124 | @Override 125 | public Object getTarget() { 126 | return joinPoint.getTarget(); 127 | } 128 | 129 | /** 130 | * 获取方法对象 131 | * 132 | * @return 方法对象 133 | */ 134 | @Override 135 | public Method getMethod() { 136 | MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); 137 | return methodSignature.getMethod(); 138 | } 139 | } 140 | } -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/manager/CacheManager.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.manager; 2 | 3 | import java.util.Collection; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | import com.zhaofujun.nest.NestConst; 8 | import com.zhaofujun.nest.provider.CacheProvider; 9 | import com.zhaofujun.nest.utils.JsonUtil; 10 | import com.zhaofujun.nest.utils.StringUtil; 11 | import com.zhaofujun.nest.utils.cache.CacheClient; 12 | import com.zhaofujun.nest.utils.cache.CacheItem; 13 | 14 | public class CacheManager { 15 | private static Map cachMap = new HashMap<>(); 16 | 17 | public static void addCacheItem(String code, String cacheProviderCode, long idleSeconds) { 18 | CacheProvider cacheProvider = ProviderManager.get(CacheProvider.class, cacheProviderCode); 19 | cachMap.put(code, new CacheClientImpl(code, cacheProvider, idleSeconds, false)); 20 | } 21 | 22 | public static void addCacheItem(CacheItem... cacheItems) { 23 | for (CacheItem cacheItem : cacheItems) { 24 | CacheProvider cacheProvider = ProviderManager.get(CacheProvider.class, cacheItem.getCacheProviderCode()); 25 | cachMap.put(cacheItem.getCode(), 26 | new CacheClientImpl(cacheItem.getCode(), cacheProvider, cacheItem.getMaxLiveSeconds(), 27 | cacheItem.isDisabled())); 28 | } 29 | } 30 | 31 | public static void addCacheItem(Collection cacheItems) { 32 | cacheItems.forEach(cacheItem -> { 33 | addCacheItem(cacheItem); 34 | }); 35 | } 36 | 37 | public static CacheClient getCacheClient(String code) { 38 | CacheClient cacheClient = cachMap.get(code); 39 | if (cacheClient == null) 40 | cacheClient = getCacheClient(NestConst.defaultCacheItem); 41 | return cacheClient; 42 | } 43 | } 44 | 45 | /** 46 | * 缓存客户端 47 | * 48 | * @author Jove 49 | */ 50 | class CacheClientImpl implements CacheClient { 51 | 52 | private CacheProvider cacheProvider; 53 | 54 | private String code; 55 | 56 | private final long idleSeconds; 57 | private final boolean disabled; 58 | 59 | public CacheClientImpl(String code, CacheProvider cacheProvider, long idleSeconds, boolean disabled) { 60 | this.cacheProvider = cacheProvider; 61 | this.code = code; 62 | this.idleSeconds = idleSeconds; 63 | this.disabled = disabled; 64 | } 65 | 66 | public boolean remove(String key) { 67 | return cacheProvider.remove(code, key); 68 | } 69 | 70 | public void removeAll() { 71 | cacheProvider.removeAll(code); 72 | } 73 | 74 | public boolean containsKey(String key) { 75 | return cacheProvider.containsKey(code, key); 76 | } 77 | 78 | public String[] getKeys() { 79 | if (disabled) 80 | return null; 81 | return cacheProvider.getKeys(code); 82 | } 83 | 84 | @Override 85 | public String getCode() { 86 | return this.code; 87 | } 88 | 89 | @Override 90 | public T get(Class tClass, String key) { 91 | if (disabled) 92 | return null; 93 | String objeString = cacheProvider.get(this.code, key); 94 | return JsonUtil.parseObject(objeString, tClass); 95 | } 96 | 97 | @Override 98 | public String get(String key) { 99 | if (disabled) 100 | return null; 101 | return cacheProvider.get(this.code, key); 102 | } 103 | 104 | @Override 105 | public Map get(Class tClass, String... keys) { 106 | if (disabled) 107 | return null; 108 | 109 | Map tMap = new HashMap<>(); 110 | cacheProvider.get(code, keys).forEach((key, objecString) -> { 111 | if (!StringUtil.isEmpty(objecString)) { 112 | T object = JsonUtil.parseObject(objecString, tClass); 113 | tMap.put(key, object); 114 | } 115 | }); 116 | return tMap; 117 | } 118 | 119 | @Override 120 | public void put(String key, Object value, long idleSeconds) { 121 | if (disabled) 122 | return; 123 | 124 | String objecString = JsonUtil.toJsonString(value); 125 | cacheProvider.put(code, key, objecString, idleSeconds); 126 | } 127 | 128 | @Override 129 | public void put(String key, String value, long idleSeconds) { 130 | if (disabled) 131 | return; 132 | 133 | cacheProvider.put(code, key, value, idleSeconds); 134 | } 135 | 136 | @Override 137 | public void put(String key, Object value) { 138 | if (disabled) 139 | return; 140 | 141 | String objecString = JsonUtil.toJsonString(value); 142 | cacheProvider.put(code, key, objecString, 12 * 60); 143 | } 144 | 145 | @Override 146 | public void put(String key, String value) { 147 | if (disabled) 148 | return; 149 | 150 | cacheProvider.put(code, key, value, idleSeconds); 151 | } 152 | } -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/Entity.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd; 2 | 3 | import java.lang.reflect.Field; 4 | import java.util.Objects; 5 | 6 | import javax.validation.NoProviderFoundException; 7 | import javax.validation.Validation; 8 | import javax.validation.ValidatorFactory; 9 | 10 | import com.zhaofujun.nest.Lifecycle; 11 | import com.zhaofujun.nest.ddd.context.QueryContext; 12 | import com.zhaofujun.nest.ddd.context.QueryContextManager; 13 | import com.zhaofujun.nest.ddd.context.ServiceContext; 14 | import com.zhaofujun.nest.ddd.context.ServiceContextManager; 15 | import com.zhaofujun.nest.exception.VerifyFailedException; 16 | import com.zhaofujun.nest.utils.JsonUtil; 17 | import com.zhaofujun.nest.utils.MessageUtil; 18 | 19 | /** 20 | * 实体基类 21 | * 扩展自 DomainObject,用于表示领域模型中的实体对象。 22 | * 提供了基本的实体操作方法,如创建、删除、验证等。 23 | */ 24 | public abstract class Entity implements DomainObject { 25 | /** 26 | * 实体的唯一标识符 27 | */ 28 | protected T id; 29 | 30 | /** 31 | * 构造函数 32 | * 33 | * 初始化实体的 ID,并在创建实体时发出消息通知。 34 | * 35 | * @param id 实体的唯一标识符 36 | */ 37 | public Entity(T id) { 38 | this.id = id; 39 | // 创建实体时,发起消息通知 40 | QueryContext currentContext = QueryContextManager.getCurrentContext(); 41 | ServiceContext serviceContext = ServiceContextManager.getCurrentContext(); 42 | // 完成实体的构造时,查看当前实体是否存在查询上下文,如果有,写入查询上下文。如果没有,再看是否存在服务上下文,如果有写入服务上下文,如果没有,不做处理。 43 | if (currentContext != null) { 44 | currentContext.addEntity(this); 45 | } else if (serviceContext != null) { 46 | serviceContext.addEntity(this); 47 | } 48 | 49 | MessageUtil.emit(Lifecycle.Entity_New.name(), this); 50 | } 51 | 52 | /** 53 | * 获取实体的唯一标识符 54 | * 55 | * @return 实体的唯一标识符 56 | */ 57 | public T getId() { 58 | return id; 59 | } 60 | 61 | /** 62 | * 实体加载完成后的初始化方法 63 | * 将产生加载时的快照 64 | * 65 | */ 66 | public void _ready() { 67 | // 加载完成后,发起消息通知 68 | this.beginSnapshot = JsonUtil.toJsonString(this); 69 | MessageUtil.emit(Lifecycle.Entity_Ready.name(), this); 70 | 71 | } 72 | 73 | /** 74 | * 实体结束时的方法 75 | * 保存当前状态的快照。 76 | */ 77 | public void _end() { 78 | this.endSnapshot = JsonUtil.toJsonString(this); 79 | } 80 | 81 | /** 82 | * 设置实体的属性值 83 | * 84 | * @param fieldName 属性名称 85 | * @param value 属性值 86 | */ 87 | public void _setValue(String fieldName, Object value) { 88 | try { 89 | Field declaredField = this.getClass().getDeclaredField(fieldName); 90 | declaredField.setAccessible(true); 91 | declaredField.set(this, value); 92 | } catch (Exception ex) { 93 | // 异常处理 94 | } 95 | } 96 | 97 | /** 98 | * 标记实体是否已删除 99 | */ 100 | private transient boolean __deleted; 101 | 102 | /** 103 | * 删除实体 104 | * 标记实体为已删除状态。 105 | */ 106 | public void delete() { 107 | this.__deleted = true; 108 | } 109 | 110 | /** 111 | * 检查实体是否已删除 112 | * 113 | * @return 实体是否已删除 114 | */ 115 | public boolean is__deleted() { 116 | return __deleted; 117 | } 118 | 119 | /** 120 | * 实体加载前的状态快照 121 | */ 122 | private transient String beginSnapshot = ""; 123 | 124 | /** 125 | * 实体加载后的状态快照 126 | */ 127 | private transient String endSnapshot = ""; 128 | 129 | /** 130 | * 获取实体加载前的状态快照 131 | * 132 | * @return 实体加载前的状态快照 133 | */ 134 | public String getBeginSnapshot() { 135 | return beginSnapshot; 136 | } 137 | 138 | /** 139 | * 获取实体加载后的状态快照 140 | * 141 | * @return 实体加载后的状态快照 142 | */ 143 | public String getEndSnapshot() { 144 | return endSnapshot; 145 | } 146 | 147 | /** 148 | * 实体的版本号 149 | */ 150 | protected int _version; 151 | 152 | /** 153 | * 验证实体的有效性 154 | * 使用默认的验证器进行验证,如果验证失败则抛出异常。 155 | */ 156 | public void verify() { 157 | ValidatorFactory validatorFactory; 158 | try { 159 | validatorFactory = Validation.buildDefaultValidatorFactory(); 160 | } catch (NoProviderFoundException exception) { 161 | return; 162 | } 163 | Object[] strings = validatorFactory 164 | .getValidator() 165 | .validate(this) 166 | .stream() 167 | .map(p -> p.getMessage()) 168 | .toArray(); 169 | 170 | if (strings.length > 0) 171 | throw new VerifyFailedException("对象验证失败", strings); 172 | } 173 | 174 | /** 175 | * 判断两个实体是否相等 176 | * 主要基于实体的 ID 进行比较。 177 | * 178 | * @param obj 要比较的对象 179 | * @return 是否相等 180 | */ 181 | @Override 182 | public boolean equals(Object obj) { 183 | if (this == obj) 184 | return true; 185 | if (obj == null || getClass() != obj.getClass()) 186 | return false; 187 | return Objects.equals(this.id, ((Entity) obj).id); 188 | } 189 | 190 | @Override 191 | public int hashCode() { 192 | return Objects.hash(this.id, getClassName()); 193 | } 194 | } -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/ddd/context/ServiceContext.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.ddd.context; 2 | 3 | import java.util.*; 4 | import java.util.stream.Collectors; 5 | 6 | import com.zhaofujun.nest.Lifecycle; 7 | import com.zhaofujun.nest.ddd.Entity; 8 | import com.zhaofujun.nest.ddd.Identifier; 9 | import com.zhaofujun.nest.ddd.Repository; 10 | import com.zhaofujun.nest.manager.RepositoryManager; 11 | import com.zhaofujun.nest.utils.MessageUtil; 12 | import com.zhaofujun.nest.utils.StringUtil; 13 | 14 | public class ServiceContext { 15 | 16 | private Set> entities = new HashSet<>(); 17 | 18 | public void begin() { 19 | 20 | } 21 | 22 | public void submit() { 23 | entities.forEach(Entity::_end); 24 | 25 | var map = analyse(); 26 | 27 | map.forEach((p, q) -> { 28 | q.forEach((r, s) -> { 29 | if (s.isEmpty()) { 30 | return; 31 | } 32 | switch (r) { 33 | case create: 34 | p.batchInsert(s); 35 | MessageUtil.emit(Lifecycle.Entity_Created.name(), s); 36 | break; 37 | case update: 38 | p.batchUpdate(s); 39 | MessageUtil.emit(Lifecycle.Entity_Updated.name(), s); 40 | break; 41 | case remove: 42 | p.batchDelete(s); 43 | MessageUtil.emit(Lifecycle.Entity_Deleted.name(), s); 44 | 45 | } 46 | 47 | }); 48 | }); 49 | 50 | } 51 | 52 | public void end() { 53 | 54 | } 55 | 56 | public void addEntity(Entity entity) { 57 | entities.add(entity); 58 | } 59 | 60 | public , I extends Identifier> T load(Class tClass, I identifier) { 61 | Entity entity = entities.stream() 62 | .filter(p -> p.getId().equals(identifier) && p.getClass().equals(tClass)) 63 | .findFirst() 64 | .orElse(null); 65 | return (T) entity; 66 | } 67 | 68 | public , I extends Identifier> Map load(Class tClass, Collection identifiers) { 69 | Map map = new TreeMap<>(); 70 | Map> entityMap = entities.stream() 71 | .filter(p -> p.getClass().equals(tClass)) 72 | .filter(p -> identifiers.contains(p.getId())) 73 | .collect(Collectors.toMap(Entity::getId, p -> p)); 74 | return (Map) entityMap; 75 | } 76 | 77 | private Map>> analyse() { 78 | 79 | Map>> mapMap = new TreeMap<>( 80 | Comparators.getRepositoryComparator()); 81 | 82 | entities 83 | .stream() 84 | .filter(p -> !(StringUtil.isEmpty(p.getBeginSnapshot()) && p.is__deleted())) // 过滤掉没有开始、有删除标识的实体 85 | .filter(p -> !p.getEndSnapshot().equals(p.getBeginSnapshot())) // 过滤掉开始与结束一样的,即没有发生改变的实体 86 | .map(p -> EntityInfo.from(p)) 87 | .collect(Collectors.groupingBy(p -> p.getRepository())) 88 | .forEach((p, q) -> { 89 | Map> collect = q.stream() 90 | .collect(Collectors.groupingBy(m -> m.operateEnum, Collectors.mapping(n -> n.getEntity(), 91 | Collectors.toCollection(() -> new TreeSet<>(Comparators.getEntityComparator()))))); 92 | mapMap.put(p, collect); 93 | }); 94 | 95 | return mapMap; 96 | } 97 | 98 | static class EntityInfo { 99 | private Entity entity; 100 | private EntityOperateEnum operateEnum; 101 | private Repository repository; 102 | 103 | public static EntityInfo from(Entity entity) { 104 | 105 | EntityOperateEnum operateEnum = EntityOperateEnum.create; 106 | if (StringUtil.isEmpty(entity.getBeginSnapshot()) && !entity.is__deleted()) 107 | operateEnum = EntityOperateEnum.create; 108 | else if (!StringUtil.isEmpty(entity.getBeginSnapshot()) && entity.is__deleted()) 109 | operateEnum = EntityOperateEnum.remove; 110 | else if (!StringUtil.isEmpty(entity.getBeginSnapshot()) && !entity.is__deleted()) { 111 | operateEnum = EntityOperateEnum.update; 112 | } 113 | return new EntityInfo(entity, operateEnum, RepositoryManager.getRepository(entity.getClass())); 114 | } 115 | 116 | private EntityInfo(Entity entity, EntityOperateEnum operateEnum, 117 | Repository repository) { 118 | this.entity = entity; 119 | this.operateEnum = operateEnum; 120 | this.repository = repository; 121 | } 122 | 123 | public Entity getEntity() { 124 | return entity; 125 | } 126 | 127 | public EntityOperateEnum getOperateEnum() { 128 | return operateEnum; 129 | } 130 | 131 | public Repository getRepository() { 132 | return repository; 133 | } 134 | 135 | } 136 | 137 | enum EntityOperateEnum { 138 | create, update, remove 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /nest-ddd/src/main/java/com/zhaofujun/nest/utils/SnowFlakeUtil.java: -------------------------------------------------------------------------------- 1 | package com.zhaofujun.nest.utils; 2 | 3 | import java.net.InetAddress; 4 | import java.net.UnknownHostException; 5 | import java.util.concurrent.ThreadLocalRandom; 6 | 7 | public class SnowFlakeUtil { 8 | private static SnowFlake snowFlake = new SnowFlake(); 9 | 10 | public synchronized static Long nextLong() { 11 | return snowFlake.nextValue(); 12 | } 13 | } 14 | 15 | class SnowFlake { 16 | 17 | // ==============================Fields=========================================== 18 | /** 19 | * 开始时间截 (2015-01-01) 20 | */ 21 | private final long twepoch = 1420041600000L; 22 | 23 | /** 24 | * 机器id所占的位数 25 | */ 26 | private final long workerIdBits = 5L; 27 | 28 | /** 29 | * 数据标识id所占的位数 30 | */ 31 | private final long datacenterIdBits = 5L; 32 | 33 | /** 34 | * 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) 35 | */ 36 | private final long maxWorkerId = ~(-1L << workerIdBits); 37 | 38 | /** 39 | * 支持的最大数据标识id,结果是31 40 | */ 41 | private final long maxDatacenterId = ~(-1L << datacenterIdBits); 42 | 43 | /** 44 | * 序列在id中占的位数 45 | */ 46 | private final long sequenceBits = 12L; 47 | 48 | /** 49 | * 机器ID向左移12位 50 | */ 51 | private final long workerIdShift = sequenceBits; 52 | 53 | /** 54 | * 数据标识id向左移17位(12+5) 55 | */ 56 | private final long datacenterIdShift = sequenceBits + workerIdBits; 57 | 58 | /** 59 | * 时间截向左移22位(5+5+12) 60 | */ 61 | private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; 62 | 63 | /** 64 | * 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) 65 | */ 66 | private final long sequenceMask = ~(-1L << sequenceBits); 67 | 68 | /** 69 | * 工作机器ID(0~31) 70 | */ 71 | private long workerId; 72 | 73 | /** 74 | * 数据中心ID(0~31) 75 | */ 76 | private long datacenterId; 77 | 78 | /** 79 | * 毫秒内序列(0~4095) 80 | */ 81 | private long sequence = 0L; 82 | 83 | /** 84 | * 上次生成ID的时间截 85 | */ 86 | private long lastTimestamp = -1L; 87 | 88 | // ==============================Constructors===================================== 89 | 90 | /** 91 | * 构造函数 92 | */ 93 | public SnowFlake() { 94 | try { 95 | InetAddress ia = InetAddress.getLocalHost(); 96 | this.workerId = (long) Math.abs(ia.getHostAddress().hashCode()) % 32L; 97 | } catch (UnknownHostException var2) { 98 | this.workerId = (long) Math.abs(ThreadLocalRandom.current().nextInt()) % 32L; 99 | } 100 | 101 | this.datacenterId = (long) Math.abs(ThreadLocalRandom.current().nextInt()) % 32L; 102 | 103 | } 104 | 105 | /** 106 | * 构造函数 107 | * 108 | * @param workerId 工作ID (0~31) 109 | * @param datacenterId 数据中心ID (0~31) 110 | */ 111 | public SnowFlake(long workerId, long datacenterId) { 112 | if (workerId > maxWorkerId || workerId < 0) { 113 | throw new IllegalArgumentException( 114 | String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); 115 | } 116 | if (datacenterId > maxDatacenterId || datacenterId < 0) { 117 | throw new IllegalArgumentException( 118 | String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId)); 119 | } 120 | this.workerId = workerId; 121 | this.datacenterId = datacenterId; 122 | } 123 | 124 | // ==============================Methods========================================== 125 | 126 | /** 127 | * 获得下一个ID (该方法是线程安全的) 128 | * 129 | * @return SnowflakeId 130 | */ 131 | 132 | public synchronized Long nextValue() { 133 | long timestamp = timeGen(); 134 | 135 | // 如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常 136 | if (timestamp < lastTimestamp) { 137 | throw new RuntimeException( 138 | String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", 139 | lastTimestamp - timestamp)); 140 | } 141 | 142 | // 如果是同一时间生成的,则进行毫秒内序列 143 | if (lastTimestamp == timestamp) { 144 | sequence = (sequence + 1) & sequenceMask; 145 | // 毫秒内序列溢出 146 | if (sequence == 0) { 147 | // 阻塞到下一个毫秒,获得新的时间戳 148 | timestamp = tilNextMillis(lastTimestamp); 149 | } 150 | } 151 | // 时间戳改变,毫秒内序列重置 152 | else { 153 | sequence = 0L; 154 | } 155 | 156 | // 上次生成ID的时间截 157 | lastTimestamp = timestamp; 158 | 159 | // 移位并通过或运算拼到一起组成64位的ID 160 | return ((timestamp - twepoch) << timestampLeftShift) // 161 | | (datacenterId << datacenterIdShift) // 162 | | (workerId << workerIdShift) // 163 | | sequence; 164 | } 165 | 166 | /** 167 | * 阻塞到下一个毫秒,直到获得新的时间戳 168 | * 169 | * @param lastTimestamp 上次生成ID的时间截 170 | * @return 当前时间戳 171 | */ 172 | private long tilNextMillis(long lastTimestamp) { 173 | long timestamp = timeGen(); 174 | while (timestamp <= lastTimestamp) { 175 | timestamp = timeGen(); 176 | } 177 | return timestamp; 178 | } 179 | 180 | /** 181 | * 返回以毫秒为单位的当前时间 182 | * 183 | * @return 当前时间(毫秒) 184 | */ 185 | private long timeGen() { 186 | return System.currentTimeMillis(); 187 | } 188 | } --------------------------------------------------------------------------------