Spring AnnotationConfigApplicationContext源码笔记 一

AnnotationConfigApplicationContext类继承关系图

AnnotationConfigApplicationContext的带参构造器作为入口。

AnnotationConfigApplicationContext
...
// 参数basePackages为自动扫描的包名
public AnnotationConfigApplicationContext(String... basePackages) {
    this();
    scan(basePackages);
    refresh();
}
...
public AnnotationConfigApplicationContext() {
    // 默认调用父类无参构造器,可从继承关系图中查看其父类。
    this.reader = new AnnotatedBeanDefinitionReader(this);
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}

间接父类AbstractApplicationContext的无参构造器。

AbstractApplicationContext
...
public AbstractApplicationContext() {
    this.resourcePatternResolver = getResourcePatternResolver();
}
...
protected ResourcePatternResolver getResourcePatternResolver() {
    return new PathMatchingResourcePatternResolver(this);
}

PathMatchingResourcePatternResolver构造器

PathMatchingResourcePatternResolver
...
public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader) {
    Assert.notNull(resourceLoader, "ResourceLoader must not be null");
    // 由于AnnotationConfigApplicationContext的父类AbstractApplicationContext继承DefaultResourceLoader,拥有ResourceLoader 的特性,此时的resourceLoader就是AnnotationConfigApplicationContext自己。
    this.resourceLoader = resourceLoader;
}

直接父类GenericApplicationContext的无参构造器。

GenericApplicationContext
...
public GenericApplicationContext() {
    // 这里直接创建ioc容器,使用的容器是DefaultListableBeanFactory。
    this.beanFactory = new DefaultListableBeanFactory();
}

在AnnotationConfigApplicationContext父类构造器的调用完成之后,回到自己的无参构造器中。

AnnotationConfigApplicationContext
...
public AnnotationConfigApplicationContext() {
    // AnnotationConfigApplicationContext的父类GenericApplicationContext实现了接口BeanDefinitionRegistry,此时this就是AnnotationConfigApplicationContext。
    this.reader = new AnnotatedBeanDefinitionReader(this);
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}

进入AnnotatedBeanDefinitionReader的带参构造器。

AnnotatedBeanDefinitionReader
...
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
    this(registry, getOrCreateEnvironment(registry));
}
...
private static Environment getOrCreateEnvironment(BeanDefinitionRegistry registry) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    if (registry instanceof EnvironmentCapable) {
        //调用AbstractApplicationContext的getEnvironment方法创建StandardEnvironment
        return ((EnvironmentCapable) registry).getEnvironment();
    }
    return new StandardEnvironment();
}
...
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    Assert.notNull(environment, "Environment must not be null");
    this.registry = registry;
    // 创建ConditionEvaluator
    this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
    // 向容器中注册注解处理器以用来处理配置的各种注解
    AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}

先看ConditionEvaluator构造器

ConditionEvaluator
...
public ConditionEvaluator(BeanDefinitionRegistry registry, Environment environment, ResourceLoader resourceLoader) {
    this.context = new ConditionContextImpl(registry, environment, resourceLoader);
}
...
public ConditionContextImpl(BeanDefinitionRegistry registry, Environment environment, ResourceLoader resourceLoader) {
    this.registry = registry;
    // 推断出beanFactory
    this.beanFactory = deduceBeanFactory(registry);
    // 推断出environment
    this.environment = (environment != null ? environment : deduceEnvironment(registry));
    // 推断出resourceLoader,resourceLoader还是AnnotationConfigApplicationContext自身
    this.resourceLoader = (resourceLoader != null ? resourceLoader : deduceResourceLoader(registry));
}
...
private Environment deduceEnvironment(BeanDefinitionRegistry source) {
    if (source instanceof EnvironmentCapable) {
        return ((EnvironmentCapable) source).getEnvironment();
    }
    return null;
}
...
private ResourceLoader deduceResourceLoader(BeanDefinitionRegistry source) {
    if (source instanceof ResourceLoader) {
        return (ResourceLoader) source;
    }
    return null;
}

