Dubbo动态调用、自动注册、引用dubbo服务,Dubbo

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

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

1
2
3
4
5
6
7
8
less复制代码@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的时候注意

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
ini复制代码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等可从配置文件中读取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
ini复制代码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等也可从配置文件中读取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
ini复制代码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动态调用,参数可从数据库中获取,记得加缓存,每次从数据库中获取会影响性能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
ini复制代码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);
}

}

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

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%