首页 > 其他分享 >《Spring揭秘》-第三章- 学习记录

《Spring揭秘》-第三章- 学习记录

时间:2023-04-13 23:23:20浏览次数:41  
标签:依赖 第三章 Service 对象 Spring NewsProvider Provider IoC 揭秘

掌管大局的IoC Service Provider

虽然业务对象可以通过IoC方式声明相应的依赖,但是最终仍然需要通过某种角色或者服务将这些相互依赖的对象绑定到一起,而IoC Service Provider就对应IoC场景中的这一角色。

IoC Service Provider在这里是一个抽象出来的概念,它可以代指任何将IoC场景中的业务对象绑定到一起的实现方式。Spring的IoC容器就是一个提供依赖注入服务的IoC Service Provider

1、IoC Service Provider的职责

IoC Service Provider 的职责相对简单,主要有:业务对象的构建管理业务对象间的依赖绑定

  • 业务对象的构建管理。在IoC场景中,业务对象无需关系所依赖的对象如何构建如何取得,所依赖对象的构建逻辑将由IoC Service Provider负责,以免这部分逻辑污染业务对象的实现。
  • 业务对象间的依赖绑定。IoC Service Provider通过结合之前构建和管理的所有业务对象,以及各个业务对象之间可以识别的依赖关系,将这些对象所依赖的对象注入绑定,从而保证每个业务对象在使用的时候,可以处于就绪状态。

2、运筹帷幄的秘密---IoC Service Provider如何管理对象间的依赖关系

对于为被注入对象提供依赖注入的IoC Service Provider来说,它需要知道自己所管理和掌握的被注入对象和依赖对象之间的对应关系。同时它也需要寻求其他方式来记录诸多对象之前的对应关系。比如:

  • 可以通过最基本的文本文件来记录对象和其依赖对象之间的对应关系;
  • 可以通过描述性较强的XML文件格式来记录对应信息;
  • 可以通过编写代码的方式来注册这些对应信息;

实际情况下,当前流行的IoC Service Provider产品使用的注册对象管理信息的方式主要有一下几种。

2.1 直接编码方式

当前大部分的IoC容器都应该支持直接编码方式,比如PicoContainer、Spring、Avalon等。在容器启动之前,我们就可以通过程序编码的方式将被注入对象和依赖对象注册到容器中,并明确他们相互之间的依赖注入关系。示例伪代码如下

// 直接编码方式管理对象间的依赖注入关系
IoContainer container = ...;
container.register(NewsProvider.class, new NewsProvider());
container.register(INewsListener.class, new DowJonesNewsListener());
..
NewsProvider newsProvider = (NewsProvider) container.get(NewsProvider.class);
newsProvider.getAndPersistNews();

通过为相应的类指定对应的具体示例,可以告知IoC容器,当我们需要这种类型的对象实例时,请将容器中注册的、对应的那个具体实例返回给我们。

当通过接口注入时,道理上是一样的,只不过除了注册相应对象,还要将“注入标志接口”与相应的依赖对象绑定一下,才能让容器最终知道是一个什么样的对象关系,示例如下

// 直接编码方式管理基于接口注入的依赖注入关系
IoContainer container = ...;
container.register(NewsProvider.class, new NewsProvider());
container.register(INewsListener.class, new DowJonesNewsListener());
..
container.bind(INewsListenerCallable.class, container.get(INewsListener.class));
...
NewsProvider newsProvider = (NewsProvider) container.get(NewsProvider.class);
newsProvider.getAndPersistNews();

通过bind方法将“被注入对象”(由INewsListenerCallable接口添加了标志---即实现了INewsListenerCallable接口的类)所依赖的对象,绑定为容器中注册过的INewsListener类型的对象实例。容器在返回NewsProvider对象实例之前,会根据这个绑定信息,将INewsListener注册到容器中的对象实例注入到“被注入对象”---NewsProvider中,并最终返回已经组装完毕的NewsProvider对象。

所以,通过程序编码让最终的IoC Service Provider(也就是各个IoC框架或者容器实现)得以知晓服务的“奥义”,应该是管理依赖绑定关系的最基本方式。

2.2 配置文件方式

这是一种较为普遍的依赖注入关系管理方式。像普通文本文件、properties文件、XML文件等,都可以成为管理依赖注入关系的载体。不过,最为常见的,还是通过XML文件来管理对象注册和对象间依赖关系,比如Spring IoC和在PicoContainer基础上扩展的NanoContaier,都是采用XML文件来管理和保存依赖注入信息的。相关的示例如下

<!--  通过Spring的配置方式来管理NewsProvider的依赖注入关系 -->
<bean id="newsProvider" class="..NewsProvider">
    <property name="newsListener">
		    <ref bean="djNewsListener"/>
    </property>
		<property name="newsPersister">
		    <ref bean="djNewsPersister"/>
		</property>
</bean>

<bean id="djNewsListener" class="..impl.DowJonesNewsListener"/>
<bean id="djNewsPersister" class="..impl.DowJonesNewsPersister"/>

最后,可以像如下代码,通过”newsProvider“这个名字,从容器中取得已经组装好的NewsProvider并直接使用。

// 从读取配置文件完成对象组装的容器中获取NewsProvider并使用
...
container.readConfigurationFiles(...);
NewsProvicer newsProvider = (NewsProvider)container.getBean("newsProvider");
newsProvider.getAndPersistNews();

2.3 元数据方式

