自定义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");
}

 

posted @ 2019-02-22 12:03  Jack_Lei  阅读(2286)  评论(0编辑  收藏  举报