再回到AnnotatedBeanDefinitionReader的构造器中看AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)

AnnotationConfigUtils
...
public static void registerAnnotationConfigProcessors(BeanDefinitionRegistry registry) {
    registerAnnotationConfigProcessors(registry, null);
}
...
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, Object source) {
    // 获取创建的默认容器
    DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
    if (beanFactory != null) {
        // 设置AnnotationAwareOrderComparator,以用来支持@Order,@Priority和实现了org.springframework.core.Ordered接口的类。
        if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
            beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
        }
        if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
            beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        }
    }

    Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<BeanDefinitionHolder>(4);
    // 向容器中注册bean
    // beanName:org.springframework.context.annotation.internalConfigurationAnnotationProcessor
    // beanClass:org.springframework.context.annotation.ConfigurationClassPostProcessor
    // 实现的接口是BeanDefinitionRegistryPostProcessor,接口父类BeanFactoryPostProcessor。
    if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // 向容器中注册AutowiredAnnotationBeanPostProcessor,bean名称为org.springframework.context.annotation.internalAutowiredAnnotationProcessor
    if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // 向容器中注册RequiredAnnotationBeanPostProcessor,bean名称为org.springframework.context.annotation.internalRequiredAnnotationProcessor
    if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
    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));
    }

    // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
    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()));
        }
        catch (ClassNotFoundException ex) {throw new IllegalStateException("Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
        }
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // 向容器中注册EventListenerMethodProcessor,bean名称为org.springframework.context.event.internalEventListenerProcessor
    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));
    }
    // 向容器中注册DefaultEventListenerFactory,bean名称为org.springframework.context.event.internalEventListenerFactory
    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;
}

完成AnnotatedBeanDefinitionReader的创建后,回到AnnotationConfigApplicationContext的无参构造器中,开始创建ClassPathBeanDefinitionScanner,进入构造器。

ClassPathBeanDefinitionScanner
...
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
    this(registry, true);
}
...
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
    // Environment为AbstractApplicationContext已经创建过的StandardEnvironment
    this(registry, useDefaultFilters, getOrCreateEnvironment(registry));
}
...
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment) {
    this(registry, useDefaultFilters, environment, (registry instanceof ResourceLoader ? (ResourceLoader) registry : null));
}
...
public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters, Environment environment, ResourceLoader resourceLoader) {
    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
    this.registry = registry;
    // 以下方法在父类ClassPathScanningCandidateComponentProvider中
    if (useDefaultFilters) {
        // 注册默认过滤器
        registerDefaultFilters();
    }
    setEnvironment(environment);
    setResourceLoader(resourceLoader);
}

进入ClassPathScanningCandidateComponentProvider

