Spring:正确设置@ComponentScan

7

我有一个关于Spring应用上下文的设置如下:


@Configuration
public class RmiContext {
@Bean
    public RmiProxyFactoryBean service() {
        RmiProxyFactoryBean rmiProxy = new RmiProxyFactoryBean();
        rmiProxy.setServiceUrl("rmi://127.0.1.1:1099/Service");
        rmiProxy.setServiceInterface(Service.class);
        return rmiProxy;
    }
}


@Configuration
public class LocalContext {
@Bean
    public Controller Controller() {
        return new ControllerImpl();
    }
}


@Configuration
@Import({RmiContext.class, LocalContext.class})
public class MainContext {

上述设置可以正常工作,但我想启用@ComponentScan注释@ComponentController,因为我的应用程序中有许多Controller,如果使用@Bean一个个声明就很繁琐。


@Configuration
@ComponentScan(basePackageClasses = {Controller.class})
public class LocalContext {
    /* ... */
}
The problem is that when I do @ComponentScan(basePackageClasses = {Controller.class}), the previously fine working RmiProxyFactoryBean are not recognized or can't be created.

那么,我该如何配置我的MainContext,以便通过RMI和本地bean创建两个bean?

3个回答

2

@Configuration也是组件扫描的候选对象,因此您可以通过以下方式扫描RmiContext中的所有bean和控制器包中的所有控制器:

@Configuration
@ComponentScan(basePackages = {"org.example.controllers", "package.of.RmiContext"})
public class MainContext {
}

@Configuration是组件扫描的候选项,在我的电脑上测试通过的测试用例如下:

package scan.controllers;
@Controller
public class ExampleController {
}

package scan;
public interface RMIService {
}

package scan;
@Configuration
public class RmiContext {
    @Bean
    public RmiProxyFactoryBean service() {
        RmiProxyFactoryBean rmiProxy = new RmiProxyFactoryBean();
        rmiProxy.setServiceUrl("rmi://127.0.1.1:1099/Service");
        rmiProxy.setServiceInterface(RMIService.class);
        rmiProxy.setLookupStubOnStartup(false);
        return rmiProxy;
    }
}

package scan;
@Configuration
//MainContext will auto scan RmiContext in package scan and all controllers in package scan.controllers
@ComponentScan(basePackages = {"scan", "scan.controllers"})
public class MainContext {
}

package scan;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes={MainContext.class})
public class TestContext {

    @Autowired private RMIService rmi;
    @Autowired private ExampleController controller;

    @Test
    public void test() {
        //both controller and rmi service are autowired as expected
        assertNotNull(controller);
        assertNotNull(rmi);
    }
}

就像我在问题中提到的那样,当使用@ComponentScan扫描其他使用@Component注释的bean时,通过RMI(即服务)传递的bean无法被识别(即找不到类型为“Service”的bean),会抛出异常。 - TheKojuEffect

1

May be you could try using the base packages of your classes (RMI, Controller):


@ComponentScan(basePackages = {"your controller package", "your rmi package"})

如果RMI类包与控制器不同,则它们将无法由Spring实例化。

当您创建控制器时,也不需要使用 @Configuration 注解。只需使用 @Controller 即可。 - Ayub Malik
我如何知道“RMI包”,因为这些RMI服务是远程调用的,所以没有这些包? - TheKojuEffect
@AyubMalik 我想你误解了。@Configuration 是用于定义基于 Java 的 Spring 配置的注释。也许你认为它是 @Component。这就是我想要做的事情,像用 @Component@Controller 注释组件类,并使用 @ComponentScan 而不是手动使用 @Bean 为每个组件定义。但问题是当我这样做时,Rmi services 组件 bean 不再被创建或识别。 - TheKojuEffect

0

如果我理解正确的话,您使用了"@ComponentScan(basePackageClasses",但它没有检测到并注册您的Spring Bean?

我几分钟前也遇到了同样的问题。我没有放弃,尝试了所有有趣的猜测。其中一个猜测解决了问题。

我不得不在XML中添加一个组件扫描条目。我只是放了一个虚拟包,像下面这样:

 component-scan base-package="dummy.filler.to.enable.component.scan"

看起来XML中的component-scan启用了@ComponentScan。

[晚期编辑:我注意到我的Spring XML模式是Spring 2.5。无论如何,我不知道这是否重要。最好的问候。]


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接