1
0
mirror of https://gitee.com/mirrors/Spring-Cloud-Alibaba.git synced 2021-06-26 13:25:11 +08:00

Separate all event-handling to smaller modules

This commit is contained in:
mercyblitz 2019-03-28 16:24:38 +08:00
parent 3407cd36de
commit 728c01991e
8 changed files with 178 additions and 271 deletions

View File

@ -17,21 +17,29 @@
package org.springframework.cloud.alibaba.dubbo.autoconfigure;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.spring.ServiceBean;
import org.apache.dubbo.config.spring.context.event.ServiceBeanExportedEvent;
import feign.Contract;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.event.ApplicationFailedEvent;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.cloud.alibaba.dubbo.metadata.DubboProtocolConfigSupplier;
import org.springframework.cloud.alibaba.dubbo.metadata.repository.DubboServiceMetadataRepository;
import org.springframework.cloud.alibaba.dubbo.metadata.resolver.DubboServiceBeanMetadataResolver;
import org.springframework.cloud.alibaba.dubbo.metadata.resolver.MetadataResolver;
import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceFactory;
import org.springframework.cloud.alibaba.dubbo.service.DubboMetadataConfigServiceExporter;
import org.springframework.cloud.alibaba.dubbo.service.DubboMetadataConfigServiceProxy;
import org.springframework.cloud.alibaba.dubbo.service.PublishingDubboMetadataConfigService;
import org.springframework.cloud.alibaba.dubbo.util.JSONUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.EventListener;
import java.util.Collection;
import java.util.function.Supplier;
@ -42,9 +50,21 @@ import java.util.function.Supplier;
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@Configuration
@Import({DubboServiceMetadataRepository.class, PublishingDubboMetadataConfigService.class, JSONUtils.class})
@Import({DubboServiceMetadataRepository.class,
PublishingDubboMetadataConfigService.class,
DubboMetadataConfigServiceExporter.class,
JSONUtils.class})
public class DubboMetadataAutoConfiguration {
@Autowired
private PublishingDubboMetadataConfigService dubboMetadataConfigService;
@Autowired
private MetadataResolver metadataResolver;
@Autowired
private DubboMetadataConfigServiceExporter dubboMetadataConfigServiceExporter;
@Bean
@ConditionalOnMissingBean
public MetadataResolver metadataJsonResolver(ObjectProvider<Contract> contract) {
@ -61,4 +81,31 @@ public class DubboMetadataAutoConfiguration {
public DubboMetadataConfigServiceProxy dubboMetadataConfigServiceProxy(DubboGenericServiceFactory factory) {
return new DubboMetadataConfigServiceProxy(factory);
}
// Event-Handling
@EventListener(ServiceBeanExportedEvent.class)
public void onServiceBeanExported(ServiceBeanExportedEvent event) {
ServiceBean serviceBean = event.getServiceBean();
publishServiceRestMetadata(serviceBean);
}
private void publishServiceRestMetadata(ServiceBean serviceBean) {
dubboMetadataConfigService.publishServiceRestMetadata(metadataResolver.resolveServiceRestMetadata(serviceBean));
}
@EventListener(ApplicationReadyEvent.class)
public void onApplicationReady() {
dubboMetadataConfigServiceExporter.export();
}
@EventListener(ApplicationFailedEvent.class)
public void onApplicationFailed() {
dubboMetadataConfigServiceExporter.unexport();
}
@EventListener(ContextClosedEvent.class)
public void onContextClosed() {
dubboMetadataConfigServiceExporter.unexport();
}
}

View File

@ -21,16 +21,12 @@ import org.apache.dubbo.config.spring.util.PropertySourcesUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.cloud.alibaba.dubbo.registry.ServiceRegistryAspect;
import org.springframework.cloud.alibaba.dubbo.registry.handler.DubboRegistryServiceIdHandler;
import org.springframework.cloud.alibaba.dubbo.registry.handler.StandardDubboRegistryServiceIdHandler;
import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceExecutionContextFactory;
import org.springframework.cloud.alibaba.dubbo.service.DubboGenericServiceFactory;
import org.springframework.cloud.alibaba.dubbo.service.parameter.PathVariableServiceParameterResolver;
import org.springframework.cloud.alibaba.dubbo.service.parameter.RequestBodyServiceParameterResolver;
import org.springframework.cloud.alibaba.dubbo.service.parameter.RequestHeaderServiceParameterResolver;
import org.springframework.cloud.alibaba.dubbo.service.parameter.RequestParamServiceParameterResolver;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@ -72,17 +68,6 @@ public class DubboServiceAutoConfiguration {
static class ParameterResolversConfiguration {
}
@Bean
public ServiceRegistryAspect serviceRegistryAspect() {
return new ServiceRegistryAspect();
}
@Bean
@ConditionalOnMissingBean
public DubboRegistryServiceIdHandler dubboRegistryServiceIdHandler(ConfigurableApplicationContext context) {
return new StandardDubboRegistryServiceIdHandler(context);
}
/**
* Bugfix code for an issue : https://github.com/apache/incubator-dubbo-spring-boot-project/issues/459
*

View File

@ -17,35 +17,27 @@
package org.springframework.cloud.alibaba.dubbo.autoconfigure;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.spring.ServiceBean;
import org.apache.dubbo.config.spring.context.event.ServiceBeanExportedEvent;
import com.ecwid.consul.v1.agent.model.NewService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.event.ApplicationFailedEvent;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.alibaba.dubbo.metadata.repository.DubboServiceMetadataRepository;
import org.springframework.cloud.alibaba.dubbo.metadata.resolver.MetadataResolver;
import org.springframework.cloud.alibaba.dubbo.registry.DubboServiceRegistrationEventPublishingAspect;
import org.springframework.cloud.alibaba.dubbo.registry.event.ServiceInstancePreRegisteredEvent;
import org.springframework.cloud.alibaba.dubbo.service.DubboMetadataConfigService;
import org.springframework.cloud.alibaba.dubbo.service.PublishingDubboMetadataConfigService;
import org.springframework.cloud.alibaba.dubbo.service.DubboMetadataConfigServiceExporter;
import org.springframework.cloud.alibaba.dubbo.util.JSONUtils;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
import org.springframework.cloud.consul.serviceregistry.ConsulRegistration;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.annotation.Import;
import org.springframework.context.event.EventListener;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
@ -53,19 +45,19 @@ import org.springframework.util.StringUtils;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import static org.springframework.cloud.alibaba.dubbo.registry.SpringCloudRegistry.DUBBO_URLS_METADATA_PROPERTY_NAME;
/**
* The Auto-Configuration class for Dubbo metadata {@link EventListener event handling}.
* Dubbo Service Registration Auto-{@link Configuration}
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@AutoConfigureAfter(value = {DubboMetadataAutoConfiguration.class})
@Configuration
public class DubboMetadataEventHandlingAutoConfiguration {
@Import({DubboServiceRegistrationEventPublishingAspect.class})
@ConditionalOnProperty(value = "spring.cloud.service-registry.auto-registration.enabled", matchIfMissing = true)
public class DubboServiceRegistrationAutoConfiguration {
private static final String CONSUL_REGISTRATION_CLASS_NAME =
"org.springframework.cloud.consul.serviceregistry.ConsulAutoRegistration";
@ -76,44 +68,18 @@ public class DubboMetadataEventHandlingAutoConfiguration {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private MetadataResolver metadataResolver;
@Autowired
private PublishingDubboMetadataConfigService dubboMetadataConfigService;
@Autowired
private ApplicationConfig applicationConfig;
@Autowired
private Supplier<ProtocolConfig> protocolConfigSupplier;
@Autowired
private ConfigurableApplicationContext context;
private ServiceRegistry serviceRegistry;
@Autowired
private DubboServiceMetadataRepository dubboServiceMetadataRepository;
@Autowired
private JSONUtils jsonUtils;
@Value("${spring.application.name:application}")
private String currentApplicationName;
private DubboMetadataConfigServiceExporter dubboMetadataConfigServiceExporter;
@Autowired
private ServiceRegistry serviceRegistry;
private JSONUtils jsonUtils;
private volatile Registration registration;
/**
* The ServiceConfig of DubboMetadataConfigService to be exported, can be nullable.
*/
private ServiceConfig<DubboMetadataConfigService> serviceConfig;
@EventListener(ServiceBeanExportedEvent.class)
public void onServiceBeanExported(ServiceBeanExportedEvent event) {
ServiceBean serviceBean = event.getServiceBean();
publishServiceRestMetadata(serviceBean);
}
private Registration registration;
@ConditionalOnClass(name = EUREKA_REGISTRATION_CLASS_NAME)
@Bean
@ -131,20 +97,15 @@ public class DubboMetadataEventHandlingAutoConfiguration {
serviceRegistry.register(registration);
}
@EventListener(ApplicationFailedEvent.class)
public void onApplicationFailed() {
unexportDubboMetadataConfigService();
}
@EventListener(ContextClosedEvent.class)
public void onContextClosed() {
unexportDubboMetadataConfigService();
}
// Event-Handling
@EventListener(ServiceInstancePreRegisteredEvent.class)
public void onServiceInstancePreRegistered(ServiceInstancePreRegisteredEvent event) {
dubboMetadataConfigServiceExporter.export();
Registration registration = event.getSource();
exportDubboMetadataConfigService();
attachURLsIntoMetadata(registration);
setRegistration(registration);
}
@ -196,52 +157,4 @@ public class DubboMetadataEventHandlingAutoConfiguration {
}
return jsonUtils.toJSON(urls.stream().map(URL::toFullString).collect(Collectors.toList()));
}
private void publishServiceRestMetadata(ServiceBean serviceBean) {
dubboMetadataConfigService.publishServiceRestMetadata(metadataResolver.resolveServiceRestMetadata(serviceBean));
}
private void exportDubboMetadataConfigService() {
if (serviceConfig != null && serviceConfig.isExported()) {
return;
}
if (StringUtils.isEmpty(dubboMetadataConfigService.getServiceRestMetadata())) {
// If there is no REST metadata, DubboMetadataConfigService will not be exported.
if (logger.isInfoEnabled()) {
logger.info("There is no REST metadata, the Dubbo service[{}] will not be exported.",
dubboMetadataConfigService.getClass().getName());
}
return;
}
serviceConfig = new ServiceConfig<>();
serviceConfig.setInterface(DubboMetadataConfigService.class);
// Use current Spring application name as the Dubbo Service version
serviceConfig.setVersion(currentApplicationName);
serviceConfig.setRef(dubboMetadataConfigService);
serviceConfig.setApplication(applicationConfig);
serviceConfig.setProtocol(protocolConfigSupplier.get());
serviceConfig.export();
if (logger.isInfoEnabled()) {
logger.info("The Dubbo service[{}] has been exported.", serviceConfig.toString());
}
}
private void unexportDubboMetadataConfigService() {
if (serviceConfig == null || serviceConfig.isUnexported()) {
return;
}
serviceConfig.unexport();
if (logger.isInfoEnabled()) {
logger.info("The Dubbo service[{}] has been unexported.", serviceConfig.toString());
}
}
}

View File

@ -27,12 +27,14 @@ import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
/**
* {@link ServiceRegistry} Aspect
* Dubbo Service Registration Event-Publishing Aspect
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
* @see ServiceInstancePreRegisteredEvent
* @see ServiceInstanceRegisteredEvent
*/
@Aspect
public class ServiceRegistryAspect implements ApplicationEventPublisherAware {
public class DubboServiceRegistrationEventPublishingAspect implements ApplicationEventPublisherAware {
/**
* The pointcut expression for {@link ServiceRegistry#register(Registration)}

View File

@ -1,53 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.dubbo.registry.handler;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.registry.Registry;
import org.springframework.context.ConfigurableApplicationContext;
/**
* Dubbo {@link Registry} Spring Cloud Service Id Builder
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
public interface DubboRegistryServiceIdHandler {
/**
* Supports the specified id of Spring Cloud Service or not
*
* @param serviceId the specified id of Spring Cloud Service
* @return if supports, return <code>true</code>, or <code>false</code>
*/
boolean supports(String serviceId);
/**
* Creates the id of Spring Cloud Service
*
* @param url The Dubbo's {@link URL}
* @return non-null
*/
String createServiceId(URL url);
/**
* The instance if {@link ConfigurableApplicationContext} .
*
* @return non-null
*/
ConfigurableApplicationContext getContext();
}

View File

@ -1,96 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.dubbo.registry.handler;
import org.apache.dubbo.common.Constants;
import org.apache.dubbo.common.URL;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.util.StringUtils;
import java.util.Objects;
import static java.lang.System.getProperty;
import static org.apache.dubbo.common.Constants.CONSUMERS_CATEGORY;
import static org.apache.dubbo.common.Constants.PROVIDERS_CATEGORY;
import static org.springframework.util.StringUtils.startsWithIgnoreCase;
/**
* The Standard {@link DubboRegistryServiceIdHandler}
* <p>
* The service ID pattern is "${category}:${interface}:${version}:${group}"
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
public class StandardDubboRegistryServiceIdHandler implements DubboRegistryServiceIdHandler {
/**
* The separator for service name that could be changed by the Java Property "dubbo.service.name.separator".
*/
protected static final String SERVICE_NAME_SEPARATOR = getProperty("dubbo.service.name.separator", ":");
private final ConfigurableApplicationContext context;
public StandardDubboRegistryServiceIdHandler(ConfigurableApplicationContext context) {
this.context = context;
}
@Override
public boolean supports(String serviceId) {
return startsWithIgnoreCase(serviceId, PROVIDERS_CATEGORY) ||
startsWithIgnoreCase(serviceId, CONSUMERS_CATEGORY);
}
@Override
public String createServiceId(URL url) {
String category = url.getParameter(Constants.CATEGORY_KEY, Constants.DEFAULT_CATEGORY);
if (!Objects.equals(category, PROVIDERS_CATEGORY) && !Objects.equals(category, CONSUMERS_CATEGORY)) {
category = PROVIDERS_CATEGORY;
}
return createServiceId(url, category);
}
@Override
public ConfigurableApplicationContext getContext() {
return context;
}
/**
* This method maybe override by sub-class.
*
* @param url The Dubbo's {@link URL}
* @param category The category
* @return
*/
protected String createServiceId(URL url, String category) {
StringBuilder serviceNameBuilder = new StringBuilder(category);
appendIfPresent(serviceNameBuilder, url, Constants.INTERFACE_KEY);
appendIfPresent(serviceNameBuilder, url, Constants.VERSION_KEY);
appendIfPresent(serviceNameBuilder, url, Constants.GROUP_KEY);
return serviceNameBuilder.toString();
}
private static void appendIfPresent(StringBuilder target, URL url, String parameterName) {
String parameterValue = url.getParameter(parameterName);
appendIfPresent(target, parameterValue);
}
private static void appendIfPresent(StringBuilder target, String parameterValue) {
if (StringUtils.hasText(parameterValue)) {
target.append(SERVICE_NAME_SEPARATOR).append(parameterValue);
}
}
}

View File

@ -0,0 +1,109 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.alibaba.dubbo.service;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.ServiceConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.util.function.Supplier;
/**
* {@link DubboMetadataConfigService} exporter
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
*/
@Component
public class DubboMetadataConfigServiceExporter {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private ApplicationConfig applicationConfig;
@Autowired
private PublishingDubboMetadataConfigService dubboMetadataConfigService;
@Autowired
private Supplier<ProtocolConfig> protocolConfigSupplier;
@Value("${spring.application.name:application}")
private String currentApplicationName;
/**
* The ServiceConfig of DubboMetadataConfigService to be exported, can be nullable.
*/
private ServiceConfig<DubboMetadataConfigService> serviceConfig;
/**
* export {@link DubboMetadataConfigService} as Dubbo service
*/
public void export() {
if (serviceConfig != null && serviceConfig.isExported()) {
return;
}
if (StringUtils.isEmpty(dubboMetadataConfigService.getServiceRestMetadata())) {
// If there is no REST metadata, DubboMetadataConfigService will not be exported.
if (logger.isInfoEnabled()) {
logger.info("There is no REST metadata, the Dubbo service[{}] will not be exported.",
dubboMetadataConfigService.getClass().getName());
}
return;
}
serviceConfig = new ServiceConfig<>();
serviceConfig.setInterface(DubboMetadataConfigService.class);
// Use current Spring application name as the Dubbo Service version
serviceConfig.setVersion(currentApplicationName);
serviceConfig.setRef(dubboMetadataConfigService);
serviceConfig.setApplication(applicationConfig);
serviceConfig.setProtocol(protocolConfigSupplier.get());
serviceConfig.export();
if (logger.isInfoEnabled()) {
logger.info("The Dubbo service[{}] has been exported.", serviceConfig.toString());
}
}
/**
* unexport {@link DubboMetadataConfigService}
*/
public void unexport() {
if (serviceConfig == null || serviceConfig.isUnexported()) {
return;
}
serviceConfig.unexport();
if (logger.isInfoEnabled()) {
logger.info("The Dubbo service[{}] has been unexported.", serviceConfig.toString());
}
}
}

View File

@ -1,7 +1,7 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboMetadataAutoConfiguration,\
org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboOpenFeignAutoConfiguration,\
org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboMetadataEventHandlingAutoConfiguration,\
org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboServiceRegistrationAutoConfiguration,\
org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboLoadBalancedRestTemplateAutoConfiguration,\
org.springframework.cloud.alibaba.dubbo.autoconfigure.DubboServiceAutoConfiguration