让dubbo支持@Autowired注解

2018-12-10 发表在 编程语言 4677


    参考文章:http://dubbo.apache.org/zh-cn/docs/user/configuration/api.html

    直接利用dubbo手动注册方式,对service进行注册,然后Controller 直接 @Autowired xxxService 就可以了。

    import com.alibaba.dubbo.config.ApplicationConfig;
    import com.alibaba.dubbo.config.ReferenceConfig;
    import com.alibaba.dubbo.config.RegistryConfig;
    import com.alibaba.dubbo.config.annotation.Reference;
    import com.zh.tourist.service.FeedbackService;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
    import org.springframework.beans.factory.support.BeanDefinitionRegistry;
    import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
    import org.springframework.core.env.Environment;
    import org.springframework.stereotype.Controller;
    
    import java.lang.reflect.Field;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * dubbo自动注入支持,让dubbo支持spring的@org.springframework.beans.factory.annotation.Autowired 并且兼容 @com.alibaba.dubbo.config.annotation.Reference
     *
     * @author panjing
     * @link http://dubbo.apache.org/zh-cn/docs/user/configuration/api.html
     */
    //@Configuration
    public class DubboAutowiredSupport implements BeanDefinitionRegistryPostProcessor {
    
        private Environment env;
    
    
        private static final Log LOG = LogFactory.getLog(DubboAutowiredSupport.class);
    
        //接口实例缓存
        private static Map<Class, Object> instanceCache = new HashMap<>();
    
        //应用程序信息
        private ApplicationConfig application;
    
        //注册中心信息
        private RegistryConfig registry;
    
        private Boolean registryCheck;
        private Integer registryTimeout;
    
    
        public DubboAutowiredSupport() {
    
        }
    
        /**
         * 获取dubbo的bean
         *
         * @param clazz
         * @param <T>
         * @return
         */
        public <T> T getBean(Class clazz) {
    
    
            Object instance = instanceCache.get(clazz);
    
            if (instance != null) {
                return (T) instance;
            }
    
            // 注意:ReferenceConfig为重对象,内部封装了与注册中心的连接,以及与服务提供方的连接
    
            // 引用远程服务
            ReferenceConfig<T> reference = new ReferenceConfig<>(); // 此实例很重,封装了与注册中心的连接以及与提供者的连接,请自行缓存,否则可能造成内存和连接泄漏
            reference.setApplication(application);
            reference.setRegistry(registry); // 多个注册中心可以用setRegistries()
            reference.setInterface(clazz);
            reference.setCheck(registryCheck);
            reference.setTimeout(registryTimeout);
            //reference.setVersion("1.0.0");
    
            // 和本地bean一样使用xxxService
            instance = reference.get(); // 注意:此代理对象内部封装了所有通讯细节,对象较重,请缓存复用
            instanceCache.put(clazz, instance);
    
            return (T) instance;
        }
    
    
        public static void main(String[] args) {
    
            FeedbackService service = new DubboAutowiredSupport().getBean(FeedbackService.class);
            System.out.println(service);
    
        }
    
        @Override
        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
    
        }
    
        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    
            //获取所有dubbo的service,进行缓存
            if (env == null) {
                this.env = beanFactory.getBean(Environment.class);
                // 当前应用配置
                application = new ApplicationConfig();
                application.setName(env.getProperty("dubbo.application.name"));
    
                // 连接注册中心配置
                registry = new RegistryConfig();
                registry.setAddress(env.getProperty("dubbo.registry.address"));
                registry.setProtocol(env.getProperty("dubbo.protocol"));
    
                registryCheck = Boolean.valueOf(env.getProperty("dubbo.consumer.check", "false"));
                registryTimeout = Integer.valueOf(env.getProperty("dubbo.consumer.timeout"));
    
                registry.setCheck(registryCheck);
                registry.setTimeout(registryTimeout);
            }
            //获取到所有的控制器后,把bean注入进去
            String[] names = beanFactory.getBeanNamesForAnnotation(Controller.class);
            LOG.info(String.format("Controller 数量:%s", names.length - 1));
            for (String name : names) {
                if ("basicErrorController".equals(name)) {
                    continue;
                }
                try {
                    Object bean = beanFactory.getBean(name);
                    if (bean != null) {
                        processAutowired(bean);
                    }
                } catch (Exception e) {
                    LOG.info(e);
                }
            }
        }
    
    
        /**
         * 处理bean的自动注入
         *
         * @param bean
         */
        private void processAutowired(Object bean) {
            try {
                Class clazz = bean.getClass();
                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields) {
                    //如果有Autowried注解,或者dubbo的注解,并且为null的时候
                    field.setAccessible(true);
    
                    //字段没有注入的时候进行注入
                    if (field.get(bean) == null && (field.getAnnotation(Autowired.class) != null || field.getAnnotation(Reference.class) != null)) {
    
                        Class fieldType = field.getType();
    
                        //获取实例
                        Object instance = getBean(fieldType);
                        field.set(bean, instance);
                        LOG.info(String.format("%s 注入bean %s", clazz.getSimpleName(), fieldType));
                    }
    
                }
            } catch (Exception e) {
                //抛出运行时异常中断初始化过程
                throw new RuntimeException(e);
            }
        }
    }


    作者:Java笔记
    本站使用「署名 4.0 国际」创作共享协议,转载请在文章明显位置注明作者及出处。
    评论
    登录以后才可以发布评论哦, 点击登录 发布评论
    评论列表 0人参与,0条评论
    暂时还没有人评论,快来一条神回复吧!