pf4j 注入spring controller 的几种方法

核心还是基于RequestMappingHandlerMapping bean 进行controller 的创建

方法一

获取RequestMappingHandlerMapping bean 注册registerMapping
参考(参考伪代码)

 
getMappingForMethod = ReflectionUtils.findMethod(RequestMappingHandlerMapping.class, "getMappingForMethod", Method.class, Class.class);
 
Controller annotation = aClass.getAnnotation(Controller.class);
if(annotation != null) {
    Object bean = <getPluginApplicationContext()>.getBean(aClass); // use parent context( PluginManager)
    Method[] methods = aClass.getMethods();
    for (Method method : methods) {
        if (method.getAnnotation(RequestMapping.class) != null
                || method.getAnnotation(GetMapping.class) != null
                || method.getAnnotation(PostMapping.class) != null) {
            RequestMappingInfo requestMappingInfo = (RequestMappingInfo) getMappingForMethod.invoke(requestMappingHandlerMapping, method, aClass);
            requestMappingHandlerMapping.registerMapping(requestMappingInfo, bean, method);
        }
    }
}

方法二

自己实现AbstractHandlerMapping ,注册一个自己的WebMvcRegistrations bean 对于spring boot 可以直接实现WebMvcRegistrations
参考

 
@Bean
@ConditionalOnMissingBean(WebMvcRegistrations.class)
public WebMvcRegistrations mvcRegistrations() {
    return new WebMvcRegistrations() {
        @Override
        public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
            return new <custom>RequestMappingHandlerMapping();
        }
 
        @Override
        public RequestMappingHandlerAdapter getRequestMappingHandlerAdapter() {
            return null;
        }
 
        @Override
        public ExceptionHandlerExceptionResolver getExceptionHandlerExceptionResolver() {
            return null;
        }
    };
}

自定义RequestMappingHandlerMapping 实现一个基于注解注册controller 的方法,这样在处理阶段就比较方便了

public void registerControllers(SpringBootPlugin springBootPlugin) {
    getControllerBeans(springBootPlugin).forEach(bean -> registerController(springBootPlugin, bean));
}
 
private void registerController(SpringBootPlugin springBootPlugin, Object controller) {
    String beanName = controller.getClass().getName();
    // unregister RequestMapping if already registered
    unregisterController(springBootPlugin.getMainApplicationContext(), controller);
    springBootPlugin.registerBeanToMainContext(beanName, controller);
    detectHandlerMethods(controller);
}

注意bean 也是注册到main context 基于此方法的好处是能够更好的利用detectHandlerMethods
进行handler 的处理,与上边实际是类似的,但是更加符合spring 的处理机制

说明

对于resource 的处理,我们也可以自己实现一个PathResourceResolver,扩展WebMvcConfigurer
添加一个自己的resourcehandler

 
default void addResourceHandlers(ResourceHandlerRegistry registry) {
}

sbp 的一些实现是很值得借鉴参考的

参考资料

https://github.com/hank-cp/sbp
https://gitee.com/dianbuapp_admin/jeegot

posted on 2022-02-20 14:05  荣锋亮  阅读(450)  评论(0编辑  收藏  举报

导航