ClassPathScanningCandidateComponentProvider
...
protected void registerDefaultFilters() {
    // Component,以用来处理@Component注解
    this.includeFilters.add(new AnnotationTypeFilter(Component.class));
    ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
    try {
        // 如果没有引入javax.annotation.ManagedBean,会抛出异常被catch,不会被加入到内置过滤器中
        this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
        logger.debug("JSR-250 'javax.annotation.ManagedBean' found and supported for component scanning");
    }
    catch (ClassNotFoundException ex) {
        // JSR-250 1.1 API (as included in Java EE 6) not available - simply skip.
    }
    try {
        // 如果没有引入javax.inject.Named,会抛出异常被catch,不会被加入到内置过滤器中
        this.includeFilters.add(new AnnotationTypeFilter(((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));
        logger.debug("JSR-330 'javax.inject.Named' annotation found and supported for component scanning");
    }
    catch (ClassNotFoundException ex) {
        // JSR-330 API not available - simply skip.
    }
}
...
public void setEnvironment(Environment environment) {
    Assert.notNull(environment, "Environment must not be null");
    this.environment = environment;
    this.conditionEvaluator = null;
}
...
public void setResourceLoader(ResourceLoader resourceLoader) {
    // 资源解析器
    this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
    // 初始化简单的元数据读取器和缓存元数据读取器
    this.metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);
}

至此,AnnotationConfigApplicationContext的空参构造器执行完毕,接下来回到带参构造器中看scan方法。

AnnotationConfigApplicationContext
...
public void scan(String... basePackages) {
    Assert.notEmpty(basePackages, "At least one base package must be specified");
    // ClassPathBeanDefinitionScanner
    this.scanner.scan(basePackages);
}

ClassPathBeanDefinitionScanner的scan方法

ClassPathBeanDefinitionScanner
...
public int scan(String... basePackages) {
    int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
    // 开始扫描包
    doScan(basePackages);

    // Register annotation config processors, if necessary.
    if (this.includeAnnotationConfig) {
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }

    return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}
...
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
    Assert.notEmpty(basePackages, "At least one base package must be specified");
    Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
    for (String basePackage : basePackages) {
        // 扫描包获取需要注入到容器的组件 父类ClassPathScanningCandidateComponentProvider的方法
        Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
        ... 限于篇幅 暂时省略
}

进入ClassPathScanningCandidateComponentProvider中的findCandidateComponents方法

ClassPathScanningCandidateComponentProvider
...
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
        Set<BeanDefinition> candidates = new LinkedHashSet<BeanDefinition>();
        try {
            // 解析路径 CLASSPATH_ALL_URL_PREFIX为 classpath*: ,resourcePattern为 **/*.class
            String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + '/' + this.resourcePattern;
            // 资源解析器开始工作 这里的resourcePatternResolver还是AnnotationConfigApplicationContext自己,调用父类GenericApplicationContext的getResources方法
            Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);
            ... 限于篇幅 暂时省略

GenericApplicationContext中的getResources方法

GenericApplicationContext
...
@Override
public Resource[] getResources(String locationPattern) throws IOException {
    // resourceLoader为null
    if (this.resourceLoader instanceof ResourcePatternResolver) {
        return ((ResourcePatternResolver) this.resourceLoader).getResources(locationPattern);
    }
    // 再去父类AbstractApplicationContext中getResources方法
    return super.getResources(locationPattern);
}

AbstractApplicationContext中的getResources方法

AbstractApplicationContext
...
@Override
public Resource[] getResources(String locationPattern) throws IOException {
    // 在AbstractApplicationContext创建对象时声明过,resourcePatternResolver为PathMatchingResourcePatternResolver,
    return this.resourcePatternResolver.getResources(locationPattern);
}

PathMatchingResourcePatternResolver

PathMatchingResourcePatternResolver
...
@Override
public Resource[] getResources(String locationPattern) throws IOException {
    Assert.notNull(locationPattern, "Location pattern must not be null");
    // true
    if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {
        // true
        // a class path resource (multiple resources for same name possible)
        if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {
            // a class path resource pattern
            return findPathMatchingResources(locationPattern);
        }
        else {
            // all class path resources with the given name
            return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));
        }
    }
    else {
        // Generally only look for a pattern after a prefix here,
        // and on Tomcat only after the "*/" separator for its "war:" protocol.
        int prefixEnd = (locationPattern.startsWith("war:") ? locationPattern.indexOf("*/") + 1 :
                locationPattern.indexOf(":") + 1);
        if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) {
            // a file pattern
            return findPathMatchingResources(locationPattern);
        }
        else {
            // a single resource with the given name
            return new Resource[] {getResourceLoader().getResource(locationPattern)};
        }
    }
}
...
protected Resource[] findPathMatchingResources(String locationPattern) throws IOException {
    // 确定根路径
    String rootDirPath = determineRootDir(locationPattern);
    // 截取掉后缀
    String subPattern = locationPattern.substring(rootDirPath.length());
    // 再次根据路径获取资源 这次是处理过的路径
    Resource[] rootDirResources = getResources(rootDirPath);
    // 暂时省略
    ......
}
...
protected String determineRootDir(String location) {
    int prefixEnd = location.indexOf(":") + 1;
    int rootDirEnd = location.length();
    while (rootDirEnd > prefixEnd && getPathMatcher().isPattern(location.substring(prefixEnd, rootDirEnd))) {
        rootDirEnd = location.lastIndexOf('/', rootDirEnd - 2) + 1;
    }
    if (rootDirEnd == 0) {
        rootDirEnd = prefixEnd;
    }
    return location.substring(0, rootDirEnd);
}
...
@Override
public Resource[] getResources(String locationPattern) throws IOException {
    Assert.notNull(locationPattern, "Location pattern must not be null");
    if (locationPattern.startsWith(CLASSPATH_ALL_URL_PREFIX)) {
        // a class path resource (multiple resources for same name possible)
        if (getPathMatcher().isPattern(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()))) {
            // a class path resource pattern
            return findPathMatchingResources(locationPattern);
        }
        else {
            // all class path resources with the given name
            // 找到路径下所有class
            return findAllClassPathResources(locationPattern.substring(CLASSPATH_ALL_URL_PREFIX.length()));
        }
    }
    else {
        // Generally only look for a pattern after a prefix here,
        // and on Tomcat only after the "*/" separator for its "war:" protocol.
        int prefixEnd = (locationPattern.startsWith("war:") ? locationPattern.indexOf("*/") + 1 :
                locationPattern.indexOf(":") + 1);
        if (getPathMatcher().isPattern(locationPattern.substring(prefixEnd))) {
            // a file pattern
            return findPathMatchingResources(locationPattern);
        }
        else {
            // a single resource with the given name
            return new Resource[] {getResourceLoader().getResource(locationPattern)};
        }
    }
}
...
protected Resource[] findAllClassPathResources(String location) throws IOException {
    String path = location;
    if (path.startsWith("/")) {
        path = path.substring(1);
    }
    Set<Resource> result = doFindAllClassPathResources(path);
    if (logger.isDebugEnabled()) {
        logger.debug("Resolved classpath location [" + location + "] to resources " + result);
    }
    return result.toArray(new Resource[result.size()]);
}
...
protected Set<Resource> doFindAllClassPathResources(String path) throws IOException {
    Set<Resource> result = new LinkedHashSet<Resource>(16);
    // 类加载器 找到需要被扫描的包对应在在磁盘上的绝对路径
    ClassLoader cl = getClassLoader();
    Enumeration<URL> resourceUrls = (cl != null ? cl.getResources(path) : ClassLoader.getSystemResources(path));
    while (resourceUrls.hasMoreElements()) {
        URL url = resourceUrls.nextElement();
        // UrlResource
        result.add(convertClassLoaderURL(url));
    }
    if ("".equals(path)) {
        // The above result is likely to be incomplete, i.e. only containing file system references.
        // We need to have pointers to each of the jar files on the classpath as well...
        addAllClassLoaderJarRoots(cl, result);
    }
    return result;
}
...
protected Resource convertClassLoaderURL(URL url) {
    return new UrlResource(url);
}

