自定义Dubbo泛型调用注解
1. 引入Dubbo spring boot starter
<dependency> <groupId>com.alibaba.boot</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>0.2.1.RELEASE</version> </dependency>
2. 创建引用注解 GenericReference
@Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE}) public @interface GenericReference { String remote() default ""; String interfaceName() default ""; }
3. 创建Dubbo对象GenericDubbo
public class GenericDubbo { public String remote; public String interfaceName; //单个参数 public Object invoke(String methodName, String paramType, Object paramValue){ GenericService genericService = getReferenceConfig().get(); return genericService.$invoke(methodName, new String[]{paramType}, new Object[]{paramValue}); }
//多个参数 public Object invoke(String methodName, String[] paramType, Object[] paramValue){ GenericService genericService = getReferenceConfig().get(); return genericService.$invoke(methodName, paramType, paramValue); } private ReferenceConfig<GenericService> getReferenceConfig(){ String key = remote+"-"+interfaceName; if(Global.referenceConfigLinkedHashMap.containsKey(key)){ return Global.referenceConfigLinkedHashMap.get(key); }else{ ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>(); reference.setApplication(new ApplicationConfig("dubbo")); reference.setInterface(interfaceName); reference.setUrl(remote); reference.setGeneric(true); Global.referenceConfigLinkedHashMap.put(key, reference); return reference; } } }
4. 巧用BeanPostProcessor实现Dubbo对象自动注入
@Component public class GenericReferenceProcessor implements BeanPostProcessor { private ConfigurableListableBeanFactory configurableBeanFactory; @Autowired public GenericReferenceProcessor(ConfigurableListableBeanFactory beanFactory) { this.configurableBeanFactory = beanFactory; } //bean初始化方法调用前被调用 @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { this.scanGenericReferenceAnnotation(bean); return bean; } //bean初始化方法调用后被调用 @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return bean; } protected void scanGenericReferenceAnnotation(Object bean) { this.configureFieldInjection(bean); } private void configureFieldInjection(Object bean) { Class<?> managedBeanClass = bean.getClass(); ReflectionUtils.FieldCallback fieldCallback = new GenericReferenceFieldCallback(configurableBeanFactory, bean); ReflectionUtils.doWithFields(managedBeanClass, fieldCallback); } }
5. 注入逻辑实现
public class GenericReferenceFieldCallback implements ReflectionUtils.FieldCallback { private static int AUTOWIRE_MODE = AutowireCapableBeanFactory.AUTOWIRE_BY_NAME; private ConfigurableListableBeanFactory configurableBeanFactory; private Object bean; public GenericReferenceFieldCallback(ConfigurableListableBeanFactory bf, Object bean) { configurableBeanFactory = bf; this.bean = bean; } @Override public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException { if (!field.isAnnotationPresent(GenericReference.class)) { return; } ReflectionUtils.makeAccessible(field); Class<?> generic = field.getType(); String remote = field.getDeclaredAnnotation(GenericReference.class).remote(); String interfaceName = field.getDeclaredAnnotation(GenericReference.class).interfaceName(); Object beanInstance = getBeanInstance(GenericDubbo.class.getName(), generic); ReflectionUtils.setField(ReflectionUtils.findField(GenericDubbo.class, "remote"), beanInstance, remote); ReflectionUtils.setField(ReflectionUtils.findField(GenericDubbo.class, "interfaceName"), beanInstance, interfaceName); field.set(bean, beanInstance); } public Object getBeanInstance(String beanName, Class<?> genericClass) { Object daoInstance = null; //if (!configurableBeanFactory.containsBean(beanName)) { Object toRegister = null; try { Constructor<?> ctr = genericClass.getConstructor(); toRegister = ctr.newInstance(); } catch (Exception e) { throw new RuntimeException(e); } daoInstance = configurableBeanFactory.initializeBean(toRegister, beanName); //以下两行是确保注入对象保持单例 //configurableBeanFactory.autowireBeanProperties(daoInstance, AUTOWIRE_MODE, true); //configurableBeanFactory.registerSingleton(beanName, daoInstance); /*} else { daoInstance = configurableBeanFactory.getBean(beanName); }*/ return daoInstance; } }
6. 创建Dubbo provider service
public interface INewsService{ String test(String param); }
@Service(interfaceClass = INewsService.class, delay = 5000) public class NewsServiceImpl implements INewsService { @Override public String test(String param){ return "Get param: "+param; } }
7. 调用例子
@GenericReference(remote = "dubbo://127.0.0.1:20889", interfaceName = "com.test.service.INewsService") private GenericDubbo genericDubbo; @RequestMapping("/test") public void test(){ System.out.print(genericDubbo.invoke("test","java.lang.String", "hello"); }