week2 container and injection

一、container

1、概念

容器是一个Java 所编写的程序,原先必须自行编写程序以管理对象关系,现在容器都会自动帮您做好。

Container技术是直接将一个应用程序所需的相关程序代码、函式库、环境配置文件都打包起来建立沙盒执行环境,Container技术产生的环境就称为Container。

Container技术采取共享Host OS的作法,而不需在每一个Container内执行Guest OS,因此建立Container不需要等待操作系统开机时间,不用1分钟或几秒钟就可以启用,远比需要数分钟甚至数十分钟才能开启的传统虚拟机来的快。

常用容器

WebSphere, WebLogic, Resin, Tomcat

2、历史

早在1982年,Unix系统内建的chroot机制也是一种Container技术。其他如1998年的FreeBSD jails、2005年出现的Solaris Zones和OpenVZ,或像是Windows系统2004年就有的Sandboxie机制都属于在操作系统内建立孤立虚拟执行环境的作法,都可称为是Container的技术。直到2013年,dotCloud这家PaaS服务公司开源释出了一套将Container标准化的平台Docker,大受欢迎,所以,dotCloud决定以Docker为名成立新公司力推。

3、背景

1、containerd是一个行业标准的容器运行时,强调简单性,健壮性和可移植性。containerd可用作Linux和Windows的守护程序。

2、containerd管理其主机系统的完整容器生命周期,从图像传输和存储到容器执行和监督,再到低级存储,再到网络附件等。

4、特点

敏捷地应用创建和部署,增加了容器镜像创建的效率; 

  持续开发,集成和部署,通过快速的回滚操作提供可靠容器镜像的创建和部署;

  开发和运行相分离,在build或者release 的阶段使应用和基础设施解耦;

  开发,测试和生产环境的持续;  

  云和操作系统版本的可移植性,可以运行在 Ubuntu, RHEL, CoreOS, on-prem, Google Container Engine和任何其它的运行环境中;

  提升了虚拟化的层次,从虚拟硬件上运行操作系统的抽象到操作系统中应用逻辑资源的虚拟。

5、发展趋向

截至今天,业界有一个重要的趋势,即从VM迁移到容器以部署软件应用程序。其主要原因是与VM相比,容器提供的灵活性和低成本。谷歌多年来一直使用容器技术与Borg和Omega容器集群管理平台大规模运行Google应用程序。更重要的是,Google通过实施cgroup和参与libcontainer项目为容器空间做出了贡献。在过去几年中,Google可能已经在使用容器的性能,资源利用率和整体效率方面获得了巨大的收益。最近,微软没有在Windows平台上进行操作系统级虚拟化,立即采取措施在Windows Server上实现对容器的本机支持。

在生产环境中,Docker、Rocket和其他容器平台不能在单个主机上运行,原因是它们暴露于单个故障点。当一个容器集合在单个主机上运行时,如果主机失败,在该主机上运行的所有容器也将失败。为了避免这种情况,需要使用容器主机集群。解决这个问题的第一个最开放源码的容器集群管理平台之一是Apache Mesos。它最初是作为一个研究项目在加州大学伯克利分校开发的,后来在2012年左右转移到了阿帕奇(Apache)。Google采取了类似的步骤来实现一个先进的、开放源码的容器集群管理系统,名为Kubernetes。Docker还启动了一个名为Docker Swarm的解决方案。今天,这些解决方案还处于非常早期的阶段,可能需要几个月才能完成全部功能集,并在生产环境中广泛应用。

微型服务是另一项突破性的技术,而不是一种使用容器进行部署的软件体系结构。微服务是一个Web服务的轻量级实现,与标准Web服务相比,它的启动速度非常快。这是通过在一个服务中打包一个功能单元并将其嵌入到一个轻量级的Web服务器二进制文件中来实现的。

通过考虑上述事实,我们可以预测,在未来几年内,容器可能会占用虚拟机,有时可能会完全取代它们。去年,我与一些企业合作,在POC层面实施基于容器的解决方案。很少有人想接受挑战并将其投入生产。随着容器集群管理系统变得更加成熟,这可能会很快发生变化

