我想知道spring servlet组件扫描是如何工作的?它扫描@服务,@组件等扫描。但我不清楚它是如何工作的?这背后有什么流程?
答案 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)
归结为使用类加载器和资源路径匹配进行一些体操,并使用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。