美文网首页
Spring AnnotationConfigApplicati

Spring AnnotationConfigApplicati

作者: 丶含光 | 来源:发表于2020-06-23 11:24 被阅读0次
    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时才会处理它们。

    相关文章

      网友评论

          本文标题:Spring AnnotationConfigApplicati

          本文链接:https://www.haomeiwen.com/subject/jicjxctx.html