• Spring源码之BeanFactory


    /*
     * Copyright 2002-2019 the original author or authors.
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      https://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package org.springframework.beans.factory;
    
    import org.springframework.beans.BeansException;
    import org.springframework.core.ResolvableType;
    import org.springframework.lang.Nullable;
    
    /**
     * The root interface for accessing a Spring bean container.
     * This is the basic client view of a bean container;
     * further interfaces such as {@link ListableBeanFactory} and
     * {@link org.springframework.beans.factory.config.ConfigurableBeanFactory}
     * are available for specific purposes.
     * 用于访问SpringBean容器的根接口
     * 这是bean容器的基本客户机视图
     * 扩展接口例如ListableBeanFactory和ConfigurableBeanFactory
     * 可用于特定目的的
     *
     * <p>This interface is implemented by objects that hold a number of bean definitions,
     * each uniquely identified by a String name. Depending on the bean definition,
     * the factory will return either an independent instance of a contained object
     * (the Prototype design pattern), or a single shared instance (a superior
     * alternative to the Singleton design pattern, in which the instance is a
     * singleton in the scope of the factory). Which type of instance will be returned
     * depends on the bean factory configuration: the API is the same. Since Spring
     * 2.0, further scopes are available depending on the concrete application
     * context (e.g. "request" and "session" scopes in a web environment).
     * 这个接口由包含许多bean定义的对象实现
     * 每个都由一个字符串名称唯一标识
     * 通过这个bean的定义,工厂将返回所包含对象的独立实例(原型设计模式)
     * 或单个共享实例(一个优于单例设计模式的选择,其中实例是工厂范围内的单例)
     * 返回哪种类型的实例取决于bean工厂配置
     * API是相同的
     * 自spring 2.0以来,可以根据具体的应用程序上下文使用更多的范围
     *
     * <p>The point of this approach is that the BeanFactory is a central registry
     * of application components, and centralizes configuration of application
     * components (no more do individual objects need to read properties files,
     * for example). See chapters 4 and 11 of "Expert One-on-One J2EE Design and
     * Development" for a discussion of the benefits of this approach.
     * 正中方法的要点是BeanFactory是应用程序组件的中心注册表 和 集中配置应用程序组件
     * (例如,单个对象不再需要读取属性文件)
     * 有关此方法的好处的讨论,请参阅"专家一对一J2EE设计和开发"的第四章和第11章
     *
     * <p>Note that it is generally better to rely on Dependency Injection
     * ("push" configuration) to configure application objects through setters
     * or constructors, rather than use any form of "pull" configuration like a
     * BeanFactory lookup. Spring's Dependency Injection functionality is
     * implemented using this BeanFactory interface and its subinterfaces.
     * 注意:通常依赖注入("push"配置)通过setter或构造函数配置应用程序更好
     * 而不是像BeanFactory查找那样使用任何形式的"pull"配置
     * Spring的依赖注入功能是使用这个BeanFactory接口及其子接口实现的
     *
     * <p>Normally a BeanFactory will load bean definitions stored in a configuration
     * source (such as an XML document), and use the {@code org.springframework.beans}
     * package to configure the beans. However, an implementation could simply return
     * Java objects it creates as necessary directly in Java code. There are no
     * constraints on how the definitions could be stored: LDAP, RDBMS, XML,
     * properties file, etc. Implementations are encouraged to support references
     * amongst beans (Dependency Injection).
     * 通常,BeanFactory将加载存储在配置源(如XML文档)中的bean定义,并使用@code包来配置bean,
     * 但是,实现可以简单地返回它在Java代码中直接创建的Java对象
     * 对于如何存储定义没有限制:LDAP, RDBMS, XML,属性文件等等,
     * 鼓励实现支持bean之间的引用(依赖注入)
     *
     * <p>In contrast to the methods in {@link ListableBeanFactory}, all of the
     * operations in this interface will also check parent factories if this is a
     * {@link HierarchicalBeanFactory}. If a bean is not found in this factory instance,
     * the immediate parent factory will be asked. Beans in this factory instance
     * are supposed to override beans of the same name in any parent factory.
     * 与{ListableBeanFactory}中的方法相反,此接口中的所有操作也将检查父工厂是否为{HierarchicalBeanFactory}
     * 如果在这个工厂实例中没有找到bean,将询问直接的父工厂
     * 这个工厂实例中的bean,应该覆盖任何父工厂中同名的bean
     *
     * <p>Bean factory implementations should support the standard bean lifecycle interfaces
     * as far as possible. The full set of initialization methods and their standard order is:
     * Bean工厂实现应该尽可能支持标准Bean生命周期接口
     * 完整的初始化方法及其标准顺序是:
     * <ol>
     * <li>BeanNameAware's {@code setBeanName}
     * <li>BeanClassLoaderAware's {@code setBeanClassLoader}
     * <li>BeanFactoryAware's {@code setBeanFactory}
     * <li>EnvironmentAware's {@code setEnvironment}
     * <li>EmbeddedValueResolverAware's {@code setEmbeddedValueResolver}
     * <li>ResourceLoaderAware's {@code setResourceLoader}
     * (only applicable when running in an application context)
     * <li>ApplicationEventPublisherAware's {@code setApplicationEventPublisher}
     * (only applicable when running in an application context)
     * <li>MessageSourceAware's {@code setMessageSource}
     * (only applicable when running in an application context)
     * <li>ApplicationContextAware's {@code setApplicationContext}
     * (only applicable when running in an application context)
     * <li>ServletContextAware's {@code setServletContext}
     * (only applicable when running in a web application context)
     * <li>{@code postProcessBeforeInitialization} methods of BeanPostProcessors
     * <li>InitializingBean's {@code afterPropertiesSet}
     * <li>a custom init-method definition
     * <li>{@code postProcessAfterInitialization} methods of BeanPostProcessors
     * </ol>
     *
     * <p>On shutdown of a bean factory, the following lifecycle methods apply:
     * <ol>
     * <li>{@code postProcessBeforeDestruction} methods of DestructionAwareBeanPostProcessors
     * <li>DisposableBean's {@code destroy}
     * <li>a custom destroy-method definition
     * </ol>
     *
     * @author Rod Johnson
     * @author Juergen Hoeller
     * @author Chris Beams
     * @since 13 April 2001
     * @see BeanNameAware#setBeanName
     * @see BeanClassLoaderAware#setBeanClassLoader
     * @see BeanFactoryAware#setBeanFactory
     * @see org.springframework.context.ResourceLoaderAware#setResourceLoader
     * @see org.springframework.context.ApplicationEventPublisherAware#setApplicationEventPublisher
     * @see org.springframework.context.MessageSourceAware#setMessageSource
     * @see org.springframework.context.ApplicationContextAware#setApplicationContext
     * @see org.springframework.web.context.ServletContextAware#setServletContext
     * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization
     * @see InitializingBean#afterPropertiesSet
     * @see org.springframework.beans.factory.support.RootBeanDefinition#getInitMethodName
     * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization
     * @see DisposableBean#destroy
     * @see org.springframework.beans.factory.support.RootBeanDefinition#getDestroyMethodName
     */
    public interface BeanFactory {
    
        /**
         * Used to dereference a {@link FactoryBean} instance and distinguish it from
         * beans <i>created</i> by the FactoryBean. For example, if the bean named
         * {@code myJndiObject} is a FactoryBean, getting {@code &myJndiObject}
         * will return the factory, not the instance returned by the factory.
         * 用于取消对实例的引用,并通过FactoryBean将其与bean区分开来
         * 例如:如果这个bean的名字是myJndiObject它是一个FactoryBean,通过getting(&myJndiObject)
         * 将会返回这个工厂,而不是返回这个工厂的实例;
         *
         */
        String FACTORY_BEAN_PREFIX = "&";
    
    
        /**
         * Return an instance, which may be shared or independent, of the specified bean.
         * <p>This method allows a Spring BeanFactory to be used as a replacement for the
         * Singleton or Prototype design pattern. Callers may retain references to
         * returned objects in the case of Singleton beans.
         * <p>Translates aliases back to the corresponding canonical bean name.
         * Will ask the parent factory if the bean cannot be found in this factory instance.
         * @param name the name of the bean to retrieve
         * @return an instance of the bean
         * @throws NoSuchBeanDefinitionException if there is no bean with the specified name
         * @throws BeansException if the bean could not be obtained
         * 返回指定bean的一个实例,该实例可以是共享的,也可以是独立的;
         * 该方法允许使用Spring BeanFactory作为单例或原型设计模式的替代,
         * 在单例bean的情况下,调用者可以保留对返回对象的引用.
         * 将别名翻译回相应的规范bean名称,
         * 将询问父工厂是否在此工厂实例中找不到bean.
         *
         */
        Object getBean(String name) throws BeansException;
    
        /**
         * Return an instance, which may be shared or independent, of the specified bean.
         * <p>Behaves the same as {@link #getBean(String)}, but provides a measure of type
         * safety by throwing a BeanNotOfRequiredTypeException if the bean is not of the
         * required type. This means that ClassCastException can't be thrown on casting
         * the result correctly, as can happen with {@link #getBean(String)}.
         * <p>Translates aliases back to the corresponding canonical bean name.
         * Will ask the parent factory if the bean cannot be found in this factory instance.
         * @param name the name of the bean to retrieve
         * @param requiredType type the bean must match; can be an interface or superclass
         * @return an instance of the bean
         * @throws NoSuchBeanDefinitionException if there is no such bean definition
         * @throws BeanNotOfRequiredTypeException if the bean is not of the required type
         * @throws BeansException if the bean could not be created
         * 返回指定bean的一个实例,该实例可以是共享的也可以是独立的;
         * 行为与getBean()相同,但是如果bean不是必需的类型,则通过抛出BeanNotOfRequiredTypeException
         * 来提供类型安全性的度量
         * 这意味着ClassCastException不能像getBean()那样在正确的转换结果时抛出
         * 将别名翻译回相应的规范bean名称
         * 将询问父工厂是否在此工厂实例中找不到bean;
         */
        <T> T getBean(String name, Class<T> requiredType) throws BeansException;
    
        /**
         * Return an instance, which may be shared or independent, of the specified bean.
         * <p>Allows for specifying explicit constructor arguments / factory method arguments,
         * overriding the specified default arguments (if any) in the bean definition.
         * @param name the name of the bean to retrieve
         * @param args arguments to use when creating a bean instance using explicit arguments
         * (only applied when creating a new instance as opposed to retrieving an existing one)
         * @return an instance of the bean
         * @throws NoSuchBeanDefinitionException if there is no such bean definition
         * @throws BeanDefinitionStoreException if arguments have been given but
         * the affected bean isn't a prototype
         * @throws BeansException if the bean could not be created
         * @since 2.5
         * 返回指定bean的一个实例,该实例可以是共享的也可以是独立的;
         * 允许指定显式构造函数参数/工厂方法参数,
         * 覆盖bean定义中指定的默认参数(如果有的话)
         */
        Object getBean(String name, Object... args) throws BeansException;
    
        /**
         * Return the bean instance that uniquely matches the given object type, if any.
         * <p>This method goes into {@link ListableBeanFactory} by-type lookup territory
         * but may also be translated into a conventional by-name lookup based on the name
         * of the given type. For more extensive retrieval operations across sets of beans,
         * use {@link ListableBeanFactory} and/or {@link BeanFactoryUtils}.
         * @param requiredType type the bean must match; can be an interface or superclass
         * @return an instance of the single bean matching the required type
         * @throws NoSuchBeanDefinitionException if no bean of the given type was found
         * @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
         * @throws BeansException if the bean could not be created
         * @since 3.0
         * @see ListableBeanFactory
         * 返回唯一匹配给定对象类型的bean实例,如果有的话
         * 该方法进入ListableBeanFactory的按类型查找领域,
         * 但是也可以根据给定类型的名称转换为传统的按名称查找
         * 用于跨bean集进行更广泛的检索操作
         * 通过使用ListableBeanFactory或者BeanFactoryUtils
         */
        <T> T getBean(Class<T> requiredType) throws BeansException;
    
        /**
         * Return an instance, which may be shared or independent, of the specified bean.
         * <p>Allows for specifying explicit constructor arguments / factory method arguments,
         * overriding the specified default arguments (if any) in the bean definition.
         * <p>This method goes into {@link ListableBeanFactory} by-type lookup territory
         * but may also be translated into a conventional by-name lookup based on the name
         * of the given type. For more extensive retrieval operations across sets of beans,
         * use {@link ListableBeanFactory} and/or {@link BeanFactoryUtils}.
         * @param requiredType type the bean must match; can be an interface or superclass
         * @param args arguments to use when creating a bean instance using explicit arguments
         * (only applied when creating a new instance as opposed to retrieving an existing one)
         * @return an instance of the bean
         * @throws NoSuchBeanDefinitionException if there is no such bean definition
         * @throws BeanDefinitionStoreException if arguments have been given but
         * the affected bean isn't a prototype
         * @throws BeansException if the bean could not be created
         * @since 4.1
         * 返回指定bean的一个实例,该实例可以是共享的也可以是独立的;
         * 允许指定显式构造函数参数/工厂方法参数,
         * 覆盖bean定义中指定的默认参数(如果有的话)
         * 该方法进入ListableBeanFactory的按类型查找领域,
         * 但是也可以根据给定类型的名称转换为传统的按名称查找
         * 用于跨bean集进行更广泛的检索操作
         * 通过使用ListableBeanFactory或者BeanFactoryUtils
         */
        <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
    
        /**
         * Return a provider for the specified bean, allowing for lazy on-demand retrieval
         * of instances, including availability and uniqueness options.
         * @param requiredType type the bean must match; can be an interface or superclass
         * @return a corresponding provider handle
         * @since 5.1
         * @see #getBeanProvider(ResolvableType)
         * 返回指定bean的提供程序,允许延迟按需检索实例,包括可用性和唯一性选项
         */
        <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
    
        /**
         * Return a provider for the specified bean, allowing for lazy on-demand retrieval
         * of instances, including availability and uniqueness options.
         * @param requiredType type the bean must match; can be a generic type declaration.
         * Note that collection types are not supported here, in contrast to reflective
         * injection points. For programmatically retrieving a list of beans matching a
         * specific type, specify the actual bean type as an argument here and subsequently
         * use {@link ObjectProvider#orderedStream()} or its lazy streaming/iteration options.
         * @return a corresponding provider handle
         * @since 5.1
         * @see ObjectProvider#iterator()
         * @see ObjectProvider#stream()
         * @see ObjectProvider#orderedStream()
         * 返回指定bean的提供程序,允许延迟按需检索实例,包括可用性和唯一性选项
         */
        <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);
    
        /**
         * Does this bean factory contain a bean definition or externally registered singleton
         * instance with the given name?
         * <p>If the given name is an alias, it will be translated back to the corresponding
         * canonical bean name.
         * <p>If this factory is hierarchical, will ask any parent factory if the bean cannot
         * be found in this factory instance.
         * <p>If a bean definition or singleton instance matching the given name is found,
         * this method will return {@code true} whether the named bean definition is concrete
         * or abstract, lazy or eager, in scope or not. Therefore, note that a {@code true}
         * return value from this method does not necessarily indicate that {@link #getBean}
         * will be able to obtain an instance for the same name.
         * @param name the name of the bean to query
         * @return whether a bean with the given name is present
         * 这个bean工厂是否包含一个bean定义或外部注册的具有给定名称的单例实例?
         * 如果给定的名称是别名,它将被转换为相应的规范bean名称
         * 如果这个工厂是分层的,将询问任何父工厂是否在这个工厂实例中找不到bean
         * 如果找到与给定名称匹配的bean定义或单例实例,该方法将返回true,无论指定的bean定义是具体的还是抽象的,
         * 是延迟的还是热切的,在作用域上是否如此,
         * 然而,请注意,这个方法的true返回值并不一定标识{getBean}能够获得同名的实例
         */
        boolean containsBean(String name);
    
        /**
         * Is this bean a shared singleton? That is, will {@link #getBean} always
         * return the same instance?
         * <p>Note: This method returning {@code false} does not clearly indicate
         * independent instances. It indicates non-singleton instances, which may correspond
         * to a scoped bean as well. Use the {@link #isPrototype} operation to explicitly
         * check for independent instances.
         * <p>Translates aliases back to the corresponding canonical bean name.
         * Will ask the parent factory if the bean cannot be found in this factory instance.
         * @param name the name of the bean to query
         * @return whether this bean corresponds to a singleton instance
         * @throws NoSuchBeanDefinitionException if there is no bean with the given name
         * @see #getBean
         * @see #isPrototype
         * 这是一个共享的单例bean吗?也就是说{getBean}总是返回相同的实例吗?
         * 注意:这个返回{false}的方法并不清楚的表示独立的实例,
         * 它指出了非单例实例,这也可能对应于一个作用域bean
         * 使用{isPrototype}操作显式地检查独立实例
         * 将别名翻译成相应的规范bean名称
         * 将询问父工厂是否在此工厂实例中找不到bean.
         */
        boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
    
        /**
         * Is this bean a prototype? That is, will {@link #getBean} always return
         * independent instances?
         * <p>Note: This method returning {@code false} does not clearly indicate
         * a singleton object. It indicates non-independent instances, which may correspond
         * to a scoped bean as well. Use the {@link #isSingleton} operation to explicitly
         * check for a shared singleton instance.
         * <p>Translates aliases back to the corresponding canonical bean name.
         * Will ask the parent factory if the bean cannot be found in this factory instance.
         * @param name the name of the bean to query
         * @return whether this bean will always deliver independent instances
         * @throws NoSuchBeanDefinitionException if there is no bean with the given name
         * @since 2.0.3
         * @see #getBean
         * @see #isSingleton
         * 这个bean是原型吗?也就是说,{getBean}总是返回独立的实例
         * 注意:这个返回{false}的方法并不清楚的表示一个单例对象
         * 它指示非独立的实例,这些实例也可能对应于作用域的bean
         * 使用{isSingleton}操作显示的检查共享的单例实例
         * 将别名翻译成相应的规范bean名称
         * 将询问父工厂是否在此工厂实例中找不到bean
         */
        boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
    
        /**
         * Check whether the bean with the given name matches the specified type.
         * More specifically, check whether a {@link #getBean} call for the given name
         * would return an object that is assignable to the specified target type.
         * <p>Translates aliases back to the corresponding canonical bean name.
         * Will ask the parent factory if the bean cannot be found in this factory instance.
         * @param name the name of the bean to query
         * @param typeToMatch the type to match against (as a {@code ResolvableType})
         * @return {@code true} if the bean type matches,
         * {@code false} if it doesn't match or cannot be determined yet
         * @throws NoSuchBeanDefinitionException if there is no bean with the given name
         * @since 4.2
         * @see #getBean
         * @see #getType
         * 检查具有给定名称的bean是否匹配指定的类型
         * 更具体地说,检查对于给定名称的{getBean}调用是否会返回可分配给指定目标类型的对象;
         * 将别名翻译成相应的规范bean名称
         * 将询问父工厂是否在此工厂实例中找不到bean
         */
        boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
    
        /**
         * Check whether the bean with the given name matches the specified type.
         * More specifically, check whether a {@link #getBean} call for the given name
         * would return an object that is assignable to the specified target type.
         * <p>Translates aliases back to the corresponding canonical bean name.
         * Will ask the parent factory if the bean cannot be found in this factory instance.
         * @param name the name of the bean to query
         * @param typeToMatch the type to match against (as a {@code Class})
         * @return {@code true} if the bean type matches,
         * {@code false} if it doesn't match or cannot be determined yet
         * @throws NoSuchBeanDefinitionException if there is no bean with the given name
         * @since 2.0.1
         * @see #getBean
         * @see #getType
         */
        boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
    
        /**
         * Determine the type of the bean with the given name. More specifically,
         * determine the type of object that {@link #getBean} would return for the given name.
         * <p>For a {@link FactoryBean}, return the type of object that the FactoryBean creates,
         * as exposed by {@link FactoryBean#getObjectType()}. This may lead to the initialization
         * of a previously uninitialized {@code FactoryBean} (see {@link #getType(String, boolean)}).
         * <p>Translates aliases back to the corresponding canonical bean name.
         * Will ask the parent factory if the bean cannot be found in this factory instance.
         * @param name the name of the bean to query
         * @return the type of the bean, or {@code null} if not determinable
         * @throws NoSuchBeanDefinitionException if there is no bean with the given name
         * @since 1.1.2
         * @see #getBean
         * @see #isTypeMatch
         * 确定具有给定名称的bean的类型,更具体地说,确定{getBean}为给定名称返回的对象类型.
         * 对于{FactoryBean},返回FactoryBean创建的对象类型,由{FactoryBean的getObjectType()}公开;
         * 这可能导致前面未初始化的{FactoryBean}的初始化(参见{getType(String,boolean)}).
         * 将别名翻译成相应的规范bean名称
         * 将询问父工厂是否在此工厂实例中找不到bean
         */
        @Nullable
        Class<?> getType(String name) throws NoSuchBeanDefinitionException;
    
        /**
         * Determine the type of the bean with the given name. More specifically,
         * determine the type of object that {@link #getBean} would return for the given name.
         * <p>For a {@link FactoryBean}, return the type of object that the FactoryBean creates,
         * as exposed by {@link FactoryBean#getObjectType()}. Depending on the
         * {@code allowFactoryBeanInit} flag, this may lead to the initialization of a previously
         * uninitialized {@code FactoryBean} if no early type information is available.
         * <p>Translates aliases back to the corresponding canonical bean name.
         * Will ask the parent factory if the bean cannot be found in this factory instance.
         * @param name the name of the bean to query
         * @param allowFactoryBeanInit whether a {@code FactoryBean} may get initialized
         * just for the purpose of determining its object type
         * @return the type of the bean, or {@code null} if not determinable
         * @throws NoSuchBeanDefinitionException if there is no bean with the given name
         * @since 5.2
         * @see #getBean
         * @see #isTypeMatch
         * 确定具有给定名称的bean类型.更具体地说,确定{getBean}为给定名称返回的对象类型.
         * 对于{FactoryBean},返回FactoryBean创建的对象的类型,由{FactoryBean的getObjectType()}公开.
         * 根据{allowFactoryBeanInit}标志,如果没有可用的早期类型信息,这可能会导致初始化以前,未初始化的{FactoryBean}
         * 将别名翻译成相应的规范bean名称,
         * 将询问父工厂是否在此工厂实例中找不到bean.
         */
        @Nullable
        Class<?> getType(String name, boolean allowFactoryBeanInit) throws NoSuchBeanDefinitionException;
    
        /**
         * Return the aliases for the given bean name, if any.
         * All of those aliases point to the same bean when used in a {@link #getBean} call.
         * <p>If the given name is an alias, the corresponding original bean name
         * and other aliases (if any) will be returned, with the original bean name
         * being the first element in the array.
         * <p>Will ask the parent factory if the bean cannot be found in this factory instance.
         * @param name the bean name to check for aliases
         * @return the aliases, or an empty array if none
         * @see #getBean
         * 返回给定bean名称的别名,如果有的话.
         * 当在{getBean}调用中使用时,所有这些别名都指向同一个bean;
         * 如果给定的名称是别名,则返回相应的原始bean名称和其他别名(如果与),原始bean名称是数字中的第一个元素.
         * 将询问父工厂是否在此工厂实例中找不到bean;
         */
        String[] getAliases(String name);
    
    }
  • 相关阅读:
    AIZU 0005
    Android Studio 1.0 (稳定版) 完全攻略
    android studio中avd sdk路径
    vim强大探究之光标移动
    Android项目打第三方jar包
    Android导出jar包后的资源使用问题
    混淆Android JAR包的方法
    Layout_margn与padding的区别
    Android软件开发之盘点自定义View界面大合集(二)
    Android软件开发之盘点所有Dialog对话框大合集(一)
  • 原文地址:https://www.cnblogs.com/wk-missQ1/p/12620298.html
Copyright © 2020-2023  润新知