getResources方法看完后继续看findPathMatchingResources方法

PathMatchingResourcePatternResolver
...
protected Resource[] findPathMatchingResources(String locationPattern) throws IOException {
    String rootDirPath = determineRootDir(locationPattern);
    String subPattern = locationPattern.substring(rootDirPath.length());
    // 这里继续
    Resource[] rootDirResources = getResources(rootDirPath);
    Set<Resource> result = new LinkedHashSet<Resource>(16);
    for (Resource rootDirResource : rootDirResources) {
        rootDirResource = resolveRootDirResource(rootDirResource);
        URL rootDirURL = rootDirResource.getURL();
        if (equinoxResolveMethod != null) {
            if (rootDirURL.getProtocol().startsWith("bundle")) {
                rootDirURL = (URL) ReflectionUtils.invokeMethod(equinoxResolveMethod, null, rootDirURL);
                rootDirResource = new UrlResource(rootDirURL);
            }
        }
        if (rootDirURL.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
            result.addAll(VfsResourceMatchingDelegate.findMatchingResources(rootDirURL, subPattern, getPathMatcher()));
        }
        else if (ResourceUtils.isJarURL(rootDirURL) || isJarResource(rootDirResource)) {
            result.addAll(doFindPathMatchingJarResources(rootDirResource, rootDirURL, subPattern));
        }
        // doFindPathMatchingFileResources载入Resource。从磁盘目录检索其下所有的class,返回FileSystemResource。
        else {
            result.addAll(doFindPathMatchingFileResources(rootDirResource, subPattern));
        }
    }
    if (logger.isDebugEnabled()) {
        logger.debug("Resolved location pattern [" + locationPattern + "] to resources " + result);
    }
    return result.toArray(new Resource[result.size()]);
}

看完getResources方法,再回到ClassPathScanningCandidateComponentProvider继续看findCandidateComponents方法

ClassPathScanningCandidateComponentProvider
...
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);
            // 这里继续 上面已经将磁盘路径下的所有class文件载入为FileSystemResource
            boolean traceEnabled = logger.isTraceEnabled();
            boolean debugEnabled = logger.isDebugEnabled();
            for (Resource resource : resources) {
                if (traceEnabled) {
                    logger.trace("Scanning " + resource);
                }
                if (resource.isReadable()) {
                    try {
                        // 获取资源元数据读取器,metadataReaderFactory是上面初始化过的CachingMetadataReaderFactory
                        MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
                        ... 限于篇幅 暂时省略
    }

CachingMetadataReaderFactory的getMetadataReader方法

CachingMetadataReaderFactory
...
@Override
public MetadataReader getMetadataReader(Resource resource) throws IOException {
    if (getCacheLimit() <= 0) {
        return super.getMetadataReader(resource);
    }
    synchronized (this.metadataReaderCache) {
        MetadataReader metadataReader = this.metadataReaderCache.get(resource);
        if (metadataReader == null) {
            // 如果缓存中没有,从父类SimpleMetadataReaderFactory获取资源的元数据读取器,并缓存起来。
            metadataReader = super.getMetadataReader(resource);
            this.metadataReaderCache.put(resource, metadataReader);
        }
        return metadataReader;
    }
}

SimpleMetadataReaderFactory的getMetadataReader方法

SimpleMetadataReaderFactory
...
@Override
public MetadataReader getMetadataReader(Resource resource) throws IOException {
    return new SimpleMetadataReader(resource, this.resourceLoader.getClassLoader());
}

SimpleMetadataReader的构造器

SimpleMetadataReader
...
SimpleMetadataReader(Resource resource, ClassLoader classLoader) throws IOException {
    InputStream is = new BufferedInputStream(resource.getInputStream());
    ClassReader classReader;
    try {
        classReader = new ClassReader(is);
    }
    catch (IllegalArgumentException ex) {
        throw new NestedIOException("ASM ClassReader failed to parse class file - " + "probably due to a new Java class file version that isn't supported yet: " + resource, ex);
    }
    finally {
        is.close();
    }
    // 这个类比较关键 后续根据类上的注解判断类是否应当加入到容器时,就是从这里取得类上的注解元数据
    AnnotationMetadataReadingVisitor visitor = new AnnotationMetadataReadingVisitor(classLoader);

    // ASM字节码技术处理 访问者模式 构造数据
    classReader.accept(visitor, ClassReader.SKIP_DEBUG);
    this.annotationMetadata = visitor;
    // (since AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor)
    this.classMetadata = visitor;
    this.resource = resource;
}

回到ClassPathScanningCandidateComponentProvider,在获取到元数据读取器之后,继续往下看。

ClassPathScanningCandidateComponentProvider
...
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 (Resource resource : resources) {
                if (traceEnabled) {
                    logger.trace("Scanning " + resource);
                }
                if (resource.isReadable()) {
                    try {
                        MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
                        // 这里继续 根据资源元数据读取器判断是否是需要的组件
                        if (isCandidateComponent(metadataReader)) {
                        ... 限于篇幅 暂时省略

isCandidateComponent方法

protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
    // excludeFilters中没有添加过任何过滤器
    for (TypeFilter tf : this.excludeFilters) {
        if (tf.match(metadataReader, this.metadataReaderFactory)) {
            return false;
        }
    }
    // ClassPathScanningCandidateComponentProvider在创建对象的时候往includeFilters中添加了一个AnnotationTypeFilter类型的默认过滤器,以用来处理@component注解
    for (TypeFilter tf : this.includeFilters) {
        // 调用AnnotationTypeFilter父类AbstractTypeHierarchyTraversingFilter的match方法
        if (tf.match(metadataReader, this.metadataReaderFactory)) {
            return isConditionMatch(metadataReader);
        }
    }
    return false;
}
...
private boolean isConditionMatch(MetadataReader metadataReader) {
    if (this.conditionEvaluator == null) {
        this.conditionEvaluator = new ConditionEvaluator(getRegistry(), getEnvironment(), getResourceLoader());
    }
    return !this.conditionEvaluator.shouldSkip(metadataReader.getAnnotationMetadata());
}

进入AbstractTypeHierarchyTraversingFilter的match方法

AbstractTypeHierarchyTraversingFilter
...
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {

    // This method optimizes avoiding unnecessary creation of ClassReaders
    // as well as visiting over those readers.
    // 匹配注解 子类AnnotationTypeFilter重写的方法
    if (matchSelf(metadataReader)) {
        return true;
    }
    ClassMetadata metadata = metadataReader.getClassMetadata();
    if (matchClassName(metadata.getClassName())) {
        return true;
    }

    if (this.considerInherited) {
        if (metadata.hasSuperClass()) {
            // Optimization to avoid creating ClassReader for super class.
            Boolean superClassMatch = matchSuperClass(metadata.getSuperClassName());
            if (superClassMatch != null) {
                if (superClassMatch.booleanValue()) {
                    return true;
                }
            }
            else {
                // Need to read super class to determine a match...
                try {
                    if (match(metadata.getSuperClassName(), metadataReaderFactory)) {
                        return true;
                    }
                }
                catch (IOException ex) {
                    logger.debug("Could not read super class [" + metadata.getSuperClassName() + "] of type-filtered class [" + metadata.getClassName() + "]");
                }
            }
        }
    }

    if (this.considerInterfaces) {
        for (String ifc : metadata.getInterfaceNames()) {
            // Optimization to avoid creating ClassReader for super class
            Boolean interfaceMatch = matchInterface(ifc);
            if (interfaceMatch != null) {
                if (interfaceMatch.booleanValue()) {
                    return true;
                }
            }
            else {
                // Need to read interface to determine a match...
                try {
                    if (match(ifc, metadataReaderFactory)) {
                        return true;
                    }
                }
                catch (IOException ex) {
                    logger.debug("Could not read interface [" + ifc + "] for type-filtered class [" + metadata.getClassName() + "]");
                }
            }
        }
    }

    return false;
}

AnnotationTypeFilter

AnnotationTypeFilter
...
@Override
protected boolean matchSelf(MetadataReader metadataReader) {
    // 获取当前资源的注解元数据
    AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
    return metadata.hasAnnotation(this.annotationType.getName()) ||
            (this.considerMetaAnnotations && metadata.hasMetaAnnotation(this.annotationType.getName()));
}

AnnotationMetadataReadingVisitor

AnnotationMetadataReadingVisitor
...
@Override
public boolean hasAnnotation(String annotationName) {
    // 判断是否包含@component annotationSet开始时为空 
    return this.annotationSet.contains(annotationName);
}
...
@Override
public boolean hasMetaAnnotation(String metaAnnotationType) {
    // 获取元数据中所有注解。例如@controller、@service这一类的注解,这些注解上有标注@component 。在metaAnnotationMap中,key是controller或者service,value是component 。这里就是为什么@controller、@service会被扫描的原因
    Collection<Set<String>> allMetaTypes = this.metaAnnotationMap.values();
    for (Set<String> metaTypes : allMetaTypes) {
        if (metaTypes.contains(metaAnnotationType)) {
            return true;
        }
    }
    return false;
}

看完isCandidateComponent之后,再回到ClassPathScanningCandidateComponentProvider往下。

ClassPathScanningCandidateComponentProvider
...
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 (Resource resource : resources) {
                if (traceEnabled) {
                    logger.trace("Scanning " + resource);
                }
                if (resource.isReadable()) {
                    try {
                        MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
                        if (isCandidateComponent(metadataReader)) {
                            // 这里继续 构造基础的扫描BeanDefinition
                            ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
                            sbd.setResource(resource);
                            sbd.setSource(resource);
                            // 基础检查
                            if (isCandidateComponent(sbd)) {
                                if (debugEnabled) {
                                    logger.debug("Identified candidate component class: " + resource);
                                }
                                // 添加到集合中
                                candidates.add(sbd);
                            }
                            else {
                                if (debugEnabled) {
                                    logger.debug("Ignored because not a concrete top-level class: " + resource);
                                }
                            }
                        }
                        else {
                            if (traceEnabled) {
                                logger.trace("Ignored because not matching any filter: " + resource);
                            }
                        }
                    }
                    catch (Throwable ex) {
                        throw new BeanDefinitionStoreException("Failed to read candidate component class: " + resource, ex);
                    }
                }
                else {
                    if (traceEnabled) {
                        logger.trace("Ignored because not readable: " + resource);
                    }
                }
            }
        }
        catch (IOException ex) {
            throw new BeanDefinitionStoreException("I/O failure during classpath scanning", ex);
        }
        // 返回包下所有应当被加入到容器中的BeanDefinition
        return candidates;
    }

回到最初的ClassPathBeanDefinitionScanner的doScan方法中

ClassPathBeanDefinitionScanner
...
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
    Assert.notEmpty(basePackages, "At least one base package must be specified");
    Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
    for (String basePackage : basePackages) {
        Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
        // 这里继续 上面findCandidateComponents已经找到包下所有需要加入到容器中的BeanDefinition
        for (BeanDefinition candidate : candidates) {
            // 解析元数据以获取scope
            ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
            candidate.setScope(scopeMetadata.getScopeName());
            // 获取beanName,这里从注解元数据中,根据配置返回bean名称(是否有别名)。
            String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
            // true
            if (candidate instanceof AbstractBeanDefinition) {
                // 当前bean设置默认属性
                postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
            }
            // true
            if (candidate instanceof AnnotatedBeanDefinition) {
                // util中处理bean上的普通注解
                AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
            }
            if (checkCandidate(beanName, candidate)) {
                // 构造BeanDefinitionHolder 
                BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
                // util中获取bean元注解中的配置,以决定是否需要代理
                definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
                beanDefinitions.add(definitionHolder);
                // 注入bean到容器中
                registerBeanDefinition(definitionHolder, this.registry);
            }
        }
    }
    return beanDefinitions;
}
...
protected void postProcessBeanDefinition(AbstractBeanDefinition beanDefinition, String beanName) {
    // 其中lazyInit默认false
    beanDefinition.applyDefaults(this.beanDefinitionDefaults);
    if (this.autowireCandidatePatterns != null) {
        beanDefinition.setAutowireCandidate(PatternMatchUtils.simpleMatch(this.autowireCandidatePatterns, beanName));
    }
}

AnnotationBeanNameGenerator,获取bean名称

AnnotationBeanNameGenerator
...
@Override
public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
    if (definition instanceof AnnotatedBeanDefinition) {
        // 根据注解推断出beanName
        String beanName = determineBeanNameFromAnnotation((AnnotatedBeanDefinition) definition);
        if (StringUtils.hasText(beanName)) {
            // Explicit bean name found.
            return beanName;
        }
    }
    // Fallback: generate a unique default bean name.
    return buildDefaultBeanName(definition, registry);
}
...
protected String determineBeanNameFromAnnotation(AnnotatedBeanDefinition annotatedDef) {
    AnnotationMetadata amd = annotatedDef.getMetadata();
    Set<String> types = amd.getAnnotationTypes();
    String beanName = null;
    for (String type : types) {
        AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(amd, type);
        // 从注解元数据中,取名称
        if (isStereotypeWithNameValue(type, amd.getMetaAnnotationTypes(type), attributes)) {
            Object value = attributes.get("value");
            if (value instanceof String) {
                String strVal = (String) value;
                if (StringUtils.hasLength(strVal)) {
                    if (beanName != null && !strVal.equals(beanName)) {
                        throw new IllegalStateException("Stereotype annotations suggest inconsistent " +
                                "component names: '" + beanName + "' versus '" + strVal + "'");
                    }
                    beanName = strVal;
                }
            }
        }
    }
    return beanName;
}
...
protected boolean isStereotypeWithNameValue(String annotationType,
        Set<String> metaAnnotationTypes, Map<String, Object> attributes) {

    boolean isStereotype = annotationType.equals(COMPONENT_ANNOTATION_CLASSNAME) ||
            (metaAnnotationTypes != null && metaAnnotationTypes.contains(COMPONENT_ANNOTATION_CLASSNAME)) ||
            annotationType.equals("javax.annotation.ManagedBean") ||
            annotationType.equals("javax.inject.Named");

    return (isStereotype && attributes != null && attributes.containsKey("value"));
}

AnnotationConfigUtils,处理普通注解、创建代理bean

AnnotationConfigUtils
...
public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
    processCommonDefinitionAnnotations(abd, abd.getMetadata());
}
// 处理要加入到容器中的类上标注的各种注解
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
    if (metadata.isAnnotated(Lazy.class.getName())) {
        abd.setLazyInit(attributesFor(metadata, Lazy.class).getBoolean("value"));
    }
    else if (abd.getMetadata() != metadata && abd.getMetadata().isAnnotated(Lazy.class.getName())) {
        abd.setLazyInit(attributesFor(abd.getMetadata(), Lazy.class).getBoolean("value"));
    }

    if (metadata.isAnnotated(Primary.class.getName())) {
        abd.setPrimary(true);
    }
    if (metadata.isAnnotated(DependsOn.class.getName())) {
        abd.setDependsOn(attributesFor(metadata, DependsOn.class).getStringArray("value"));
    }

    if (abd instanceof AbstractBeanDefinition) {
        AbstractBeanDefinition absBd = (AbstractBeanDefinition) abd;
        if (metadata.isAnnotated(Role.class.getName())) {
            absBd.setRole(attributesFor(metadata, Role.class).getNumber("value").intValue());
        }
        if (metadata.isAnnotated(Description.class.getName())) {
            absBd.setDescription(attributesFor(metadata, Description.class).getString("value"));
        }
    }
}