二、injection(详细例子查看:https://www.cnblogs.com/ihuangjianxin/p/9394219.html)

1、概念

Java EE提供了注入机制,使您的对象能够获取对资源和其他依赖项的引用,而无需直接实例化它们。通过使用将字段标记为注入点的注释之一来装饰字段或方法,可以在类中声明所需的资源和其他依赖项。然后容器在运行时提供所需的实例。注入简化了代码并将其与依赖项的实现分离。

注入(Injection)的用处:

  依赖注入:

    控制反转用于解耦,解的究竟是谁和谁的耦?这是我在最初了解依赖注入时候产生的第一个问题。

资源注入:

 

    通过资源注入,您可以将JNDI名称空间中可用的任何资源注入任何容器管理的对象,例如servlet,企业bean或托管bean。例如,您可以使用资源注入来注入JNDI名称空间中可用的数据源,连接器或自定义资源。用于引用注入实例的类型通常是一个接口,它将您的代码与资源的实现分离。

class A {
    public function __construct() {
        // 这种实例化写法, A类的内部,依赖了B类 需要解耦
        $this->b = new B();
    }
    public function say(){
        $this->b->talk();
    }
}

class B{
    public function __construct() {
    }
    public function talk(){
        echo __METHOD__;
    }
}

$a = new A;
$a->say();

A类依赖B类,耦合较重。

 

  换一种写法:

class A {
    public function __construct(B $b) {// B的实例化,放在客户端,当作构造参数传递过来
        $this->b = $b;
    }
    public function say(){
        $this->b->talk();
    }
}

class B{
    public function __construct() {
    }
    public function talk(){
        echo __METHOD__;
    }
}

$b = new B;// 在客户端实例化B
$a = new A($b);// 构造器中传递
$a->say();

这个代码,就相当于实例化B的步骤放在了A类的外部,从而实现解耦。这就是依赖注入的一种实现方式。

 

 

Laravel框架中,通过这种依赖注入的方式,再配合反射功能,实现功能。

比如在Laravel的容器类,Container.php(vendor/laravel/framework/src/illuminate/Container/Container.php)中

利用反射,实例化注入的类。

/**
 *
 * 依赖注入的思想,把外部依赖的类放在构造函数的参数里
 *
 * Laravel框架根据反射 搞定依赖
 */
class Test{
    public function __construct(Para $p1, Parb $p2) {
        echo $p1->getInfo()," ",$p2->getInfo()," ";
    }
    function say(){
        echo __CLASS__;
        return;
    }
}
/**
 * Class Para
 * 参数A
 */
class Para {
    function getInfo() {
        echo __CLASS__;
    }
}
/**
 * Class Parb
 * 参数B
 */
class Parb {
    function getInfo(){
        echo __CLASS__;
    }
}

$obj = new Test(new Para(), new Parb());
// ===================================================
$reflector = new ReflectionClass($obj);// 对象 反射其类信息
$constructor = $reflector->getConstructor();
$dependencies = $constructor->getParameters();// 获取构造器下的参数信息
$parArr = array();
foreach ($dependencies as $depend){
    // $depend->getClass()->name 获取类名称 构造器参数是类
    $parArr[] = new ($depend->getClass()->name)();
}
$refNew = $reflector->newInstanceArgs($parArr);// Test 对象
$refNew->say();

代码中,获取$obj反射后的类信息,再取其构造器中的依赖类,实例化这些依赖类,再传入Test类中。  

这就是Laravel容器中实现的依赖注入和反射应用。

 

下边的代码有助于理解Laravel框架下的容器Container概念。参考自文章:https://www.insp.top/article/learn-laravel-container

<?php

interface SuperModuleInterface{
    public function activate(array $target);
}
class Superman
{
    protected $module;
    /**
     * Superman constructor.
     * @param SuperModuleInterface $module
     * 通过构造器 注入依赖
     */
    public function __construct(SuperModuleInterface $module)
    {
        $this->module = $module;
    }
    public function show(array $target){
        $this->module->activate($target);
    }
}
class PowerA implements SuperModuleInterface
{
    public function activate(array $target)
    {
        echo '<pre>'. __METHOD__;
        print_r(func_get_args());
    }
}
class PowerB implements SuperModuleInterface
{
    public function activate(array $target)
    {
        echo '<pre>'. __METHOD__;
        print_r(func_get_args());
    }
}
 
class Container
{
    protected $binds;
    protected $instances;
    /**
     * @param $abstract
     * @param $concrete
     * 把代词 绑定到容器里,为后续make
     */
    public function bind($abstract, $concrete)
    {
        if ($concrete instanceof Closure) {
            $this->binds[$abstract] = $concrete;
        } else {
            $this->instances[$abstract] = $concrete;
        }
    }
    /**
     * @param $abstract
     * @param array $parameters
     * @return mixed
     * 创建对象
     */
    public function make($abstract, $parameters = [])
    {
        if (isset($this->instances[$abstract])) {
            return $this->instances[$abstract];
        }
        // 把容器对象$this,放到参数数组第一个元素。为call_user_func_array使用
        array_unshift($parameters, $this);
       
        // 这里$this->binds[$abstract] 绑定的闭包函数, 执行函数参数是$parameters
        return call_user_func_array($this->binds[$abstract], $parameters);
    }
}

// 创建一个容器(后面称作超级工厂)
$container = new Container;

// 向该 超级工厂添加超能力模组的生产脚本
$container->bind('powerA', function($container) {
    return new PowerA;
});
// 同上
$container->bind('powerB', function($container) {
    return new PowerB;
});

// 向该 超级工厂添加超人的生产脚本
$container->bind('superman', function($container, $moduleName) {
    return new Superman($container->make($moduleName));
});
 
echo "<pre>";
// 开始启动生产
$superman_1 = $container->make('superman', ['powerA']);
$superman_1->show(['a' => 1]);
$superman_2 = $container->make('superman', ['powerB']);
$superman_2->show(['b' => 1]);
原文地址:https://www.cnblogs.com/EST-woah/p/10497878.html