From 6f6d8b21facfbd32e50d451932966f61d851f921 Mon Sep 17 00:00:00 2001 From: "ken.lj" Date: Tue, 19 Sep 2017 18:49:34 +0800 Subject: [PATCH] fabric8 configuration --- pom.xml | 69 +++- .../dubbo/config/spring/AnnotationBean.java | 313 ++++++++++++++++++ .../test/DubboFeatureTestApplication.java | 3 + .../dubbo/test/conf/DubboConfiguration.java | 2 + .../dubbo/test/service/AnnotateService.java | 8 + .../service/impl/AnnotateServiceImpl.java | 15 + .../dubbo/test/web/BaseController.java | 27 ++ .../dubbo/test/web/HelloController.java | 16 + src/main/resources/dubbo-annotation.xml | 40 +++ src/main/resources/dubbo-mouse.xml | 4 +- .../dubbo/test/ObjectMapConvertTest.java | 41 +++ 11 files changed, 531 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/alibaba/dubbo/config/spring/AnnotationBean.java create mode 100644 src/main/java/com/alibaba/dubbo/test/service/AnnotateService.java create mode 100644 src/main/java/com/alibaba/dubbo/test/service/impl/AnnotateServiceImpl.java create mode 100644 src/main/java/com/alibaba/dubbo/test/web/BaseController.java create mode 100644 src/main/java/com/alibaba/dubbo/test/web/HelloController.java create mode 100644 src/main/resources/dubbo-annotation.xml create mode 100644 src/test/java/com/alibaba/dubbo/test/ObjectMapConvertTest.java diff --git a/pom.xml b/pom.xml index 9e9c6c1..d644b72 100644 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,6 @@ + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 com.alibaba.dubbo @@ -21,14 +21,29 @@ UTF-8 UTF-8 - 1.6 - 7.0.59 + 1.6 + 7.0.59 + artifact + docker.io/fabric8/java-jboss-openjdk8-jdk:1.0.10 + weipeng2k/${project.artifactId}:${project.version} + 8080 + 8778 + icons/spring-boot + /health + 8080 + 5 + 30 + 8080 + dubbo-feature-test + 80 + LoadBalancer + UTF-8 org.springframework.boot - spring-boot-starter + spring-boot-starter-web @@ -39,7 +54,7 @@ com.alibaba dubbo - 2.5.5 + 2.5.5 org.javassist @@ -76,6 +91,50 @@ org.springframework.boot spring-boot-maven-plugin + + io.fabric8 + docker-maven-plugin + 0.14.2 + + + + ${docker.image} + + ${docker.from} + + /app + ${docker.assemblyDescriptorRef} + + + ${project.artifactId}-${project.version}.jar + -Djava.security.egd=/dev/./urandom + + + + + + + + io.fabric8 + fabric8-maven-plugin + 2.2.100 + + + json + generate-resources + + json + + + + attach + package + + attach + + + + diff --git a/src/main/java/com/alibaba/dubbo/config/spring/AnnotationBean.java b/src/main/java/com/alibaba/dubbo/config/spring/AnnotationBean.java new file mode 100644 index 0000000..0d2c32f --- /dev/null +++ b/src/main/java/com/alibaba/dubbo/config/spring/AnnotationBean.java @@ -0,0 +1,313 @@ +/* + * Copyright 1999-2012 Alibaba Group. + * + * Licensed 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 com.alibaba.dubbo.config.spring; + +import com.alibaba.dubbo.common.Constants; +import com.alibaba.dubbo.common.logger.Logger; +import com.alibaba.dubbo.common.logger.LoggerFactory; +import com.alibaba.dubbo.common.utils.ConcurrentHashSet; +import com.alibaba.dubbo.common.utils.ReflectUtils; +import com.alibaba.dubbo.config.AbstractConfig; +import com.alibaba.dubbo.config.ApplicationConfig; +import com.alibaba.dubbo.config.ConsumerConfig; +import com.alibaba.dubbo.config.ModuleConfig; +import com.alibaba.dubbo.config.MonitorConfig; +import com.alibaba.dubbo.config.ProtocolConfig; +import com.alibaba.dubbo.config.ProviderConfig; +import com.alibaba.dubbo.config.ReferenceConfig; +import com.alibaba.dubbo.config.RegistryConfig; +import com.alibaba.dubbo.config.ServiceConfig; +import com.alibaba.dubbo.config.annotation.Reference; +import com.alibaba.dubbo.config.annotation.Service; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * AnnotationBean + * + * @author william.liangf + * @export + */ +public class AnnotationBean extends AbstractConfig implements DisposableBean, BeanFactoryPostProcessor, BeanPostProcessor, ApplicationContextAware { + + private static final long serialVersionUID = -7582802454287589552L; + + private static final Logger logger = LoggerFactory.getLogger(Logger.class); + private final Set> serviceConfigs = new ConcurrentHashSet>(); + private final ConcurrentMap> referenceConfigs = new ConcurrentHashMap>(); + private String annotationPackage; + private String[] annotationPackages; + private ApplicationContext applicationContext; + + public String getPackage() { + return annotationPackage; + } + + public void setPackage(String annotationPackage) { + this.annotationPackage = annotationPackage; + this.annotationPackages = (annotationPackage == null || annotationPackage.length() == 0) ? null + : Constants.COMMA_SPLIT_PATTERN.split(annotationPackage); + } + + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + } + + public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) + throws BeansException { + if (annotationPackage == null || annotationPackage.length() == 0) { + return; + } + if (beanFactory instanceof BeanDefinitionRegistry) { + try { + // init scanner + Class scannerClass = ReflectUtils.forName("org.springframework.context.annotation.ClassPathBeanDefinitionScanner"); + Object scanner = scannerClass.getConstructor(new Class[]{BeanDefinitionRegistry.class, boolean.class}).newInstance(new Object[]{(BeanDefinitionRegistry) beanFactory, true}); + // add filter + Class filterClass = ReflectUtils.forName("org.springframework.core.type.filter.AnnotationTypeFilter"); + Object filter = filterClass.getConstructor(Class.class).newInstance(Service.class); + Method addIncludeFilter = scannerClass.getMethod("addIncludeFilter", ReflectUtils.forName("org.springframework.core.type.filter.TypeFilter")); + addIncludeFilter.invoke(scanner, filter); + // scan packages + String[] packages = Constants.COMMA_SPLIT_PATTERN.split(annotationPackage); + Method scan = scannerClass.getMethod("scan", new Class[]{String[].class}); + scan.invoke(scanner, new Object[]{packages}); + } catch (Throwable e) { + // spring 2.0 + } + } + } + + public void destroy() throws Exception { + for (ServiceConfig serviceConfig : serviceConfigs) { + try { + serviceConfig.unexport(); + } catch (Throwable e) { + logger.error(e.getMessage(), e); + } + } + for (ReferenceConfig referenceConfig : referenceConfigs.values()) { + try { + referenceConfig.destroy(); + } catch (Throwable e) { + logger.error(e.getMessage(), e); + } + } + } + + public Object postProcessAfterInitialization(Object bean, String beanName) + throws BeansException { + if (!isMatchPackage(bean)) { + return bean; + } + Service service = bean.getClass().getAnnotation(Service.class); + if (service != null) { + ServiceBean serviceConfig = new ServiceBean(service); + if (void.class.equals(service.interfaceClass()) + && "".equals(service.interfaceName())) { + if (bean.getClass().getInterfaces().length > 0) { + serviceConfig.setInterface(bean.getClass().getInterfaces()[0]); + } else { + throw new IllegalStateException("Failed to export remote service class " + bean.getClass().getName() + ", cause: The @Service undefined interfaceClass or interfaceName, and the service class unimplemented any interfaces."); + } + } + if (applicationContext != null) { + serviceConfig.setApplicationContext(applicationContext); + if (service.registry() != null && service.registry().length > 0) { + List registryConfigs = new ArrayList(); + for (String registryId : service.registry()) { + if (registryId != null && registryId.length() > 0) { + registryConfigs.add((RegistryConfig) applicationContext.getBean(registryId, RegistryConfig.class)); + } + } + serviceConfig.setRegistries(registryConfigs); + } + if (service.provider() != null && service.provider().length() > 0) { + serviceConfig.setProvider((ProviderConfig) applicationContext.getBean(service.provider(), ProviderConfig.class)); + } + if (service.monitor() != null && service.monitor().length() > 0) { + serviceConfig.setMonitor((MonitorConfig) applicationContext.getBean(service.monitor(), MonitorConfig.class)); + } + if (service.application() != null && service.application().length() > 0) { + serviceConfig.setApplication((ApplicationConfig) applicationContext.getBean(service.application(), ApplicationConfig.class)); + } + if (service.module() != null && service.module().length() > 0) { + serviceConfig.setModule((ModuleConfig) applicationContext.getBean(service.module(), ModuleConfig.class)); + } + if (service.provider() != null && service.provider().length() > 0) { + serviceConfig.setProvider((ProviderConfig) applicationContext.getBean(service.provider(), ProviderConfig.class)); + } else { + + } + if (service.protocol() != null && service.protocol().length > 0) { + List protocolConfigs = new ArrayList(); + for (String protocolId : service.registry()) { + if (protocolId != null && protocolId.length() > 0) { + protocolConfigs.add((ProtocolConfig) applicationContext.getBean(protocolId, ProtocolConfig.class)); + } + } + serviceConfig.setProtocols(protocolConfigs); + } + try { + serviceConfig.afterPropertiesSet(); + } catch (RuntimeException e) { + throw (RuntimeException) e; + } catch (Exception e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + serviceConfig.setRef(bean); + serviceConfigs.add(serviceConfig); + serviceConfig.export(); + } + return bean; + } + + public Object postProcessBeforeInitialization(Object bean, String beanName) + throws BeansException { + if (!isMatchPackage(bean)) { + return bean; + } + Method[] methods = bean.getClass().getMethods(); + for (Method method : methods) { + String name = method.getName(); + if (name.length() > 3 && name.startsWith("set") + && method.getParameterTypes().length == 1 + && Modifier.isPublic(method.getModifiers()) + && !Modifier.isStatic(method.getModifiers())) { + try { + Reference reference = method.getAnnotation(Reference.class); + if (reference != null) { + Object value = refer(reference, method.getParameterTypes()[0]); + if (value != null) { + method.invoke(bean, new Object[]{value}); + } + } + } catch (Throwable e) { + logger.error("Failed to init remote service reference at method " + name + " in class " + bean.getClass().getName() + ", cause: " + e.getMessage(), e); + } + } + } + Field[] fields = bean.getClass().getFields(); + for (Field field : fields) { + try { + if (!field.isAccessible()) { + field.setAccessible(true); + } + Reference reference = field.getAnnotation(Reference.class); + if (reference != null) { + Object value = refer(reference, field.getType()); + if (value != null) { + field.set(bean, value); + } + } + } catch (Throwable e) { + logger.error("Failed to init remote service reference at filed " + field.getName() + " in class " + bean.getClass().getName() + ", cause: " + e.getMessage(), e); + } + } + return bean; + } + + private Object refer(Reference reference, Class referenceClass) { //method.getParameterTypes()[0] + String interfaceName; + if (!"".equals(reference.interfaceName())) { + interfaceName = reference.interfaceName(); + } else if (!void.class.equals(reference.interfaceClass())) { + interfaceName = reference.interfaceClass().getName(); + } else if (referenceClass.isInterface()) { + interfaceName = referenceClass.getName(); + } else { + throw new IllegalStateException("The @Reference undefined interfaceClass or interfaceName, and the property type " + referenceClass.getName() + " is not a interface."); + } + String key = reference.group() + "/" + interfaceName + ":" + reference.version(); + ReferenceBean referenceConfig = referenceConfigs.get(key); + if (referenceConfig == null) { + referenceConfig = new ReferenceBean(reference); + if (void.class.equals(reference.interfaceClass()) + && "".equals(reference.interfaceName()) + && referenceClass.isInterface()) { + referenceConfig.setInterface(referenceClass); + } + if (applicationContext != null) { + referenceConfig.setApplicationContext(applicationContext); + if (reference.registry() != null && reference.registry().length > 0) { + List registryConfigs = new ArrayList(); + for (String registryId : reference.registry()) { + if (registryId != null && registryId.length() > 0) { + registryConfigs.add((RegistryConfig) applicationContext.getBean(registryId, RegistryConfig.class)); + } + } + referenceConfig.setRegistries(registryConfigs); + } + if (reference.consumer() != null && reference.consumer().length() > 0) { + referenceConfig.setConsumer((ConsumerConfig) applicationContext.getBean(reference.consumer(), ConsumerConfig.class)); + } + if (reference.monitor() != null && reference.monitor().length() > 0) { + referenceConfig.setMonitor((MonitorConfig) applicationContext.getBean(reference.monitor(), MonitorConfig.class)); + } + if (reference.application() != null && reference.application().length() > 0) { + referenceConfig.setApplication((ApplicationConfig) applicationContext.getBean(reference.application(), ApplicationConfig.class)); + } + if (reference.module() != null && reference.module().length() > 0) { + referenceConfig.setModule((ModuleConfig) applicationContext.getBean(reference.module(), ModuleConfig.class)); + } + if (reference.consumer() != null && reference.consumer().length() > 0) { + referenceConfig.setConsumer((ConsumerConfig) applicationContext.getBean(reference.consumer(), ConsumerConfig.class)); + } + try { + referenceConfig.afterPropertiesSet(); + } catch (RuntimeException e) { + throw (RuntimeException) e; + } catch (Exception e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + referenceConfigs.putIfAbsent(key, referenceConfig); + referenceConfig = referenceConfigs.get(key); + } + return referenceConfig.get(); + } + + private boolean isMatchPackage(Object bean) { + if (annotationPackages == null || annotationPackages.length == 0) { + return true; + } + String beanClassName = bean.getClass().getName(); + for (String pkg : annotationPackages) { + if (beanClassName.startsWith(pkg)) { + return true; + } + } + return false; + } + +} diff --git a/src/main/java/com/alibaba/dubbo/test/DubboFeatureTestApplication.java b/src/main/java/com/alibaba/dubbo/test/DubboFeatureTestApplication.java index d63335c..3270ab1 100644 --- a/src/main/java/com/alibaba/dubbo/test/DubboFeatureTestApplication.java +++ b/src/main/java/com/alibaba/dubbo/test/DubboFeatureTestApplication.java @@ -2,9 +2,12 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.FilterType; @SpringBootApplication +@ComponentScan(basePackages = {"com.alibaba.dubbo.test"}, includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {com.alibaba.dubbo.config.annotation.Service.class, com.alibaba.dubbo.config.annotation.Reference.class})}) public class DubboFeatureTestApplication { public static void main(String[] args) throws InterruptedException { diff --git a/src/main/java/com/alibaba/dubbo/test/conf/DubboConfiguration.java b/src/main/java/com/alibaba/dubbo/test/conf/DubboConfiguration.java index 18520cc..d48269a 100644 --- a/src/main/java/com/alibaba/dubbo/test/conf/DubboConfiguration.java +++ b/src/main/java/com/alibaba/dubbo/test/conf/DubboConfiguration.java @@ -1,6 +1,8 @@ package com.alibaba.dubbo.test.conf; +import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.ImportResource; /** diff --git a/src/main/java/com/alibaba/dubbo/test/service/AnnotateService.java b/src/main/java/com/alibaba/dubbo/test/service/AnnotateService.java new file mode 100644 index 0000000..9bdbaa1 --- /dev/null +++ b/src/main/java/com/alibaba/dubbo/test/service/AnnotateService.java @@ -0,0 +1,8 @@ +package com.alibaba.dubbo.test.service; + +/** + * Created by ken.lj on 2017/9/19. + */ +public interface AnnotateService { + String sayHello(); +} diff --git a/src/main/java/com/alibaba/dubbo/test/service/impl/AnnotateServiceImpl.java b/src/main/java/com/alibaba/dubbo/test/service/impl/AnnotateServiceImpl.java new file mode 100644 index 0000000..bad2f2f --- /dev/null +++ b/src/main/java/com/alibaba/dubbo/test/service/impl/AnnotateServiceImpl.java @@ -0,0 +1,15 @@ +package com.alibaba.dubbo.test.service.impl; + +import com.alibaba.dubbo.config.annotation.Service; +import com.alibaba.dubbo.test.service.AnnotateService; + +/** + * Created by ken.lj on 2017/9/19. + */ +@Service +public class AnnotateServiceImpl implements AnnotateService { + @Override + public String sayHello() { + return "Hello"; + } +} diff --git a/src/main/java/com/alibaba/dubbo/test/web/BaseController.java b/src/main/java/com/alibaba/dubbo/test/web/BaseController.java new file mode 100644 index 0000000..a2d7200 --- /dev/null +++ b/src/main/java/com/alibaba/dubbo/test/web/BaseController.java @@ -0,0 +1,27 @@ +package com.alibaba.dubbo.test.web; + +import com.alibaba.dubbo.config.annotation.Reference; +import com.alibaba.dubbo.test.service.AnnotateService; + +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * Created by ken.lj on 2017/9/19. + */ +public class BaseController { + @Reference + public T annotateService; + + @RequestMapping("/hello") + String hello() { + return annotateService.sayHello(); + } + + public T getAnnotateService() { + return annotateService; + } + + public void setAnnotateService(T annotateService) { + this.annotateService = annotateService; + } +} diff --git a/src/main/java/com/alibaba/dubbo/test/web/HelloController.java b/src/main/java/com/alibaba/dubbo/test/web/HelloController.java new file mode 100644 index 0000000..d244964 --- /dev/null +++ b/src/main/java/com/alibaba/dubbo/test/web/HelloController.java @@ -0,0 +1,16 @@ +package com.alibaba.dubbo.test.web; + +import com.alibaba.dubbo.config.annotation.Reference; +import com.alibaba.dubbo.test.service.AnnotateService; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * Created by ken.lj on 2017/9/19. + */ +@RestController +public class HelloController extends BaseController { + + +} diff --git a/src/main/resources/dubbo-annotation.xml b/src/main/resources/dubbo-annotation.xml new file mode 100644 index 0000000..4e01d66 --- /dev/null +++ b/src/main/resources/dubbo-annotation.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/dubbo-mouse.xml b/src/main/resources/dubbo-mouse.xml index 8e4311d..bb818ad 100644 --- a/src/main/resources/dubbo-mouse.xml +++ b/src/main/resources/dubbo-mouse.xml @@ -21,9 +21,9 @@ http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> - + - + diff --git a/src/test/java/com/alibaba/dubbo/test/ObjectMapConvertTest.java b/src/test/java/com/alibaba/dubbo/test/ObjectMapConvertTest.java new file mode 100644 index 0000000..c8a679c --- /dev/null +++ b/src/test/java/com/alibaba/dubbo/test/ObjectMapConvertTest.java @@ -0,0 +1,41 @@ +package com.alibaba.dubbo.test; + +import java.util.Map; + +/** + * Created by ken.lj on 2017/9/12. + */ +public class ObjectMapConvertTest { + public static void main(String[] args) { + Class cls = Person.class; + Map personMap = (Map )(new Person(1, "chiken")); + System.out.println(personMap); + } + +} + +class Person { + private int id; + private String name; + + public Person(int id, String name) { + this.id = id; + this.name = name; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +}