• Spring源码解析-IOC容器的实现-ApplicationContext


      上面我们已经知道了IOC的建立的基本步骤了,我们就可以用编码的方式和IOC容器进行建立过程了。其实Spring已经为我们提供了很多实现,想必上面的简单扩展,如XMLBeanFacroty等。我们一般是用ApplicationContext这个接口,这个接口实现了基本的功能外,还添加了很多相应的功能,根据看下面的源码我来看看是怎么实现更多的功能的。

    public interface ApplicationContext extends ListableBeanFactory, HierarchicalBeanFactory,
            MessageSource, ApplicationEventPublisher, ResourcePatternResolver {

        /**
         * 返回一个唯一的bean的ID
         */
        String getId();

        /**
         * 返回一个name为context
        */
        String getDisplayName();

        /**
         * 返回第一次加载的时间戳
         */
        long getStartupDate();

        /**
         * Return the parent context, or <code>null</code> if there is no parent
         * and this is the root of the context hierarchy.
         * @return the parent context, or <code>null</code> if there is no parent
         */
        ApplicationContext getParent();

        /**
         * Expose AutowireCapableBeanFactory functionality for this context.
         * <p>This is not typically used by application code, except for the purpose
         * of initializing bean instances that live outside the application context,
         * applying the Spring bean lifecycle (fully or partly) to them.
         * <p>Alternatively, the internal BeanFactory exposed by the
         * {@link ConfigurableApplicationContext} interface offers access to the
         * AutowireCapableBeanFactory interface too. The present method mainly
         * serves as convenient, specific facility on the ApplicationContext
         * interface itself.
         * @return the AutowireCapableBeanFactory for this context
         * @throws IllegalStateException if the context does not support
         * the AutowireCapableBeanFactory interface or does not hold an autowire-capable
         * bean factory yet (usually if <code>refresh()</code> has never been called)
         * @see ConfigurableApplicationContext#refresh()
         * @see ConfigurableApplicationContext#getBeanFactory()
         */
        AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;

    }
    以上是ApplicationContext的源码,她继承了相应的接口,ListableBeanFactory, HierarchicalBeanFactory,
            MessageSource, ApplicationEventPublisher, ResourcePatternResolver
    去进行相应的扩展。因此ApplicationContext增加了相应的很多功能。

    如下:1.支持不同的信息源,因为他扩展了MessageSource接口,这个就支持了消息的国际化实现。2.支持相应的事件。因为继承了ApplicationEventPublisher,这样就为上下文提供了事件的机制。3.访问资源。这个体现在ResourceLoader和Resource的支持上,这样我们就可以在不同的地方得到bean定义的资源。

    因此在我们使用的时候,一般都使用ApplicationContext作为IOC容器的基本形式。创建IOC容器。

    ListableBeanFactory源码:

    public interface ListableBeanFactory extends BeanFactory {

        /**
         * 检查beaFactory是否包含bean的定义  通过bean的name
         * <p>Does not consider any hierarchy this factory may participate in,
         * and ignores any singleton beans that have been registered by
         * other means than bean definitions.
         * @param beanName the name of the bean to look for
         * @return if this bean factory contains a bean definition with the given name
         * @see #containsBean
         */
        boolean containsBeanDefinition(String beanName);

        /**
         * 返回在BeanFactory中存在的bean的定义的数量
         * <p>Does not consider any hierarchy this factory may participate in,
         * and ignores any singleton beans that have been registered by
         * other means than bean definitions.
         * @return the number of beans defined in the factory
         */
        int getBeanDefinitionCount();

        /**
         * 返回所有关于bean定义的name
         * <p>Does not consider any hierarchy this factory may participate in,
         * and ignores any singleton beans that have been registered by
         * other means than bean definitions.
         * @return the names of all beans defined in this factory,
         * or an empty array if none defined
         */
        String[] getBeanDefinitionNames();
        
        /**
         * 返回bean的名称  通过bean定义的类型
         * judging from either bean definitions or the value of <code>getObjectType</code>
         * in the case of FactoryBeans.
         * <p><b>NOTE: This method introspects top-level beans only.</b> It does <i>not</i>
         * check nested beans which might match the specified type as well.
         * <p>Does consider objects created by FactoryBeans, which means that FactoryBeans
         * will get initialized. If the object created by the FactoryBean doesn't match,
         * the raw FactoryBean itself will be matched against the type.
         * <p>Does not consider any hierarchy this factory may participate in.
         * Use BeanFactoryUtils' <code>beanNamesForTypeIncludingAncestors</code>
         * to include beans in ancestor factories too.
         * <p>Note: Does <i>not</i> ignore singleton beans that have been registered
         * by other means than bean definitions.
         * <p>This version of <code>getBeanNamesForType</code> matches all kinds of beans,
         * be it singletons, prototypes, or FactoryBeans. In most implementations, the
         * result will be the same as for <code>getBeanNamesOfType(type, true, true)</code>.
         * <p>Bean names returned by this method should always return bean names <i>in the
         * order of definition</i> in the backend configuration, as far as possible.
         * @param type the class or interface to match, or <code>null</code> for all bean names
         * @return the names of beans (or objects created by FactoryBeans) matching
         * the given object type (including subclasses), or an empty array if none
         * @see FactoryBean#getObjectType
         * @see BeanFactoryUtils#beanNamesForTypeIncludingAncestors(ListableBeanFactory, Class)
         */
        String[] getBeanNamesForType(Class type);

        /**
         * 返回bean的名称  通过bean定义的类型 (including subclasses),
         * judging from either bean definitions or the value of <code>getObjectType</code>
         * in the case of FactoryBeans.
         * <p><b>NOTE: This method introspects top-level beans only.</b> It does <i>not</i>
         * check nested beans which might match the specified type as well.
         * <p>Does consider objects created by FactoryBeans if the "allowEagerInit" flag is set,
         * which means that FactoryBeans will get initialized. If the object created by the
         * FactoryBean doesn't match, the raw FactoryBean itself will be matched against the
         * type. If "allowEagerInit" is not set, only raw FactoryBeans will be checked
         * (which doesn't require initialization of each FactoryBean).
    $     * <p>Does not consider any hierarchy this factory may participate in.
         * Use BeanFactoryUtils' <code>beanNamesForTypeIncludingAncestors</code>
         * to include beans in ancestor factories too.
         * <p>Note: Does <i>not</i> ignore singleton beans that have been registered
         * by other means than bean definitions.
         * <p>Bean names returned by this method should always return bean names <i>in the
         * order of definition</i> in the backend configuration, as far as possible.
         * @param type the class or interface to match, or <code>null</code> for all bean names
         * @param includeNonSingletons whether to include prototype or scoped beans too
         * or just singletons (also applies to FactoryBeans)
         * @param allowEagerInit whether to initialize <i>lazy-init singletons</i> and
         * <i>objects created by FactoryBeans</i> (or by factory methods with a
         * "factory-bean" reference) for the type check. Note that FactoryBeans need to be
         * eagerly initialized to determine their type: So be aware that passing in "true"
         * for this flag will initialize FactoryBeans and "factory-bean" references.
         * @return the names of beans (or objects created by FactoryBeans) matching
         * the given object type (including subclasses), or an empty array if none
         * @see FactoryBean#getObjectType
         * @see BeanFactoryUtils#beanNamesForTypeIncludingAncestors(ListableBeanFactory, Class, boolean, boolean)
         */
        String[] getBeanNamesForType(Class type, boolean includeNonSingletons, boolean allowEagerInit);

        /**
         * 通过对象类型返回相应bean的实例 (including
         * subclasses), judging from either bean definitions or the value of
         * <code>getObjectType</code> in the case of FactoryBeans.
         * <p><b>NOTE: This method introspects top-level beans only.</b> It does <i>not</i>
         * check nested beans which might match the specified type as well.
         * <p>Does consider objects created by FactoryBeans, which means that FactoryBeans
         * will get initialized. If the object created by the FactoryBean doesn't match,
         * the raw FactoryBean itself will be matched against the type.
         * <p>Does not consider any hierarchy this factory may participate in.
         * Use BeanFactoryUtils' <code>beansOfTypeIncludingAncestors</code>
         * to include beans in ancestor factories too.
         * <p>Note: Does <i>not</i> ignore singleton beans that have been registered
         * by other means than bean definitions.
         * <p>This version of getBeansOfType matches all kinds of beans, be it
         * singletons, prototypes, or FactoryBeans. In most implementations, the
         * result will be the same as for <code>getBeansOfType(type, true, true)</code>.
         * <p>The Map returned by this method should always return bean names and
         * corresponding bean instances <i>in the order of definition</i> in the
         * backend configuration, as far as possible.
         * @param type the class or interface to match, or <code>null</code> for all concrete beans
         * @return a Map with the matching beans, containing the bean names as
         * keys and the corresponding bean instances as values
         * @throws BeansException if a bean could not be created
         * @since 1.1.2
         * @see FactoryBean#getObjectType
         * @see BeanFactoryUtils#beansOfTypeIncludingAncestors(ListableBeanFactory, Class)
         */
        <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException;

        /**
         * 通过对象类型返回相应bean的实例 (including
         * subclasses), judging from either bean definitions or the value of
         * <code>getObjectType</code> in the case of FactoryBeans.
         * <p><b>NOTE: This method introspects top-level beans only.</b> It does <i>not</i>
         * check nested beans which might match the specified type as well.
         * <p>Does consider objects created by FactoryBeans if the "allowEagerInit" flag is set,
         * which means that FactoryBeans will get initialized. If the object created by the
         * FactoryBean doesn't match, the raw FactoryBean itself will be matched against the
         * type. If "allowEagerInit" is not set, only raw FactoryBeans will be checked
         * (which doesn't require initialization of each FactoryBean).
         * <p>Does not consider any hierarchy this factory may participate in.
         * Use BeanFactoryUtils' <code>beansOfTypeIncludingAncestors</code>
         * to include beans in ancestor factories too.
         * <p>Note: Does <i>not</i> ignore singleton beans that have been registered
         * by other means than bean definitions.
         * <p>The Map returned by this method should always return bean names and
         * corresponding bean instances <i>in the order of definition</i> in the
         * backend configuration, as far as possible.
         * @param type the class or interface to match, or <code>null</code> for all concrete beans
         * @param includeNonSingletons whether to include prototype or scoped beans too
         * or just singletons (also applies to FactoryBeans)
         * @param allowEagerInit whether to initialize <i>lazy-init singletons</i> and
         * <i>objects created by FactoryBeans</i> (or by factory methods with a
         * "factory-bean" reference) for the type check. Note that FactoryBeans need to be
         * eagerly initialized to determine their type: So be aware that passing in "true"
         * for this flag will initialize FactoryBeans and "factory-bean" references.
         * @return a Map with the matching beans, containing the bean names as
         * keys and the corresponding bean instances as values
         * @throws BeansException if a bean could not be created
         * @see FactoryBean#getObjectType
         * @see BeanFactoryUtils#beansOfTypeIncludingAncestors(ListableBeanFactory, Class, boolean, boolean)
         */
        <T> Map<String, T> getBeansOfType(Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
                throws BeansException;

        /*
         * 查找所有的bean  通过注解

      *Find all beans whose <code>Class</code> has the supplied {@link java.lang.annotation.Annotation} type.
         * @param annotationType the type of annotation to look for
         * @return a Map with the matching beans, containing the bean names as
         * keys and the corresponding bean instances as values
         * @throws BeansException if a bean could not be created
         */
        Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType)
                throws BeansException;

        /**
         * Find a {@link Annotation} of <code>annotationType</code> on the specified
         * bean, traversing its interfaces and super classes if no annotation can be
         * found on the given class itself.
         * @param beanName the name of the bean to look for annotations on
         * @param annotationType the annotation class to look for
         * @return the annotation of the given type found, or <code>null</code>
         */
        <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType);

    }
    HierarchicalBeanFactory源码:

    public interface HierarchicalBeanFactory extends BeanFactory {
        
        /**
         * 返回父 bean factory, or <code>null</code> if there is none.
         */
        BeanFactory getParentBeanFactory();

        /**
         * 返回本地是否存在bean的名称为name的bean
         * ignoring beans defined in ancestor contexts.
         * <p>This is an alternative to <code>containsBean</code>, ignoring a bean
         * of the given name from an ancestor bean factory.
         * @param name the name of the bean to query
         * @return whether a bean with the given name is defined in the local factory
         * @see org.springframework.beans.factory.BeanFactory#containsBean
         */
        boolean containsLocalBean(String name);

    }

    MessageSource的源码:

    public interface MessageSource {

        /**
         * Try to resolve the message. Return default message if no message was found.
         * @param code the code to lookup up, such as 'calculator.noRateSet'. Users of
         * this class are encouraged to base message names on the relevant fully
         * qualified class name, thus avoiding conflict and ensuring maximum clarity.
         * @param args array of arguments that will be filled in for params within
         * the message (params look like "{0}", "{1,date}", "{2,time}" within a message),
         * or <code>null</code> if none.
         * @param defaultMessage String to return if the lookup fails
         * @param locale the Locale in which to do the lookup
         * @return the resolved message if the lookup was successful;
         * otherwise the default message passed as a parameter
         * @see java.text.MessageFormat
         */
        String getMessage(String code, Object[] args, String defaultMessage, Locale locale);

        /**
         * Try to resolve the message. Treat as an error if the message can't be found.
         * @param code the code to lookup up, such as 'calculator.noRateSet'
         * @param args Array of arguments that will be filled in for params within
         * the message (params look like "{0}", "{1,date}", "{2,time}" within a message),
         * or <code>null</code> if none.
         * @param locale the Locale in which to do the lookup
         * @return the resolved message
         * @throws NoSuchMessageException if the message wasn't found
         * @see java.text.MessageFormat
         */
        String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException;

        /**
         * Try to resolve the message using all the attributes contained within the
         * <code>MessageSourceResolvable</code> argument that was passed in.
         * <p>NOTE: We must throw a <code>NoSuchMessageException</code> on this method
         * since at the time of calling this method we aren't able to determine if the
         * <code>defaultMessage</code> property of the resolvable is null or not.
         * @param resolvable value object storing attributes required to properly resolve a message
         * @param locale the Locale in which to do the lookup
         * @return the resolved message
         * @throws NoSuchMessageException if the message wasn't found
         * @see java.text.MessageFormat
         */
        String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;

    }

    ApplicationEventPublisher的源码:

    public interface ApplicationEventPublisher {

        /**
         * Notify all listeners registered with this application of an application
         * event. Events may be framework events (such as RequestHandledEvent)
         * or application-specific events.
         * @param event the event to publish
         * @see org.springframework.web.context.support.RequestHandledEvent
         */
        void publishEvent(ApplicationEvent event);

    }

    ResourcePatternResolver的源码:

    public interface ResourcePatternResolver extends ResourceLoader {

        /**
         * Pseudo URL prefix for all matching resources from the class path: "classpath*:"
         * This differs from ResourceLoader's classpath URL prefix in that it
         * retrieves all matching resources for a given name (e.g. "/beans.xml"),
         * for example in the root of all deployed JAR files.
         * @see org.springframework.core.io.ResourceLoader#CLASSPATH_URL_PREFIX
         */
        String CLASSPATH_ALL_URL_PREFIX = "classpath*:";

        /**
         * Resolve the given location pattern into Resource objects.
         * <p>Overlapping resource entries that point to the same physical
         * resource should be avoided, as far as possible. The result should
         * have set semantics.
         * @param locationPattern the location pattern to resolve
         * @return the corresponding Resource objects
         * @throws IOException in case of I/O errors
         */
        Resource[] getResources(String locationPattern) throws IOException;

    }

    这个接口继承了ResourceLoader,所以让ApplicationContext也支持ResourceLoader和Resource.ResourceLoader里面有一个方法是得到Resource,可以看看:

    public interface ResourceLoader {

        /** Pseudo URL prefix for loading from the class path: "classpath:" */
        String CLASSPATH_URL_PREFIX = ResourceUtils.CLASSPATH_URL_PREFIX;


        /**
         * 通过资源的地址得到Resource
         */
        Resource getResource(String location);

        /**
         * Expose the ClassLoader used by this ResourceLoader.
         * <p>Clients which need to access the ClassLoader directly can do so
         * in a uniform manner with the ResourceLoader, rather than relying
         * on the thread context ClassLoader.
         * @return the ClassLoader (never <code>null</code>)
         */
        ClassLoader getClassLoader();

    }

  • 相关阅读:
    Mysql 之根据经纬度按距离排序
    Python的列表和元组
    go实现堆排序、快速排序、桶排序算法
    微信Hook劫获protobuf数据
    手机号批量查询微信昵称/网名/名称
    保存整个网页的内容
    天地图官网引入文件
    Postman-动态传参
    JAVA FileOutputStream与BufferedOutputStream的区别
    JAVA中sleep()和wait()的区别
  • 原文地址:https://www.cnblogs.com/tonylovett/p/4532689.html
Copyright © 2020-2023  润新知