上一篇介绍spring 自定义扫描标签解析过程,中间有个重要的知识点我们单独取出来分析,就是注解扫描器的创建
1、ComponentScanBeanDefinitionParser implements BeanDefinitionParser 这里开始创建
@Override @Nullable public BeanDefinition parse(Element element, ParserContext parserContext) { //获取basePackage属性 String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE); basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage); //可以用逗号分开 String[] basePackages = StringUtils.tokenizeToStringArray(basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS); //创建注解扫描器,今天从这里开始,点击进入 ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element); //扫描并把扫描的类封装成beanDefinition对象 核心方法,重要程度 5 SetbeanDefinitions = scanner.doScan(basePackages); registerComponents(parserContext.getReaderContext(), beanDefinitions, element); return null; }
protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) { //使用默认的过滤器 boolean useDefaultFilters = true; //@Service @Component 默认filter if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) { useDefaultFilters = Boolean.valueOf(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)); } //从这里开始 创建注解的扫描器 ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters); scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults()); scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns()); //删除部分代码 try { parseBeanNameGenerator(element, scanner); } try { parseScope(element, scanner); } parseTypeFilters(element, scanner, parserContext); return scanner; }
protected ClassPathBeanDefinitionScanner createScanner(XmlReaderContext readerContext, boolean useDefaultFilters) { //点击进入 return new ClassPathBeanDefinitionScanner(readerContext.getRegistry(), useDefaultFilters, readerContext.getEnvironment(), readerContext.getResourceLoader()); }
2、ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment, @Nullable ResourceLoader resourceLoader) { Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); this.registry = registry; //使用默认的过滤器 if (useDefaultFilters) { //默认的 注解@Service @Component 点击进入 registerDefaultFilters(); } setEnvironment(environment); setResourceLoader(resourceLoader); }
3、 ClassPathScanningCandidateComponentProvider implements EnvironmentCapable, ResourceLoaderAware
protected void registerDefaultFilters() { //过滤器中添加需要扫描的注解类型,把componet 注解包装 同时也处理了@server注解,一样它继承了compont注解 this.includeFilters.add(new AnnotationTypeFilter(Component.class)); ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader(); //删除不重要的 }
4、
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @org.springframework.stereotype.Component//继承了compont注解 public @interface Service { /** * The value may indicate a suggestion for a logical component name, * to be turned into a Spring bean in case of an autodetected component. * @return the suggested component name, if any (or empty String otherwise) */ @AliasFor(annotation = org.springframework.stereotype.Component.class) String value() default ""; }
5、到这里大家应该豁然开朗了吧,项目中常用的注解 @Component @Service 在这里开始进入我们视线。下篇我们介绍类里面的注解问题,大家可以先思考一下。敬请期待!