这种方式的代表实现是Google Guice,这是Bob Lee在Java 5的注解和Generic的基础上开发的一套IoC框架。我们可以直接在类中使用元数据信息来标注各个对象之间的依赖关系,然后由Guice框架根据这些注解所提供的信息将这些对象组装后,交给客户端对象使用。示例如下

// 使用Guice的注解标注依赖关系后的NewsProvider定义
public class NewsProvider {
    private INewsListener newsListener;
    private INewsPersister newsPersister;
    @Inject
    public NewsProvider(INewsListener listener, INewsPersister persister) {
        this.newsListener= listener;
        this.newsPersister = persister;
    }
		...

通过@Inject注解,指明了需要IoC Service Provider通过构造方法注入方式,为NewsProvider注入其所依赖的对象。至于余下的依赖相关曦曦,在Guice中是由相应的Module来提供的,示例如下

// NewsProvider所使用的Moudle实现
public class NewsBindingModule extends AbstractModule {

    @Override
    protected void configure() {
        bind(INewsListener.class)
                .to(DowJonesNewsListener.class).in(Scopes.SINGLETON);
        bind(INewsPersister.class)
                .to(DowJonesNewsPersister.class).in(Scopes.SINGLETON);
    }

通过Module指定进一步的依赖注入相关信息之后,我们就可以直接从Guice哪里取得最终已经注入完毕,并可以直接使用的对象了。

// 从Guice获取并使用最终绑定完成的NewsProvider
Injector injector = Guice.createInjector(new NewsBindingModule());
NewsProvider newsProvider = injector.getInstance(NewsProvider.class);
newsProvider.getAndPersistNews();

当然,注解最终也要通过代码处理来确定最终的注入关系,从这点上来说,注解方式可以算作编码方式的一种特殊情况。

3、小结

本章对IoC Service Provider进行了介绍,讨论了IoC Service Provider的基本职责,以及它常用的几种依赖关系管理方式。

应该说,IoC Service Provider只是为了简化概念而提出的一个一般性的概念。后面的章节会深入了解一个特定的IoC Service Provider实现产品,即Srping提供的IoC容器。

标签:依赖,第三章,Service,对象,Spring,NewsProvider,Provider,IoC,揭秘
From: https://www.cnblogs.com/zc-01/p/17316937.html

相关文章

  • 《深入理解计算机系统第三版》第三章家庭作业参考答案
    简述最近看docker和k8s的底层实现原理,严重感觉自己对底层的知识了解不足,于是开始业余时间深入看一些底层书籍,就找了本据说是理解整个计算机体系的入门书-《深入理解计算机系统》.直接买的最新的第三版,从第三章开始看的,第二章接下来有心情再看(看了几眼全是如何手算进制间计算之类......
  • springcloud学习——网关
    1.网关的作用如图,微服务之间调用使用的feign帮我们发送请求。当用户需要访问微服务时,就需要网关来帮忙。网关主要实现三大作用:权限控制:网关作为微服务入口,需要校验用户是是否有请求资格,如果没有则进行拦截。路由和负载均衡:一切请求都必须先经过gateway,但网关不处理业务,而是根......
  • java 处理常量字符串过长 & springboot 项目读取 resouces 文件夹下的文件内容
    长字符串起因项目里面有一长串的加密字符串(最长的万多个字符),需要拼接作为参数发送给第三方。如果我们使用枚举定义的话,idea编译的时候就会出现编译报错Error:java:常量字符串过长解决想法网上还有一个说法,说是编译器问题,修改idea工具的编译为eclipse即可......
  • C++课本第三章例题
    3-2输入一个8位二进制数,将其转换为十进制数输出。1#include<iostream>2usingnamespacestd;3doublepower(doublex,intn);//函数的声明,double类型防止超出整型4intmain()5{6intnumber=0;7for(inti......
  • SpringBoot 自定义对象映射器的使用
    SpringBoot底层默认使用Jackson进行Java实体对象与Json之间的转换,有时转换的效果并不是我们所期望的,需要进行额外的处理工作,有经验的小伙伴们,肯定遇到过下面两种典型的情况:当对象的属性是日期类型时,转换成json后的结果并不是我们想要的效果,还需要我们额外进行显示格式......
  • Spring Boot实现分片上传、断点续传、大文件极速秒传-备忘
    文件上传是一个老生常谈的话题了,在文件相对比较小的情况下,可以直接把文件转化为字节流上传到服务器,但在文件比较大的情况下,用普通的方式进行上传,这可不是一个好的办法,毕竟很少有人会忍受,当文件上传到一半中断后,继续上传却只能重头开始上传,这种让人不爽的体验。那有没有比较好......
  • Spring IOC容器注解大全—基于Java的容器配置
    本节介绍了如何在你的Java代码中使用注解来配置Spring容器。它包括以下主题。基本概念:@Bean 和 @Configuration通过使用 AnnotationConfigApplicationContext 实例化Spring容器使用 @Bean 注解使用 @Configuration 注解构建基于Java的配置Bean定义配置PropertySource 抽象......
  • springboot学习之四(整和mybatis)
    springboot整和mybatis    1.mapper文件开发 2.纯注解开发    https://www.cnblogs.com/fps2tao/p/13821490.html ......
  • springboot学习之三(整个redis)
     springboot整合redis1.依赖<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>2.配置#Redis配置spring.r......
  • Springboot-HelloWorld
    1.引入依赖<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.3.4.RELEASE</version></parent><dependencies>......