Java Spring在运行时不会发现新上下文的@RequestMapping注释

Java Spring在运行时不会发现新上下文的@RequestMapping注释,java,spring,spring-mvc,spring-boot,request-mapping,Java,Spring,Spring Mvc,Spring Boot,Request Mapping,我只是尝试为我的spring boot web应用程序开发一个插件系统。应用程序使用根上下文路径部署在tomcat服务器上。插件系统允许我在运行时加载特别准备的jar文件。系统还应该能够在运行时取消部署插件。这些JAR包含在当前工作目录的插件文件夹中。我希望每个插件都有自己的spring上下文来操作。依赖项注入按预期工作,但spring没有发现插件上下文的@RequestMapping注释。所以我的问题是:如何让spring发现我的插件的@RequestMapping注释(在运行时) 我使用的是

我只是尝试为我的spring boot web应用程序开发一个插件系统。应用程序使用根上下文路径部署在tomcat服务器上。插件系统允许我在运行时加载特别准备的jar文件。系统还应该能够在运行时取消部署插件。这些JAR包含在当前工作目录的插件文件夹中。我希望每个插件都有自己的spring上下文来操作。依赖项注入按预期工作,但spring没有发现插件上下文的@RequestMapping注释。所以我的问题是:如何让spring发现我的插件的@RequestMapping注释(在运行时)

我使用的是最新的spring boot版本和以下application.yml:

# Server
server:
  error:
    whitelabel:
      enabled: true
  session:
    persistent: true
  tomcat:
    uri-encoding: UTF-8
# Spring
spring:
  application:
    name: Plugins
  mvc:
    favicon:
      enabled: false
  favicon:
    enabled: false
  thymeleaf:
    encoding: UTF-8
# Logging
logging:
  file: application.log
  level.: error
这是加载插件的代码:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
URLClassLoader urlClassLoader = URLClassLoader.newInstance(new URL[] { plugin.getPluginURL() }, getClass().getClassLoader()); // plugin.getPluginURL will refer to a jar file with the plugin code (see below).
context.setClassLoader(urlClassLoader);
context.setParent(applicationContext); // applicationContext is the the context of the original spring application. It was autowired.
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context, true);
scanner.scan("my.plugin.package");
context.refresh();
控制器代码(在我的插件中):

但是,我仍在寻找一种方法,使用spring方式使其工作:


感谢阅读。

您是否在spring_servlet.xml中的context:component scan base package=“location”中添加了控制器位置SpringMvc有自己的缓存
@RequestMapping
,详细代码是
RequestMappingHandlerMapping
。如您所见,显示了init方法,也许您可以在加载新插件后调用init方法

protected void initHandlerMethods() {
        if (logger.isDebugEnabled()) {
            logger.debug("Looking for request mappings in application context: " + getApplicationContext());
        }

        String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?
                BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
                getApplicationContext().getBeanNamesForType(Object.class));

        for (String beanName : beanNames) {
            if (isHandler(getApplicationContext().getType(beanName))){
                detectHandlerMethods(beanName);
            }
        }
        handlerMethodsInitialized(getHandlerMethods());
    }

这是spring3的
RequestMappingHandlerMapping
code,可能spring4的impl中有一些变化。

我认为,您需要添加

<context:component-scan base-package="package_name" />
<mvc:annotation-driven />
<mvc:default-servlet-handler />


在你的xxx-servlet.xml文件中。

你能发布你的application.properties吗?@Alex我刚刚更新了帖子以包含我的应用程序。ymlI刚刚注意到你的pluginestcontroller.doGet方法是私有的。我目前无法测试它,但您确定这是受支持的吗?好的,查一下,它是被支持的。()但我还是会尝试将方法更改为public@Alex我只是尝试了一下,但仍然不起作用。我想您可能需要在容器中注册Spring的DispatcherServlet的新实例。在这里进行推测,但当您初始化SpringWeb应用程序时,spring的DispatcherServlet和相关的委托会找出如何将请求映射到您的bean。您可能需要一个新的web应用上下文,其中包含与servlet容器相关的管道(例如tomcat或jetty),在单独的评论中建议一种替代方法,因为我已经用完了spi,我使用spring boot和rhe java annotatiom驱动的方式来配置我的控制器。因此,该项目没有spring_servlet.xml。这实际上非常有用,与我昨晚已经计算出的代码类似。到目前为止,我正在使用一种类似的方法,基于这个问题的答案:。我刚刚更新了我的答案,加入了使控制器为我工作的代码。我不认为我的aproach是完美的,但至少现在它的工作。我将看看spring4实现它的方式。谢谢你指出代码。我很高兴能帮助你,如果你有新的研究结果,你会更新这篇文章吗?我使用spring boot和java注释驱动的方式来配置我的控制器。因此,该项目没有spring_servlet.xml。这个问题也已经得到了回答
protected void initHandlerMethods() {
        if (logger.isDebugEnabled()) {
            logger.debug("Looking for request mappings in application context: " + getApplicationContext());
        }

        String[] beanNames = (this.detectHandlerMethodsInAncestorContexts ?
                BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
                getApplicationContext().getBeanNamesForType(Object.class));

        for (String beanName : beanNames) {
            if (isHandler(getApplicationContext().getType(beanName))){
                detectHandlerMethods(beanName);
            }
        }
        handlerMethodsInitialized(getHandlerMethods());
    }
<context:component-scan base-package="package_name" />
<mvc:annotation-driven />
<mvc:default-servlet-handler />