利用注册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);
}
}
如果只是注册服务获取引用服务使用其中一个方法就行了。 第一次写文章,有不对的地方或者写得不好的地方大家多多指点,共同进步。。。。。