组件如何在spring中扫描?是将所有对象初始化为singleton还是lazy初始化?

时间:2014-07-16 15:43:38

标签: java spring

我想知道spring servlet组件扫描是如何工作的?它扫描@服务,@组件等扫描。但我不清楚它是如何工作的?这背后有什么流程?

2 个答案:

答案 0 :(得分:0)

当您对开源项目中实现某些内容感到好奇时,最好的办法就是查看源代码。这是我如何去做的。这些步骤特定于我的特定配置(使用Eclipse编写的基于XML的Spring上下文),但一般理论适用于任何环境....

1)我从源代码中了解到,解析特定XML配置元素的类通常具有以“BeanDefinitionParser”结尾的名称。所以看看如何:

<context:component-scan base-package="com.yourproject" />

实现后,查找名为“Component * BeanDefinitionProcessor”的类。

2)在Eclipse中执行CTRL + SHIFT + T并搜索“Component * BeanDefinitionProcessor”我想出了ComponentScanBeanDefinitionParser。这听起来像是我正在寻找的......

3)在那个班级(第83-85行)中,有一大堆代码:

ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
registerComponents(parserContext.getReaderContext(), beanDefinitions, element);

因此,处理XML标记的类委托给ClassPathBeanDefinitionScanner。这是有道理的,因为Spring既支持XML配置,也支持基于Java的配置。在注释配置处理程序和XML配置处理程序中复制实际扫描逻辑是没有意义的。

4)查看ClassPathBeanDefinitionScanner的代码,我看不到任何看起来像是在类路径上寻找东西的东西。但是,它确实扩展了一个名为ClassPathScanningCandidateComponentProvider的类。

public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {  

5)查看ClassPathScanningCandidateComponentProvider,我可以看到循环遍历包中所有内容的for循环

public Set<BeanDefinition> findCandidateComponents(String basePackage) {
    Set<BeanDefinition> candidates = new LinkedHashSet<BeanDefinition>();

    try {
        String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
        resolveBasePackage(basePackage) + "/" + this.resourcePattern;

        Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);

        boolean traceEnabled = logger.isTraceEnabled();
        boolean debugEnabled = logger.isDebugEnabled();

        for (int i = 0; i < resources.length; i++) {

6)它正在使用ResourcePatternResolver在类路径中查找内容:

private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();

7)在PathMatchingResourcePatternResolver中,您可以看到实际搜索类路径的代码。

答案 1 :(得分:0)

How component scan in spring?

归结为使用类加载器和资源路径匹配进行一些体操,并使用ClassLoader.getResources(String name)方法返回包含表示类路径资源的URL的Enumeration。然后检查那些资源(Java类)以查看它们是否包含@Component注释(或它的特化),如果是,则被视为&#34;候选&#34;零件。可以进行其他过滤,但默认情况下,这些组件以编程方式定义为Spring bean。当启用注释配置时,组件的自动装配也会发生,因此我可以让Spring扫描所有Web控制器的类路径,然后自动注入服务或数据访问对象等依赖项。

执行此魔法的实际类是ClassPathScanningCandidateComponentProvider,默认情况下,它使用PathMatchingResourcePatternResolver使用ClassLoader.getResources()查找匹配的类路径资源。


根据Spring documentation默认情况下,Spring bean是单例。

  

与一般的Spring管理组件一样,默认为止   最常见的范围是&#39; singleton&#39;。但是,有时候还有其他的   范围是必要的。因此Spring 2.5引入了一个新的@Scope   注释也是如此。只需提供范围内的名称即可   注释

@Scope(StandardScopes.PROTOTYPE)
@Repository
public class MovieFinderImpl implements MovieFinder {
    // ...
}

不同的Bean范围是可用的here