// 创建代理bean
static BeanDefinitionHolder applyScopedProxyMode(ScopeMetadata metadata, BeanDefinitionHolder definition, BeanDefinitionRegistry registry) {

    ScopedProxyMode scopedProxyMode = metadata.getScopedProxyMode();
    if (scopedProxyMode.equals(ScopedProxyMode.NO)) {
        return definition;
    }
    boolean proxyTargetClass = scopedProxyMode.equals(ScopedProxyMode.TARGET_CLASS);
    return ScopedProxyCreator.createScopedProxy(definition, registry, proxyTargetClass);
}

最后回到ClassPathBeanDefinitionScanner的scan方法中

ClassPathBeanDefinitionScanner
...
public int scan(String... basePackages) {
    int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
    doScan(basePackages);

    // Register annotation config processors, if necessary.
    // /true
    if (this.includeAnnotationConfig) {
        // util中往容器中注册注解配置处理器。在AnnotatedBeanDefinitionReader的构造器中已经执行过。
        AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
    }

    return (this.registry.getBeanDefinitionCount() - beanCountAtScanStart);
}

至此,所有的需要往容器中直接注入的bean都已经注入到容器中,但不包括在配置类(@Configuration修饰的类)中声明的bean,不包括使用@import导入的bean。这些形式的bean都要等到处理它们依附的bean时才会处理它们。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,219评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,363评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,933评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,020评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,400评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,640评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,896评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,597评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,327评论 1 244
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,581评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,072评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,399评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,054评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,849评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,672评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,585评论 2 270

推荐阅读更多精彩内容