千家信息网

dubbo中SpringExtensionFactory有什么用

发表于:2025-12-03 作者:千家信息网编辑
千家信息网最后更新 2025年12月03日,dubbo中SpringExtensionFactory有什么用,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。ExtensionFact
千家信息网最后更新 2025年12月03日dubbo中SpringExtensionFactory有什么用

dubbo中SpringExtensionFactory有什么用,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

ExtensionFactory

dubbo-2.7.3/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionFactory.java

@SPIpublic interface ExtensionFactory {    /**     * Get extension.     *     * @param type object type.     * @param name object name.     * @return object instance.     */     T getExtension(Class type, String name);}
  • ExtensionFactory接口定义了getExtension方法

SpringExtensionFactory

dubbo-2.7.3/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/extension/SpringExtensionFactory.java

public class SpringExtensionFactory implements ExtensionFactory {    private static final Logger logger = LoggerFactory.getLogger(SpringExtensionFactory.class);    private static final Set CONTEXTS = new ConcurrentHashSet();    private static final ApplicationListener SHUTDOWN_HOOK_LISTENER = new ShutdownHookListener();    public static void addApplicationContext(ApplicationContext context) {        CONTEXTS.add(context);        if (context instanceof ConfigurableApplicationContext) {            ((ConfigurableApplicationContext) context).registerShutdownHook();            DubboShutdownHook.getDubboShutdownHook().unregister();        }        BeanFactoryUtils.addApplicationListener(context, SHUTDOWN_HOOK_LISTENER);    }    public static void removeApplicationContext(ApplicationContext context) {        CONTEXTS.remove(context);    }    public static Set getContexts() {        return CONTEXTS;    }    // currently for test purpose    public static void clearContexts() {        CONTEXTS.clear();    }    @Override    @SuppressWarnings("unchecked")    public  T getExtension(Class type, String name) {        //SPI should be get from SpiExtensionFactory        if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {            return null;        }        for (ApplicationContext context : CONTEXTS) {            if (context.containsBean(name)) {                Object bean = context.getBean(name);                if (type.isInstance(bean)) {                    return (T) bean;                }            }        }        logger.warn("No spring extension (bean) named:" + name + ", try to find an extension (bean) of type " + type.getName());        if (Object.class == type) {            return null;        }        for (ApplicationContext context : CONTEXTS) {            try {                return context.getBean(type);            } catch (NoUniqueBeanDefinitionException multiBeanExe) {                logger.warn("Find more than 1 spring extensions (beans) of type " + type.getName() + ", will stop auto injection. Please make sure you have specified the concrete parameter type and there's only one extension of that type.");            } catch (NoSuchBeanDefinitionException noBeanExe) {                if (logger.isDebugEnabled()) {                    logger.debug("Error when get spring extension(bean) for type:" + type.getName(), noBeanExe);                }            }        }        logger.warn("No spring extension (bean) named:" + name + ", type:" + type.getName() + " found, stop get bean.");        return null;    }    private static class ShutdownHookListener implements ApplicationListener {        @Override        public void onApplicationEvent(ApplicationEvent event) {            if (event instanceof ContextClosedEvent) {                DubboShutdownHook shutdownHook = DubboShutdownHook.getDubboShutdownHook();                shutdownHook.doDestroy();            }        }    }}
  • SpringExtensionFactory实现了ExtensionFactory方法,它提供了addApplicationContext静态方法来添加ApplicationContext,同时注册了SHUTDOWN_HOOK_LISTENER;其getExtension方法首先根据name从ApplicationContext中获取bean,获取不到则在根据type再去ApplicationContext中获取bean,获取不到则返回null

SpringExtensionFactoryTest

dubbo-2.7.3/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/extension/SpringExtensionFactoryTest.java

@Configurationpublic class SpringExtensionFactoryTest {    private SpringExtensionFactory springExtensionFactory = new SpringExtensionFactory();    private AnnotationConfigApplicationContext context1;    private AnnotationConfigApplicationContext context2;    @BeforeEach    public void init() {        context1 = new AnnotationConfigApplicationContext();        context1.register(getClass());        context1.refresh();        context2 = new AnnotationConfigApplicationContext();        context2.register(BeanForContext2.class);        context2.refresh();        SpringExtensionFactory.addApplicationContext(context1);        SpringExtensionFactory.addApplicationContext(context2);    }    @Test    public void testGetExtensionBySPI() {        Protocol protocol = springExtensionFactory.getExtension(Protocol.class, "protocol");        Assertions.assertNull(protocol);    }    @Test    public void testGetExtensionByName() {        DemoService bean = springExtensionFactory.getExtension(DemoService.class, "bean1");        Assertions.assertNotNull(bean);    }    @Test    public void testGetExtensionByTypeMultiple() {        try {            springExtensionFactory.getExtension(DemoService.class, "beanname-not-exist");        } catch (Exception e) {            e.printStackTrace();            Assertions.assertTrue(e instanceof NoUniqueBeanDefinitionException);        }    }    @Test    public void testGetExtensionByType() {        HelloService bean = springExtensionFactory.getExtension(HelloService.class, "beanname-not-exist");        Assertions.assertNotNull(bean);    }    @AfterEach    public void destroy() {        SpringExtensionFactory.clearContexts();        context1.close();        context2.close();    }    @Bean("bean1")    public DemoService bean1() {        return new DemoServiceImpl();    }    @Bean("bean2")    public DemoService bean2() {        return new DemoServiceImpl();    }    @Bean("hello")    public HelloService helloService() {        return new HelloServiceImpl();    }}
  • SpringExtensionFactoryTest的init方法给springExtensionFactory添加了context1和context2;之后验证了根据SPI、根据name、根据type来获取extension

小结

SpringExtensionFactory实现了ExtensionFactory方法,它提供了addApplicationContext静态方法来添加ApplicationContext,同时注册了SHUTDOWN_HOOK_LISTENER;其getExtension方法首先根据name从ApplicationContext中获取bean,获取不到则在根据type再去ApplicationContext中获取bean,获取不到则返回null

看完上述内容,你们掌握dubbo中SpringExtensionFactory有什么用的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注行业资讯频道,感谢各位的阅读!

0