• 为什么需要依赖注入?
    • 依赖注入与Service Locator
    • ServiceUser是组件,在编写者之外的环境内被使用,且使用者不能改变其源代码.
    • ServiceProvider是服务,其类似于ServiceUser,都要被其他应用使用,不同是ServiceProvider会被用于非本地环境,需要对应不同环境.
    • 普通的ServiceUser来负责直接创建所需Service实现的实例方法.拥有以下的局限
      • 在不同的环境下,ServiceProvider是千差万别的(数据库,临时文件,内存).
      • 所以,不能将ServiceUser作为组件发布(适应不了各种差异环境).
    • 为了将ServiceUser所在单元作为组件发布,必须满足以下的条件.
      • 将ServiceUser与具体的ServiceProvider_Imp解耦(解除编译时依赖).即不能出现new ServiceProvider_Imp()语句.
      • 在运行时,根据环境来为ServiceUser来动态地提供ServiceProvider的实现实例.
      • 总之,将ServiceUser和ServiceProvider之间的依赖,由编译时,推迟到运行时动态决定.
      • 即在运行时"注入"这种依赖,称为依赖注入(DI).
      • ServiceUser可以看做框架.其需要对外发布,被其他模块使用.
      • ServiceProvider可看做插件.其在不同的环境下有差别.
    • 依赖注入
      • 在编译时,使用IServiceProvider接口.在运行时,再将具体的实现类型绑定到ServiceUser上.
      • 从而实现了服务的使用者(框架)和服务的提供者(插件)的松耦合.
    • 加入一个Assembler(容器)来完成对框架单独发布所需的要求.
      •  依赖注入与Service Locator
  • 构造器DI
    • 构造器指的是ServiceUser的构造器,也就是在构造ServiceUser的实例时,才把具体的ServiceProvider_实现传递给它.
    •  1  class ServiceUser
       2     {
       3         IServiceProvider sp;
       4         ServiceUser(IServiceProver sp)
       5         {
       6             this.sp = sp;
       7         }
       8     }
       9 
      10     private MutablePicoContainer configureContainer() {
      11         MutablePicoContainer pico = new DefaultPicoContainer();
      12         //下面就是把ServiceProvider和ServiceUser都放入容器的过程,以后就由容器来提供ServiceUser的已完成依赖注入实例,
      13         //其中用到的实例参数和类型参数一般是从配置档中读取的,这里是个简单的写法。
      14         Parameter[] finderParams =  {new ConstantParameter("movies1.txt")};
      15         pico.registerComponentImplementation(IServiceProvider.class, ServiceProvider.class, finderParams);
      16         pico.registerComponentImplementation(ServiceUser.class);        
      17         //至此,容器里面装入了两个类型,其中没给出构造参数的那一个(ServiceUser)将依靠其在构造器中定义的传入参数类型,在容器中
      18         //进行查找,找到一个类型匹配项即可进行构造初始化。
      19         return pico; 
      20     }
      CtorDI

相关文章: