您的位置:首页 > 编程语言 > Java开发

Spring源码阅读-IOC 容器解析

2019-07-27 22:11 417 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/weixin_45273693/article/details/97563450

在Spring框架中最重要的是Spring IoC容器,它是Spring框架的核心。本文将从更高的角度来解析Sping IoC容器,了解其是如何设计的。了解一样东西最好的办法是从其核心本质出发,只要把握住了这样一个核心,其他的一些东西也迎刃而解了。这是一个很好的开端,我们一起开始吧...

Spring IoC容器

org.springframework.context.ApplicationContext
接口代表Spring IoC容器,主要负责bean的实例化、配置、装配,简而言之,Spring IoC容器是管理这些bean的(这里所说的bean指的是组成你的应用程序中的对象,并且这些对象被Spring所管理)。容器如何知道哪些对象要进行实例化、配置和装配的呢?是通过读取配置文件元数据来达到这个效果的,配置文件元数据是用xml配置、Java注解和Java代码配置来表示的。这使得作为程序员的我们,只需要向Spring容器提供配置元数据,Spring容器就能在我们的应用中实例化、配置和装配这些对象。
org.springframework.beans
org.springframework.context
包是Spring IoC容器的基础。Spring提供了很多
Application
接口的实现。在单独的应用中,创建
ClassPathXmlApplicationContext
FileSystemXmlApplicationContext
的实例是非常常用的做法。示例如下:

<pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important; color: rgb(49, 70, 89); font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

Copy

ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); Hello hello = (Hello) ac.getBean("hello"); hello.sayHello();
</pre>

然而在大部分的应用场景中,不需要实例化一个或者多个Spring IoC容器的实例。例如在web应用的场景下,只需要在web.xml中创建七行样板配置的代码如下:

<pre class="xml" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important; color: rgb(49, 70, 89); font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

Copy

<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</paramvalue> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
</pre>

下面这张图从更高的视角展示了Spring是怎样工作的。你的应用程序中的类是和配置元数据组合在一起,以便在

ApplicationContext
创建和初始化之后,你拥有了一个完全配置的、可执行的系统。

image

ApplicationContext设计解析

为了方便对

ApplicationContext
接口的层次结构有一个大概的认识,下面使用IDEA来生成
ApplicationContext
的继承关系图。(选中ApplicationContext接口->右键->Diagrams->Show Diagrams...)

(温馨提示:点击图片可以查看高清大图)

image

从上图就能很清楚的看出

ApplicationContext
继承的接口分为五类:

  • BeanFactory
    :提供了能够管理任何对象的高级配置机制,这个接口是Spring框架中比较重要的一个接口。
    ListableBeanFactory
    :从该接口的名字就能知道,该接口除了拥有BeanFactory的功能外,该接口还有能列出factory中所有bean的实例的能力。
  • HierarchicalBeanFactory
    :该接口除了拥有BeanFactory的功能外,还提供了BeanFactory分层的机制,查找bean的时候,除了在自身BeanFactory查找外,如果没有查找到,还会在父级BeanFactory进行查找。
  • MessageSource
    :消息资源的处理,用于国际化。
  • ApplicationEventPublisher
    :用于处理事件发布机制。
  • EnvironmentCapable
    :提供了
    Environment
    的访问能力。
  • ResourceLoader
    :用于加载资源的策略接口(例如类路径下的资源、系统文件下的资源等等)。
      ResourcePatternResolver
      :用于将位置模式(例如Ant风格的路径模式)解析成资源对象的策略接口。
      classpath*:
      前缀能匹配所以类路径下的资源。

    先看一下在

    ApplicationContext
    中定义的方法:

    <pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important; color: rgb(49, 70, 89); font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

    Copy

    `String getId(); // 获取ApplicationContext的唯一id
    String getApplicationName(); // 该上下文所属的已经部署了的应用的名字,默认为""
    String getDisplayName(); // 友好的展示名字
    long getStartupDate(); // 该上下文第一次加载的时间

    ApplicationContext getParent(); // 父级ApplicationContext
    AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;`</pre>

    前四个方法用于获取该

    ApplicationContext
    的一些基本信息,
    getAutowireCapableBeanFactory()
    用于暴露
    AutowireCapableBeanFactory
    的功能,这通常不是提供给用于代码使用的,除非你想要在应用上下文的外面初始化bean的实例,关于
    AutowireCapableBeanFactory
    后面会有更加详细的解析。

    BeanFactory

    BeanFactory
    是Spring框架中比较重要的一个接口,下面列出了这个接口中的方法的定义:

    <pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important; color: rgb(49, 70, 89); font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

    Copy

    `// 获取bean
    Object getBean(String name) throws BeansException;
    <T> T getBean(String name, Class<T> requiredType) throws BeansException;
    Object getBean(String name, Object... args) throws BeansException;
    <T> T getBean(Class<T> requiredType) throws BeansException;
    <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;

    // 获取bean的提供者(对象工厂)
    <T> ObjectProvider<T> getBeanProvider(Class<T> requiredType);
    <T> ObjectProvider<T> getBeanProvider(ResolvableType requiredType);

    boolean containsBean(String name); // 是否包含指定名字的bean
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException; // 是否为单例
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException; // 是否为原型
    // 指定名字的bean是否和指定的类型匹配
    boolean isTypeMatch(String name, ResolvableType typeToMatch);
    boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
    Class<?> getType(String name)
    throws NoSuchBeanDefinitionException; // 获取指定名字的bean的类型
    String[] getAliases(String name); // 获取指定名字的bean的所有别名`</pre>

    这些方法大致可以分为三类:

    • getBean()
      方法用于获取匹配的bean的实例对象(有可能是Singleton或者Prototype的),如果没有找到匹配的bean则抛出
      BeansException
      子类的异常。如果在当前的工厂实例中没有找到匹配的bean,会在父级的工厂中进行查找。带有
      args
      参数的
      getBean()
      方法,允许显式的去指定构造器或者工厂方法的参数,会覆盖了在bean的定义中定义的参数,这仅仅在创建一个新的实例的时候才起作用,而在获取一个已经存在的实例是不起作用的。

    • getBeanProvider()
      方法用于获取指定bean的提供者,可以看到它返回的是一个
      ObjectProvider
      ,其父级接口是
      ObjectFactory
      。首先来看一下
      ObjectFactory
      ,它是一个对象的实例工厂,只有一个方法:

      <pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important;">

      Copy

      T getObject() throws BeansException;
      </pre>

      调用这个方法返回的是一个对象的实例。此接口通常用于封装一个泛型工厂,在每次调用的时候返回一些目标对象新的实例。

      ObjectFactory
      FactoryBean
      是类似的,只不过
      FactoryBean
      通常被定义为
      BeanFactory
      中的服务提供者(SPI)实例,而
      ObjectFactory
      通常是以API的形式提供给其他的bean。简单的来说,
      ObjectFactory
      一般是提供给开发者使用的,
      FactoryBean
      一般是提供给
      BeanFactory
      使用的。

      ObjectProvider
      继承
      ObjectFactory
      ,特为注入点而设计,允许可选择性的编程和宽泛的非唯一性的处理。在Spring 5.1的时候,该接口从
      Iterable
      扩展,提供了对
      Stream
      的支持。该接口的方法如下:

      <pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important;">

      Copy

      `// 获取对象的实例,允许根据显式的指定构造器的参数去构造对象
      T getObject(Object... args) throws BeansException;
      // 获取对象的实例,如果不可用,则返回null
      T getIfAvailable() throws BeansException;
      T getIfAvailable(Supplier<T> defaultSupplier) throws BeansException;
      void ifAvailable(Consumer<T> dependencyConsumer) throws BeansException;
      // 获取对象的实例,如果不是唯一的或者没有首先的bean,则返回null
      T getIfUnique() throws BeansException;
      T getIfUnique(Supplier<T> defaultSupplier) throws BeansException;
      void ifUnique(Consumer<T> dependencyConsumer) throws BeansException;

      // 获取多个对象的实例
      Iterator<T> iterator();
      Stream<T> stream();
      Stream<T> orderedStream()`</pre>

      这些接口是分为两类,

      一类是获取单个对象,
      getIfAvailable()
      方法用于获取可用的bean(没有则返回null),
      getIfUnique()
      方法用于获取唯一的bean(如果bean不是唯一的或者没有首选的bean返回null)。
      getIfAvailable(Supplier<T> defaultSupplier)
      getIfUnique(Supplier<T> defaultSupplier)
      ,如果没有获取到bean,则返回defaultSupplier提供的默认值,
      ifAvailable(Consumer<T> dependencyConsumer)
      ifUnique(Consumer<T> dependencyConsumer)
      提供了以函数式编程的方式去消费获取到的bean。
    • 另一类是获取多个对象,
      stream()
      方法返回连续的
      Stream
      ,不保证bean的顺序(通常是bean的注册顺序)。
      orderedStream()
      方法返回连续的
      Stream
      ,预先会根据工厂的公共排序比较器进行排序,一般是根据
      org.springframework.core.Ordered
      的约定进行排序。
  • 其他的是一些工具性的方法:

      通过名字判断是否包含指定bean的定义的
      containsBean(String name)
      方法
    • 判断是单例和原型的
      isSingleton(String name)
      isPrototype(String name)
      方法
    • 判断给定bean的名字是否和类型匹配的
      isTypeMatch
      方法
    • 根据bean的名字来获取其类型的
      getType(String name)
      方法
    • 根据bean的名字来获取其别名的
      getAliases(String name)
      方法

    或许你已经注意到了,有两个方法含有类型是

    ResolvableType
    的参数,那么
    ResolvableType
    是什么呢?假如说你要获取泛型类型的bean:
    MyBean<TheType>
    ,根据Class<t style="margin: 0px; padding: 0px;">来获取,肯定是满足不了要求的,泛型在编译时会被擦除。使用
    ResolvableType
    就能满足此需求,代码如下:</t>

    <pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important; color: rgb(49, 70, 89); font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

    Copy

    ResolvableType type = ResolvableType.forClassWithGenerics(MyType.class, TheType.class); ObjectProvider<MyType<TheType>> op = applicationContext.getBeanProvider(type); MyType<TheType> bean = op.getIfAvailable()
    </pre>

    简单的来说,

    ResolvableType
    是对Java
    java.lang.reflect.Type
    的封装,并且提供了一些访问该类型的其他信息的方法(例如父类, 泛型参数,该类)。从成员变量、方法参数、方法返回类型、类来构建
    ResolvableType
    的实例。

    ListableBeanFactory

    ListableBeanFactory
    接口有能列出工厂中所有的bean的能力,下面给出该接口中的所有方法:

    <pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important; color: rgb(49, 70, 89); font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

    Copy

    `boolean containsBeanDefinition(String beanName); // 是否包含给定名字的bean的定义
    int getBeanDefinitionCount(); // 工厂中bean的定义的数量
    String[] getBeanDefinitionNames(); // 工厂中所有定义了的bean的名字
    // 获取指定类型的bean的名字
    String[] getBeanNamesForType(ResolvableType type);
    String[] getBeanNamesForType(Class<?> type);
    String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit);
    // 获取所有使用提供的注解进行标注的bean的名字
    String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType);
    // 查找指定bean中的所有指定的注解(会考虑接口和父类中的注解)
    <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
    throws NoSuchBeanDefinitionException;

    // 根据指定的类型来获取所有的bean
    <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException;
    <T> Map<String, T> getBeansOfType(Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
    throws BeansException;
    // 获取所有使用提供的注解进行标注了的bean
    Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException;`</pre>

    上面的这些方法都不考虑祖先工厂中的bean,只会考虑在当前工厂中定义的bean。

    • 前八个方法用于获取bean的一些信息
    • 最后的三个方法用于获取所有满足条件的bean,返回结果Map中的键为bean的名字,值为bean的实例。这些方法都会考虑通过
      FactoryBean
      创建的bean,这也意味着
      FactoryBean
      会被初始化。为什么这里的三个方法不返回List?Map不光包含这些bean的实例,而且还包含bean的名字,而List只包含bean的实例。也就是说Map比List更加的通用。

    HierarchicalBeanFactory

    HierarchicalBeanFactory
    接口定义了
    BeanFactory
    之间的分层结构,
    ConfigurableBeanFactory
    中的
    setParentBeanFactory
    方法能设置父级的
    BeanFactory
    ,下面列出了
    HierarchicalBeanFactory
    中定义的方法:

    <pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important; color: rgb(49, 70, 89); font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

    Copy

    BeanFactory getParentBeanFactory(); // 获取父级的BeanFactory // 本地的工厂是否包含指定名字的bean boolean containsLocalBean(String name);
    </pre>

    这两个方法都比较直接明了,

    getParentBeanFactory
    方法用于获取父级
    BeanFactory
    containsLocalBean

    用于判断本地的工厂是否包含指定的bean,忽略在祖先工厂中定义的bean。

    MessageSource

    MessageSource
    主要用于消息的国际化,下面是该接口中的方法定义:

    <pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important; color: rgb(49, 70, 89); font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

    Copy

    // 获取消息 String getMessage(String code, Object[] args, String defaultMessage, Locale locale); String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException; String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;
    </pre>

    以上的三个方法都是用于获取消息的,第一个方法提供了默认消息,第二个接口如果没有获取到指定的消息会抛出异常。第三个接口中的

    MessageSourceResolvable
    参数是对代码、参数值、默认值的一个封装。

    ApplicationEventPublisher

    ApplicationEventPublisher
    接口封装了事件发布功能,提供Spring中事件的机制。接口中的方法定义如下:

    <pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important; color: rgb(49, 70, 89); font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

    Copy

    // 发布事件 void publishEvent(ApplicationEvent event); void publishEvent(Object event);
    </pre>

    第一个方法用于发布特定于应用程序事件。第二个方法能发布任意的事件,如果事件不是

    ApplicationEvent
    ,那么会被包裹成
    PayloadApplicationEvent
    事件。

    EnvironmentCapable

    EnvironmentCapable
    提供了访问
    Environment
    的能力,该接口只有一个方法:

    <pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important; color: rgb(49, 70, 89); font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

    Copy

    Environment getEnvironment();
    </pre>

    Environment
    表示当前正在运行的应用的环境变量,它分为两个部分:profiles和properties。它的父级接口
    PropertyResolver
    提供了property的访问能力。

    ResourceLoader和ResourcePatternResolver

    先来看一下

    ResourceLoader
    ,该接口是用来加载资源(例如类路径或者文件系统中的资源)的策略接口。该接口中的方法如下:

    <pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important; color: rgb(49, 70, 89); font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

    Copy

    Resource getResource(String location); // 根据指定的位置获取资源 ClassLoader getClassLoader(); // 获取该资源加载器所使用的类加载器
    </pre>

    该接口只有简单明了的两个方法,一个是用来获取指定位置的资源,一个用于获取资源加载器所使用的类加载器。

    Resource
    是从实际类型的底层资源(例如文件、类路径资源)进行抽象的资源描述符。先看下
    Resource
    中的方法:

    <pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important; color: rgb(49, 70, 89); font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

    Copy

    `boolean exists(); // 资源实际上是否存在
    boolean isReadable(); // 资源是否可读
    boolean isOpen(); // 检查资源是否为打开的流
    boolean isFile(); // 资源是否为文件系统上的一个文件

    URL getURL() throws IOException; // 获取url
    URI getURI() throws IOException; // 获取URI
    File getFile() throws IOException; // 获取文件

    ReadableByteChannel readableChannel() throws IOException; // 获取ReadableByteChannel

    long contentLength() throws IOException; // 资源的内容的长度
    long lastModified() throws IOException; // 资源的最后修改时间
    // 相对于当前的资源创建一个新的资源
    Resource createRelative(String relativePath) throws IOException;
    String getFilename(); // 获取资源的文件名
    String getDescription(); // 获取资源的描述信息`</pre>

    Resource
    的父级接口
    InputStreamSource
    ,可以简单的理解为
    InputStream
    的来源,只有一个方法,如下:

    <pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important; color: rgb(49, 70, 89); font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

    Copy

    InputStream getInputStream() throws IOException; // 获取输入流
    </pre>

    接下来在来看一下

    ResourcePatternResolver
    ,该接口用于解析一个位置模式(例如Ant风格的路径模式),该接口只有一个方法,如下:

    <pre class="java" style="margin: 10px 0px; padding: 0px; white-space: pre !important; overflow-wrap: break-word; position: relative !important; color: rgb(49, 70, 89); font-size: 15px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 300; letter-spacing: normal; orphans: 2; text-align: left; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); text-decoration-style: initial; text-decoration-color: initial;">

    Copy

    // 将给定的位置模式解析成资源对象 Resource[] getResources(String locationPattern) throws IOException;
    </pre>

    Spring IoC容器设计复盘

    假如让你设计IoC容器,你该如何去做呢?首先你应该要明确你设计的容器的功能和特性,然后根据这些功能和特性设计出合理的接口。下面只是粗略的分析一下:

    • IoC容器对bean的配置和管理,那么是不是需要设计一个接口来完成这些功能呢?(BeanFactory)
    • 既然需要这些元数据的配置,那么是不是需要设计一个接口来完成对一些配置文件的读取。(ResourceLoader和Resource)
    • 在IoC容器初始化、摧毁的时候,是不是可能要执行一些操作呢?那么是不是需要使用事件机制来完成呢?(ApplicationEventPublisher)
    • ....

    本文思维导图

     

  • 内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: