Dubbo动态调用、自动注册、引用dubbo服务,Dubbo注解整合Spring注解,不用xml配置、和dubbo注解

1,767 阅读1分钟

利用注册bean过滤接口获取注册bean和bean的属性动态注册或者引用dubbo服务

启动类配置@ComponentScan(excludeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM, classes = {BeanFilter.class})})

@ComponentScan(excludeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM, classes = {BeanFilter.class})})
@SpringBootApplication
public class DubboDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DubboDemoApplication.class,args);
    }
}

实现TypeFilter接口,默认取实现的第一个接口(可做修改),如果Service注解没有设置value值,spring注册的bean是实现类的首字母小写,获取bean的时候注意

public class BeanFilter  implements TypeFilter{

    @Override
    public boolean match(MetadataReader reader, MetadataReaderFactory factory) throws IOException {
        AnnotationMetadata annotationMetadata = reader.getAnnotationMetadata();
        //扫描Spring的service注解
        Map<String, Object> annotationAttributes = annotationMetadata.getAnnotationAttributes(Service.class.getName());
        AnnotationAttributes annoAttrs = AnnotationAttributes.fromMap(annotationAttributes);
        if(ObjectUtil.isNotNull(annoAttrs)){
            String[] interfaceNames = reader.getAnnotationMetadata().getInterfaceNames();
            //注册dubbo服务
            if(interfaceNames.length > 0){
                //默认注册第一个实现接口
                providerConfig(interfaceNames[0],annoAttrs.getString("value"));
            }
            //引用dubbo服务
            String className = annotationMetadata.getClassName();
            Field[] declaredFields = Class.forName(className).getDeclaredFields();
            for (Field field : declaredFields) {
                //获取属性上面所有注解
                Annotation[] annotations = field.getAnnotations();
                for (int i = 0; i < annotations.length; i++) {
                    Annotation annotation =  annotations[i];
                    String beanName = "";
                    if(annotation instanceof Resource || annotation instanceof Autowired){
                        String name = field.getType().getName();
                        //过滤不需要引用的bean
                        if(name.contains(".mapper.") ){
                            continue;
                        }

                        Autowired annotation2 = field.getAnnotation(Autowired.class);
                        if(ObjectUtil.isNotNull(annotation2)){
                            if(!annotation2.required()){
                                continue;
                            }
                        }
                        if(StrUtil.isBlank(beanName)){
                            String[] splits = field.getType().getName().split("\.");
                            beanName = splits[splits.length-1];
                            beanName = lowerFirstCase(beanName);
                        }
                        //过滤重复的bean
                        if(!callBeans.containsKey(beanName)){
                            callBeans.put(beanName,Class.forName(field.getType().getName()));
                            referenceConfig(field.getType().getName(),beanName);
                        }
                    }
                }
            }
        }
        return false;
    }

注册dubbo服务方法,dubbo注册参参数group、version等可从配置文件中读取

private void providerConfig(String ClassName, String beanName) {

        ServiceConfig<Object> serviceConfig = new ServiceConfig<>();
        serviceConfig.setInterface(Class.forName(beanName));
        serviceConfig.setRef(beanFactory.getBean(beanName));
        serviceConfig.setVersion("2.1");
        serviceConfig.setGroup("test");
        serviceConfig.setTimeout(50000);

        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("applicationName");
        serviceConfig.setApplication(applicationConfig);

        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setProtocol("zookeeper");
        registryConfig.setAddress("127.0.0.1:2181");
        serviceConfig.setRegistry(registryConfig);

        ProtocolConfig protocolConfig = new ProtocolConfig();
        protocolConfig.setName("dubbo");
        protocolConfig.setPort(-1);
        protocolConfig.setHost("0.0.0.0");
        serviceConfig.setProtocol(protocolConfig);

        //注册服务
        serviceConfig.export();
}

引用dubbo服务方法包含dubbo动态调用。group、version等也可从配置文件中读取

private void referenceConfig(String className,String beanName){
    //spring和redis的jar包不适用dubbo调用相关的bean
    if(className.contains("org.springframework") || className.contains("org.redisson.api")){
        return;
    }
    //自己服务不使用dubbo
    if(className.contains("com.dubbo.demo")){
        return;
    }
    ReferenceConfig<Object> referenceConfig = new ReferenceConfig<>();
    referenceConfig.setInterface(Class.forName(className));
    // 负载均衡策略,可选值:random,roundrobin,leastactive,分别表示:随机,轮询,最少活跃调用
    referenceConfig.setLoadbalance("random");
    referenceConfig.setId(beanName);
    referenceConfig.setVersion("*");
    referenceConfig.setGroup("test");
    referenceConfig.setTimeout(5000);
    referenceConfig.setCheck(false);

    ConsumerConfig consumerConfig = new ConsumerConfig();
    consumerConfig.setCheck(false);
    referenceConfig.setConsumer(consumerConfig);

    ApplicationConfig applicationConfig = new ApplicationConfig();
    applicationConfig.setName("applicationName");
    referenceConfig.setApplication(applicationConfig);

    RegistryConfig registryConfig = new RegistryConfig();
    registryConfig.setProtocol("zookeeper");
    registryConfig.setAddress("addr");
    referenceConfig.setRegistry(registryConfig);

    //过滤指定路径的包动态调用代理一个类出来使用
    if(className.contains("com.dubbo.api")){
        Class<?> aClass = Class.forName(className);
        Object o = Proxy.getProxy(aClass).newInstance(new DubboHandler(referenceConfig));
        beanFactory.registerSingleton(beanName,o);
        return;
    }

    Object o = referenceConfig.get();
    beanFactory.registerSingleton(beanName,o);

}

dubbo动态调用,参数可从数据库中获取,记得加缓存,每次从数据库中获取会影响性能

public class DubboHandler implements InvocationHandler {

    private ReferenceConfig referenceConfig;


    public DubboHandler(){

    }

    public DubboHandler(ReferenceConfig referenceConfig){
        this.referenceConfig = referenceConfig;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        DubboConfigService dubboConfigService = ContextUtils.getApplicationContext().getBean(DubboConfigService.class);
        DubboConfig dubboConfig = dubboConfigService.getDubboConfig();
        RegistryConfig registryConfig = new RegistryConfig();
        referenceConfig.setProtocol("zookeeper");
        registryConfig.setAddress(dubboConfig.getAddr());
        referenceConfig.setGroup(dubboConfig.getGroup());
        referenceConfig.setVersion(dubboConfig.getVersion());
        referenceConfig.setRegistry(registryConfig);
        ReferenceConfig newReferenceConfig = new ReferenceConfig();
        BeanUtils.copyProperties(referenceConfig ,newReferenceConfig);
        ReferenceConfigCache cache = ReferenceConfigCache.getCache();
        Object o = cache.get(newReferenceConfig);
        return method.invoke(o, args);
    }

}

如果只是注册服务获取引用服务使用其中一个方法就行了。 第一次写文章,有不对的地方或者写得不好的地方大家多多指点,共同进步。。。。。