《Spring揭秘》 第3章 掌控大局的IoC Service Provider 笔记


          在第2章中我们可以通过接口注入,构造方法注入,setter方法注入方式去声明依赖关系,Ioc Service Provider 是用来将Ioc场景中的业务对象绑定到一起的实现方式。
它是一个抽象的概念,可以用代码实现,也可以是一组相关的类,同是还能是Ioc框架或者通用的Ioc容器。Ioc Service Provider 是用来提供对象间的依赖对象的,而Spring中的Ioc Service Provider 则是Spring的自带的Ioc容器,提供了依赖注入服务。
          我们不经要问那么Ioc Service Provider 的具体的职责是什么?Ioc Service Provider 是怎么实现提供服务,怎么去管理对象之间的依赖关系呢?
  •      Ioc  Service Provider 的具体的职责
                   1.依赖对象的构建管理:
                         比如我们被注入对象是ServiceImpl通过setter注入的方式可以直接获取到依赖对象IDao,建立依赖关系。而此时的IDao业务对象并不是由ServiceImple来构建的。Ioc Service Provider 的职责之一就是依赖对象的构建管理工作。将依赖对象的构建逻辑从客户端隔离,接触了相应的耦合。
                   2.  业务对象间的依赖绑定
                         业务对象之间的依赖绑定也是Ioc  Service Provider 的最重要的功能,它的最终使命。若是没有实现业务对象间的依赖绑定,无论业务对象怎么去呼唤去通知,也不会得到依赖对象的相应的响应,若是没有实现业务之间的依赖绑定,比如SeriviceImple需要依赖对象IDao,但是没有相应的依赖绑定,没有谁提供服务给你。好比去酒吧喝酒,你说你要啤酒但是服务员不在或者服务员压根不知道啤酒是什么,酒虽然有了,但是没有谁能够去提供给你喝。Ioc Service Provider 通过结合之前的构建和管理所有的业务对象,以及各个业务对象之间可以识别的依赖关系,将这些对象所依赖的对象注入绑定,从而保证每个业务对象在使用被注入对象时候,被注入的对象处于就绪状态。
         那么问题来了,Ioc Service Provider 到底是怎么管理对象之间的依赖关系,怎么实现的呢?
         在第2章的笔记中有记录,被注入对象可以通过3种注入方式去通知Ioc Service Provider 为其注入相应的依赖。但是问题是是否Ioc Service Provider 就能一定并且正确的注入呢?当时是不。
          好比我们去酒吧喝酒(比作被注入对象),此时服务员在(比作Ioc), 我们想要啤酒(依赖注入对象)。但是服务员此刻是个新人,并不知道啤酒放在哪里,你若要想喝啤酒,服务员必须知道啤酒和库存的关系。对于Ioc Service Provider  来说的话,同样的需要知道自己所管理和掌握的被注入对象与依赖注入对象之前的对应关系,才能准确无误的去为被注入对象提供注入服务, 那么Ioc Service Provider 就需要寻求一些能够记录被注入对象与依赖对象之间的关系。可以通过最基本的文本文件记录,或者通过描述性强的XML文档方式,或者语音或者图片。
          实际上,当前流行的Ioc  Service  Provider 使用的依赖绑定信息管理有以下方式
  •                直接编码方式:
                         当前的大部分的Ioc容器都是支持直接编码方式进行管理依赖绑定的,Spring就是其中之一。在容器启动之前我们就可以通过直接编码将被注入对象与依赖对象注册到容器中,并明确他们的依赖关系。如下伪代码。
          IocContainer container  =  ....
         container.register(ServiceImple.class,new ServiceImple());
         container.register(IDao1.class,new Dao1());
         container.register(IDao2.class,new Dao2());
         ....
         ServiceImpl serImpl = (ServiceImple)container.get(ServiceImple.class);
         ....
                     通过为相应的类指定具体的实例,可以告知Ioc容器,当我们需要这种类型对象时候,请将容器中注册的、对应的具体的实例给予我们。
                    若是通过接口注入方式注入的话,除了需要以上的的伪代码,还需要对于ServiceImple的需要实现的接口进行绑定相应的对象,才能让容器知道具体的依赖关系。
           IocContainer container  =  ....
         container.register(ServiceImple.class,new ServiceImple());
         container.register(IDao1.class,new Dao1());
         container.register(IDao2.class,new Dao2());
         Container.bind(IServiceImple,IDao1.class);
         Container.bind(IServiceImple,IDao2.class);
         ....
         ServiceImpl serImpl = (ServiceImple)container.get(ServiceImple.class);
         ...
     通过bind()方法,将被注入对象(通过实现接口方式)与依赖对象IDao1,IDao2进行绑定,容器在返回ServiceImple对象实例之前,根据绑定信息,将                  IDao1,IDao2注册到容器中的对象实例注入到被注入对象ServiceImpel中,并返回已经组装好的ServiceImple。
所以通过直接编码可以让Ioc Service Provider 得以管理业务对象之间的依赖绑定方式,这也是一种最基本的方式
  •            xml等配置文件方式
               Ioc 也可以通过xml,propertites等配置文件的方式来管理依赖注入关系。最常见的还是xml配置文件方式。配置文件如下:
                < bean  id  =  "dao1"   class =  "...dao.impl.Dao1 " >
       </ bean  >

       < bean  id  =  "dao2"   class =  "...dao.impl.Dao2 " >
       </ bean  >

       < bean  id  =  "serviceImpl"   class =  "...service.impl.ServiceImple " >
             < property  name  =  "dao1"   ref =  "dao1"   />
             < property  name  =  "dao2"   ref =  "dao2"   />
       </ bean  >
               当配置文件配置完成后,如下伪代码为怎样从容器中获取到被注入对象并使用:
              ...
           container.readConfigurationFiles( ...);
           ServiceImpl  serviceImpl  = (ServiceImpl)Container.getbean(  "serviceImpl" );
           ...
  •      元数据方式
                    元数据方式也是也是编码方式的一种特殊形式,通过注解方式去实现。通过注解方式所提供的信息,将这些对象组装后,交给被注入对象使用
                         private  IDao1  dao1 ;
              private  IDao2  dao2 ;
              public  IDao1 getDao1() {
                   return   dao1 ;
           }
              @Inject
              public   void  setDao1(IDao1  dao1 ) {
                   this .   dao1  =  dao1 ;
           }
              @Inject
              public  IDao2 getDao2() {
                   return   dao2 ;
           }
              public   void  setDao2(IDao2  dao2 ) {
                   this .   dao2  =  dao2 ;
           }    
       这里通过Inject,指明需要Ioc Service Provider 通过setter方式去注入,为ServiceImpl注入所依赖的对象。至于剩下的相关的信息,由相应的Module来提供,如下给出了ServiceImpl所使用的Module。
           public   class   ServiceBindingModule  extends  AbstractModule{       
              @Override
              protected   void  configure(){
                 bind(IDao1 . class   ),to( Dao1.  class ).in(Scope.SINGLETON);
                 bind(IDao2 . class   ).to(Dao1.   class ).in(Scope.SINGLETON )
                }
          }     
          通过Module指定进一步的依赖注入相关信息后,我们就可以直接从Guice那里取得最终的已经注入,并可以使用的对象
             Injector  injector  = Guice.createInjector(  new  ServiceBindingModule());
            ServiceImpl  serviceImpl  =  injector  .getInstance(ServiceImpl.  class );
            ...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值