package org.enodeframework.spring; import org.enodeframework.commanding.ICommandHandlerProvider; import org.enodeframework.commanding.ICommandProcessor; import org.enodeframework.commanding.IProcessingCommandHandler; import org.enodeframework.commanding.impl.CommandHandlerProxy; import org.enodeframework.commanding.impl.DefaultCommandHandlerProvider; import org.enodeframework.commanding.impl.DefaultCommandProcessor; import org.enodeframework.commanding.impl.DefaultProcessingCommandHandler; import org.enodeframework.common.container.ObjectContainer; import org.enodeframework.common.extensions.ClassNameComparator; import org.enodeframework.common.extensions.ClassPathScanHandler; import org.enodeframework.common.scheduling.IScheduleService; import org.enodeframework.common.scheduling.ScheduleService; import org.enodeframework.domain.IAggregateRepositoryProvider; import org.enodeframework.domain.IAggregateRootFactory; import org.enodeframework.domain.IAggregateSnapshotter; import org.enodeframework.domain.IAggregateStorage; import org.enodeframework.domain.IDomainException; import org.enodeframework.domain.IMemoryCache; import org.enodeframework.domain.IRepository; import org.enodeframework.domain.impl.DefaultAggregateRepositoryProvider; import org.enodeframework.domain.impl.DefaultAggregateRootFactory; import org.enodeframework.domain.impl.DefaultAggregateRootInternalHandlerProvider; import org.enodeframework.domain.impl.DefaultAggregateSnapshotter; import org.enodeframework.domain.impl.DefaultMemoryCache; import org.enodeframework.domain.impl.DefaultRepository; import org.enodeframework.domain.impl.EventSourcingAggregateStorage; import org.enodeframework.domain.impl.SnapshotOnlyAggregateStorage; import org.enodeframework.eventing.DomainEventStreamMessage; import org.enodeframework.eventing.IEventCommittingService; import org.enodeframework.eventing.IEventSerializer; import org.enodeframework.eventing.IEventStore; import org.enodeframework.eventing.IProcessingEventProcessor; import org.enodeframework.eventing.IPublishedVersionStore; import org.enodeframework.eventing.impl.DefaultEventCommittingService; import org.enodeframework.eventing.impl.DefaultEventSerializer; import org.enodeframework.eventing.impl.DefaultProcessingEventProcessor; import org.enodeframework.infrastructure.IAssemblyInitializer; import org.enodeframework.infrastructure.ITypeNameProvider; import org.enodeframework.infrastructure.impl.DefaultTypeNameProvider; import org.enodeframework.messaging.IApplicationMessage; import org.enodeframework.messaging.IMessageDispatcher; import org.enodeframework.messaging.IMessageHandlerProvider; import org.enodeframework.messaging.IMessagePublisher; import org.enodeframework.messaging.IThreeMessageHandlerProvider; import org.enodeframework.messaging.ITwoMessageHandlerProvider; import org.enodeframework.messaging.impl.DefaultMessageDispatcher; import org.enodeframework.messaging.impl.DefaultMessageHandlerProvider; import org.enodeframework.messaging.impl.DefaultThreeMessageHandlerProvider; import org.enodeframework.messaging.impl.DefaultTwoMessageHandlerProvider; import org.enodeframework.messaging.impl.MessageHandlerProxy1; import org.enodeframework.messaging.impl.MessageHandlerProxy2; import org.enodeframework.messaging.impl.MessageHandlerProxy3; import org.enodeframework.queue.ISendMessageService; import org.enodeframework.queue.ISendReplyService; import org.enodeframework.queue.applicationmessage.DefaultApplicationMessageListener; import org.enodeframework.queue.applicationmessage.DefaultApplicationMessagePublisher; import org.enodeframework.queue.command.DefaultCommandListener; import org.enodeframework.queue.command.DefaultCommandResultProcessor; import org.enodeframework.queue.command.DefaultCommandService; import org.enodeframework.queue.command.ICommandResultProcessor; import org.enodeframework.queue.domainevent.DefaultDomainEventListener; import org.enodeframework.queue.domainevent.DefaultDomainEventPublisher; import org.enodeframework.queue.publishableexceptions.DefaultPublishableExceptionListener; import org.enodeframework.queue.publishableexceptions.DefaultPublishableExceptionPublisher; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Scope; import java.util.Set; import java.util.TreeSet; /** * @author [email protected] */ public class EnodeAutoConfiguration implements ApplicationContextAware { private final static Logger logger = LoggerFactory.getLogger(EnodeAutoConfiguration.class); private ApplicationContext applicationContext; @Value("${spring.enode.queue.command.topic}") private String commandTopic; @Value("${spring.enode.queue.event.topic}") private String eventTopic; @Value("${spring.enode.queue.application.topic}") private String applicationTopic; @Value("${spring.enode.queue.exception.topic}") private String exceptionTopic; @Value("${spring.enode.queue.command.tag}") private String commandTag; @Value("${spring.enode.queue.event.tag}") private String eventTag; @Value("${spring.enode.queue.application.tag}") private String applicationTag; @Value("${spring.enode.queue.exception.tag}") private String exceptionTag; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; SpringObjectContainer container = new SpringObjectContainer(applicationContext); ObjectContainer.INSTANCE = container; scanConfiguredPackages(ObjectContainer.BASE_PACKAGES); } private void registerBeans(Set<Class<?>> classSet) { applicationContext.getBeansOfType(IAssemblyInitializer.class).values().forEach(provider -> { provider.initialize(classSet); if (logger.isDebugEnabled()) { logger.debug("{} initial success", provider.getClass().getName()); } }); } /** * Scan the packages configured */ private void scanConfiguredPackages(String... scanPackages) { if (scanPackages == null) { throw new IllegalArgumentException("packages is not specified"); } ClassPathScanHandler handler = new ClassPathScanHandler(scanPackages); Set<Class<?>> classSet = new TreeSet<>(new ClassNameComparator()); for (String pakName : scanPackages) { classSet.addAll(handler.getPackageAllClasses(pakName, true)); } registerBeans(classSet); } @Bean(name = "scheduleService") public ScheduleService scheduleService() { return new ScheduleService(); } @Bean(name = "defaultTypeNameProvider") public DefaultTypeNameProvider defaultTypeNameProvider() { return new DefaultTypeNameProvider(); } @Bean(name = "domainEventMessageProcessor", initMethod = "start", destroyMethod = "stop") public DefaultProcessingEventProcessor domainEventMessageProcessor(IScheduleService scheduleService, IMessageDispatcher messageDispatcher, IPublishedVersionStore publishedVersionStore) { return new DefaultProcessingEventProcessor(scheduleService, messageDispatcher, publishedVersionStore); } /** * 原型模式获取bean,每次新建代理执行 */ @Bean @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) public CommandHandlerProxy commandHandlerProxy() { return new CommandHandlerProxy(); } @Bean @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) public MessageHandlerProxy1 messageHandlerProxy1() { return new MessageHandlerProxy1(); } @Bean @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) public MessageHandlerProxy2 messageHandlerProxy2() { return new MessageHandlerProxy2(); } @Bean @Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE) public MessageHandlerProxy3 messageHandlerProxy3() { return new MessageHandlerProxy3(); } @Bean(name = "defaultEventSerializer") public DefaultEventSerializer defaultEventSerializer(ITypeNameProvider typeNameProvider) { return new DefaultEventSerializer(typeNameProvider); } @Bean(name = "aggregateRootInternalHandlerProvider") public DefaultAggregateRootInternalHandlerProvider aggregateRootInternalHandlerProvider() { return new DefaultAggregateRootInternalHandlerProvider(); } @Bean(name = "messageDispatcher") public DefaultMessageDispatcher defaultMessageDispatcher( ITypeNameProvider typeNameProvider, IMessageHandlerProvider messageHandlerProvider, ITwoMessageHandlerProvider twoMessageHandlerProvider, IThreeMessageHandlerProvider threeMessageHandlerProvider) { return new DefaultMessageDispatcher(typeNameProvider, messageHandlerProvider, twoMessageHandlerProvider, threeMessageHandlerProvider); } @Bean(name = "defaultRepository") public DefaultRepository defaultRepository(IMemoryCache memoryCache) { return new DefaultRepository(memoryCache); } @Bean(name = "defaultMemoryCache", initMethod = "start", destroyMethod = "stop") public DefaultMemoryCache defaultMemoryCache(IAggregateStorage aggregateStorage, IScheduleService scheduleService, ITypeNameProvider typeNameProvider) { return new DefaultMemoryCache(aggregateStorage, scheduleService, typeNameProvider); } @Bean(name = "defaultAggregateRepositoryProvider") public DefaultAggregateRepositoryProvider defaultAggregateRepositoryProvider() { return new DefaultAggregateRepositoryProvider(); } @Bean(name = "threeMessageHandlerProvider") public DefaultThreeMessageHandlerProvider threeMessageHandlerProvider() { return new DefaultThreeMessageHandlerProvider(); } @Bean(name = "twoMessageHandlerProvider") public DefaultTwoMessageHandlerProvider twoMessageHandlerProvider() { return new DefaultTwoMessageHandlerProvider(); } @Bean(name = "messageHandlerProvider") public DefaultMessageHandlerProvider messageHandlerProvider() { return new DefaultMessageHandlerProvider(); } @Bean(name = "commandHandlerProvider") public DefaultCommandHandlerProvider commandHandlerProvider() { return new DefaultCommandHandlerProvider(); } @Bean(name = "aggregateRootFactory") public DefaultAggregateRootFactory aggregateRootFactory() { return new DefaultAggregateRootFactory(); } @Bean(name = "aggregateSnapshotter") public DefaultAggregateSnapshotter aggregateSnapshotter(IAggregateRepositoryProvider aggregateRepositoryProvider) { return new DefaultAggregateSnapshotter(aggregateRepositoryProvider); } @Bean(name = "defaultProcessingCommandHandler") public DefaultProcessingCommandHandler defaultProcessingCommandHandler( IEventStore eventStore, ICommandHandlerProvider commandHandlerProvider, ITypeNameProvider typeNameProvider, IEventCommittingService eventService, IMemoryCache memoryCache, @Qualifier(value = "applicationMessagePublisher") IMessagePublisher<IApplicationMessage> applicationMessagePublisher, @Qualifier(value = "publishableExceptionPublisher") IMessagePublisher<IDomainException> publishableExceptionPublisher ) { return new DefaultProcessingCommandHandler(eventStore, commandHandlerProvider, typeNameProvider, eventService, memoryCache, applicationMessagePublisher, publishableExceptionPublisher); } @Bean(name = "defaultEventCommittingService") public DefaultEventCommittingService defaultEventCommittingService(IMemoryCache memoryCache, IEventStore eventStore, @Qualifier(value = "domainEventPublisher") IMessagePublisher<DomainEventStreamMessage> domainEventPublisher) { return new DefaultEventCommittingService(memoryCache, eventStore, domainEventPublisher); } @Bean(name = "defaultCommandProcessor", initMethod = "start", destroyMethod = "stop") public DefaultCommandProcessor defaultCommandProcessor(IProcessingCommandHandler processingCommandHandler, IScheduleService scheduleService) { return new DefaultCommandProcessor(processingCommandHandler, scheduleService); } @Bean(name = "defaultCommandResultProcessor") public DefaultCommandResultProcessor defaultCommandResultProcessor() { return new DefaultCommandResultProcessor(); } @Bean(name = "snapshotOnlyAggregateStorage") @ConditionalOnProperty(prefix = "spring.enode", name = "aggregatestorage", havingValue = "snapshot", matchIfMissing = false) public SnapshotOnlyAggregateStorage snapshotOnlyAggregateStorage(IAggregateSnapshotter aggregateSnapshotter) { return new SnapshotOnlyAggregateStorage(aggregateSnapshotter); } @Bean(name = "eventSourcingAggregateStorage") @ConditionalOnProperty(prefix = "spring.enode", name = "aggregatestorage", havingValue = "eventsourcing", matchIfMissing = true) public EventSourcingAggregateStorage eventSourcingAggregateStorage( IAggregateRootFactory aggregateRootFactory, IEventStore eventStore, IAggregateSnapshotter aggregateSnapshotter, ITypeNameProvider typeNameProvider) { return new EventSourcingAggregateStorage(eventStore, aggregateRootFactory, aggregateSnapshotter, typeNameProvider); } @Bean(name = "defaultCommandService") public DefaultCommandService defaultCommandService(ICommandResultProcessor commandResultProcessor, ISendMessageService sendMessageService) { return new DefaultCommandService(commandTopic, commandTag, commandResultProcessor, sendMessageService); } @Bean(name = "domainEventPublisher") public DefaultDomainEventPublisher domainEventPublisher(IEventSerializer eventSerializer, ISendMessageService sendMessageService) { return new DefaultDomainEventPublisher(eventTopic, eventTag, eventSerializer, sendMessageService); } @Bean(name = "applicationMessagePublisher") public DefaultApplicationMessagePublisher applicationMessagePublisher(ISendMessageService sendMessageService) { return new DefaultApplicationMessagePublisher(applicationTopic, applicationTag, sendMessageService); } @Bean(name = "publishableExceptionPublisher") public DefaultPublishableExceptionPublisher publishableExceptionPublisher(ISendMessageService sendMessageService) { return new DefaultPublishableExceptionPublisher(eventTopic, eventTag, sendMessageService); } @Bean(name = "defaultCommandListener") public DefaultCommandListener commandListener(ISendReplyService sendReplyService, ITypeNameProvider typeNameProvider, ICommandProcessor commandProcessor, IRepository repository, IAggregateStorage aggregateRootStorage) { return new DefaultCommandListener(sendReplyService, typeNameProvider, commandProcessor, repository, aggregateRootStorage); } @Bean(name = "defaultDomainEventListener") public DefaultDomainEventListener domainEventListener(ISendReplyService sendReplyService, IProcessingEventProcessor domainEventMessageProcessor, IEventSerializer eventSerializer) { return new DefaultDomainEventListener(sendReplyService, domainEventMessageProcessor, eventSerializer); } @Bean(name = "defaultPublishableExceptionListener") public DefaultPublishableExceptionListener publishableExceptionListener(ITypeNameProvider typeNameProvider, IMessageDispatcher messageDispatcher) { return new DefaultPublishableExceptionListener(typeNameProvider, messageDispatcher); } @Bean(name = "defaultApplicationMessageListener") public DefaultApplicationMessageListener applicationMessageListener(ITypeNameProvider typeNameProvider, IMessageDispatcher messageDispatcher) { return new DefaultApplicationMessageListener(typeNameProvider, messageDispatcher); } }