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