Spring源码分析之@Component注解自动扫描的处理


前言

在项目中使用Spring,我们都会使用它的自动扫描Bean的功能,今天就来分析一下自动扫描的原理。

简单使用

import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;

public class TestComponentScan {

  public static void main(String[] args) {
    DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(
        beanFactory, true);
    String packageName = ClassUtils.getPackageName(TestComponentScan.class);
    scanner.scan(packageName);
    UserService userService = (UserService) beanFactory.getBean("userService");
    userService.users();
  }

  @Component("userService")
  public static class UserService {

    public void users() {
      System.out.println("UserService.users()");
    }
  }
}

使用ClassPathBeanDefinitionScanner(扫描器)来扫描指定package下的Bean,默认会扫描包含@Component注解的Class。
根据扫描到的Class创建BeanDefinition,并注册到BeanFactory中。我们也可以自定义要扫描的条件,如扫描指定的接口的实现类。

import java.util.Map;
import java.util.Map.Entry;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.util.ClassUtils;

public class TestComponentScan2 {

  public static void main(String[] args) {
    DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
    ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(
        beanFactory, true);
    //扫描类型为IService的Class
    scanner.addIncludeFilter(new ClassTypeFilter(IService.class));
    String packageName = ClassUtils.getPackageName(TestComponentScan2.class);
    scanner.scan(packageName);
    Map iServiceMap = beanFactory.getBeansOfType(IService.class);
    for (Entry entry : iServiceMap.entrySet()) {
      System.out.println(entry);
    }
  }

  public static class ClassTypeFilter implements TypeFilter {

    private Class<?> targetType;

    public ClassTypeFilter(Class<?> targetType) {
      this.targetType = targetType;
    }

    @Override
    public boolean match(MetadataReader metadataReader,
        MetadataReaderFactory metadataReaderFactory) {
      try {
        //获取Class
        Class<?> aClass = ClassUtils
            .forName(metadataReader.getClassMetadata().getClassName(),
                ClassUtils.getDefaultClassLoader());
        return !metadataReader.getClassMetadata().isInterface() &&
            targetType.isAssignableFrom(aClass);
      } catch (ClassNotFoundException e) {
        e.printStackTrace();
      }
      return false;
    }
  }

  public interface IService {

  }

  public static class AddressService {

  }

  public static class UserService implements IService {

    public void users() {
      System.out.println("UserService.users()");
    }
  }
}

扫描接口IService的实现类,只有UserService,不包含AddressService。SpringDataJPA就是通过这种方式来扫描Repository接口的。

源码分析

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
			Environment environment, @Nullable ResourceLoader resourceLoader) {
		this.registry = registry;
                //注册默认类型过滤器,过滤@Component注解
		if (useDefaultFilters) {
			registerDefaultFilters();
		}
		setEnvironment(environment);
		setResourceLoader(resourceLoader);
	}

开始扫描

public int scan(String... basePackages) {
		int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
                //实际扫描
		doScan(basePackages);
		//注册一些处理注解相关的BeanPostProcessor
		if (this.includeAnnotationConfig) {
			AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
		}
		return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
	}

查看自动注册了哪些BeanPostProcessor

public static Set registerAnnotationConfigProcessors(
			BeanDefinitionRegistry registry, @Nullable Object source) {
                //获取DefaultListableBeanFactory,这个例子中registry的实际类型就是DefaultListableBeanFactory
                //如果我们是在ApplicationContext中调用此方法,registry的类型就是ApplicationContext的具体实现类
		DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
		if (beanFactory != null) {
			if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
				beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
			}
			if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
                                //处理@Value注解的属性注入
				beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
			}
		}

		Set beanDefs = new LinkedHashSet<>(8);

		if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
                        //处理@Configuration注解,@ComponentScan注解,@Bean注解等
			RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
                        //处理@Autowired注解的属性注入
			RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		////支持@PostConstruct(Bean初始化)和@PreDestroy(Bean销毁)
		if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
                        
			RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		//处理JPA相关注解
		if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition();
			try {
				def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
						AnnotationConfigUtils.class.getClassLoader()));
			}
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
		}
                //处理@EventListener注解相关
		if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
		}
                //也是事件监听相关,暂时不管
		if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
		}

		return beanDefs;
	}

真正扫描的过程

protected Set doScan(String... basePackages) {
		//保存扫描到的所有BeanDefinition
		Set beanDefinitions = new LinkedHashSet<>();
		for (String basePackage : basePackages) {
                        //扫描指定package下的所有class,根据类型过滤器过滤,根据Class创建BeanDefinition
			Set candidates = findCandidateComponents(basePackage);
			for (BeanDefinition candidate : candidates) {
                                //处理@Scope注解相关
				ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
				candidate.setScope(scopeMetadata.getScopeName());
				String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
				if (candidate instanceof AbstractBeanDefinition) {
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
				if (candidate instanceof AnnotatedBeanDefinition) {
                                        //处理@Primary注解,@Lazy注解(是否懒加载)等
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
				if (checkCandidate(beanName, candidate)) {
					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                                        //@Scope注解可以配置对当前Bean是否创建动态代理
					definitionHolder =
							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
					beanDefinitions.add(definitionHolder);
                                        //将BeanDefinition注册到BeanFactory中
					registerBeanDefinition(definitionHolder, this.registry);
				}
			}
		}
		return beanDefinitions;
	}

继续跟进去findCandidateComponents()方法

public Set findCandidateComponents(String basePackage) {
                //componentsIndex不知道是什么情况下使用,暂时不管
		if (this.componentsIndex != null && indexSupportsIncludeFilters()) {
			return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);
		}
		else {
                        //真正扫描Class
			return scanCandidateComponents(basePackage);
		}
	}

继续scanCandidateComponents()方法

private Set scanCandidateComponents(String basePackage) {
		Set candidates = new LinkedHashSet<>();
		try {
                        //使用PathMatchingResourcePatternResolver(支持通配符)从classpath下查找所有class文件
			String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
					resolveBasePackage(basePackage) + '/' + this.resourcePattern;
                        //实际的查找路径为classpath*:xx/**/*.class
			Resource[] resources = getResourcePatternResolver().getResources(packageSearchPath);
			for (Resource resource : resources) {
				if (resource.isReadable()) {
					try {
						MetadataReader metadataReader = getMetadataReaderFactory().getMetadataReader(resource);
                                                //根据类型过滤器判断,如我们自己定义的ClassTypeFilter,其实这里还会根据@Conditional注解来判断,但先不管
						if (isCandidateComponent(metadataReader)) {
                                                        //创建BeanDefinition
							ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
							sbd.setResource(resource);
							sbd.setSource(resource);
                                                        //当前Class必须是独立的(非内部类,或者是静态内部类)
							if (isCandidateComponent(sbd)) {
								candidates.add(sbd);
							}
						}
					}
				}
			}
		}
		return candidates;
	}

至此就扫描完了,总结起来就是查找到所有的class,根据类型过滤器来过滤,根据class创建BeanDefinition并注册到BeanFactory(实际上是BeanDefinitionRegistry类型)中。

Spring中的使用

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan
public class BeanConfig {
}

我们使用Spring或者SpringBoot的时候,都是通过@ComponentScan注解来开启扫描的,不需要手动创建ClassPathBeanDefinitionScanner对象且调用scan()方法。

总结

@Controller注解,@Service,@Repository,这三个注解都是被@Component注解所标记的,Spring也会扫描到。