• 【SSH进阶之路】一步步重构容器实现Spring框架——从一个简单的容器开始(八)


    目录

           【SSH进阶之路】一步步重构容器实现Spring框架——从一个简单的容器开始(八)

           【SSH进阶之路】一步步重构容器实现Spring框架——解决容器对组件的“侵入式”管理的两种方案--主动查找和控制反转(九)已更新
           【SSH进阶之路】一步步重构容器实现Spring框架——配置文件+反射实现IoC容器(十)更新
           【SSH进阶之路】一步步重构容器实现Spring框架——彻底封装,实现简单灵活的Spring框架(十一)已更新

      

           最近一直在和容器打交道,甚至前面的博文,我们也介绍了Spring的IoC的原理以及源码,但是回头看看,duang~ duang~的,还是深了,不够通俗易懂,不够深入浅出。由于以上原因吧,从这篇博客开始,我们从一个简单的容器开始,一步步的重构,最后实现一个基本的Spring框架的雏形,为了帮助我们更加深入的理解Spring的IoC的原理和源码。

     

    容器

      

          相信大家对容器并不陌生,它是生活中非常常见的物品,容器用来包装和装载物品的贮存器(如箱、罐、坛等等),但是在编程中什么容器呢?我们先看一下百科的解释:

    ---------------------------------------------------------------------------------------------------------------------------------------------------------

            容器可以管理对象的生命周期、对象与对象之间的依赖关系,您可以使用一个配置文件(通常是XML),在上面定义好对象的名称、如何产生(Prototype 方式或Singleton 方式)、哪个对象产生之后必须设定成为某个对象的属性等,在启动容器之后,所有的对象都可以直接取用,不用编写任何一行程序代码来产生对象,或是建立对象与对象之间的依赖关系。

    ---------------------------------------------------------------------------------------------------------------------------------------------------------

           看见上面的解释,第一感觉就是什么玩意?说白了,容器就是一个专门用来管理对象的模块。它负责创建对象,管理对象的依赖关系,管理对象的生命周期等等,类似这样的模块就叫容器。

           运行在容器中的对象也称为组件,它们必须遵循容器定义的规范。

      

    普通实现

      

           我们理解了容器之后,下面我们从一个简单的实例开始。先看一下代码:

    Service层:

    public interface Service {
    	public void serviceMethod();
    }
    import com.tgb.container.dao.Dao;
    import com.tgb.container.dao.impl.Dao4MySqlImpl;
    import com.tgb.container.service.Service;
    
    public class ServiceImpl implements Service {
    	//实例化Dao实现
    	private Dao dao = new Dao4MySqlImpl();  
    
    	@Override
    	public void serviceMethod() {
    		//调用Dao实现的方法
    		dao.daoMethod();
    	}
    }
    Dao层:

    public interface Dao {
    	public void daoMethod();
    }
    import com.tgb.container.dao.Dao;
    
    public class Dao4MySqlImpl implements Dao {
    	public void daoMethod(){
    		System.out.println("Dao4MySqlImpl.daoMethod()");
    		
    	}
    }

    import com.tgb.container.dao.Dao;
    
    public class Dao4OracleImpl implements Dao {
    	public void daoMethod(){
    		System.out.println("Dao4OracleImpl.daoMethod()");
    		
    	}
    		
    }

    客户端:

    import com.tgb.container.service.Service;
    import com.tgb.container.service.impl.ServiceImpl;
    
    public class Client {
    	public static void main(String[] args) {
    		//实例化Service实现
    		Service service = new ServiceImpl();
    		//调用Service实现的方法
    		service.serviceMethod();
    	}
    }

      

    这段代码的运行结果,大家一眼就能看出来,如下:

      

          Dao4MySqlImpl.daoMethod()

      

    UML类图如下:

               

           从上图我们可以发现,ServiceImpl不仅依赖Dao层接口,而且还依赖Dao层实现,显然违背了面向对象的基本设计原则,依赖倒转原则:抽象不应该依赖细节,细节应该依赖与抽象,说白了,就是针对接口编程,不要对实现编程。

       

    借助容器

      

            下面我们使用容器来将依赖实现的关系去掉。

    Container类:

    import java.util.HashMap;
    import java.util.Map;
    
    import com.tgb.container.dao.Dao;
    import com.tgb.container.dao.impl.Dao4MySqlImpl;
    import com.tgb.container.service.Service;
    import com.tgb.container.service.impl.ServiceImpl;
    
    public class Container {
    	//定义一个map结构的对象
    	private static Map<String, Object> components;
    
    	private Container() {
    	}
    
    	/**
    	 * 初始化容器
    	 */
    	public static synchronized void init() {
    		if (components == null) {
    			components = new HashMap<String, Object>();
    			//写一个读配置文件的类,根据读取的配置文件,反射对应的类
    			//反射好类后进行 依赖管理,往对应的属性上注入相应的类
    			//客户端创建新类的时候把容器创建好的类付给新类
    			
    			Dao dao4Mysql = new Dao4MySqlImpl();
    			components.put("dao4Mysql", dao4Mysql);
    			
    			Service service = new ServiceImpl();  
    			components.put("service", service);
    			
    		}
    	}
    
    	/**
    	 * 查找组件
    	 * 
    	 * @param id
    	 * @return
    	 */
    	public static Object getComponent(String id) {
    		return components.get(id);
    	}
    
    }
    修改ServiceImpl类:

    import com.tgb.container.Container;
    import com.tgb.container.dao.Dao;
    import com.tgb.container.service.Service;
    
    public class ServiceImpl implements Service {
    	//从容器查找响应的对象
    	private Dao dao = (Dao) Container.getComponent("dao4Mysql");  
    
    	@Override
    	public void serviceMethod() {
    		dao.daoMethod();
    	}
    }

    客户端:

    import com.tgb.container.Container;
    import com.tgb.container.service.Service;
    
    public class Client {
    	public static void main(String[] args) {
    		//容器初始化,这个可以用filter完成,只需在整个项目中初始化一次
    		Container.init();
    		
    		//从容器中查找接口
    		Service service =(Service)Container.getComponent("service");
    		//调用Service实现的方法
    		service.serviceMethod();
    	}
    }

    此时的UML类图如下:

            
            对比两张类图,我们可以发现,容器给我们带来了优点,同时也带来了缺点。

    优点:

           此时的Service层不再依赖Dao层实现,而把这种对实现的依赖交给了容器。

    缺点:

            但是我们却发现,ServiceImpl依赖了Container容器类,使得组件不能脱离容器独立存在,显然,这是一种“侵入式”的管理。

             如何让组件不依赖容器,见博客《【SSH进阶之路】一步步重构容器实现Spring框架——解决容器对组件的“侵入式”管理的两种方案--主动查找和控制反转(九)》。


             源码下载

            


  • 相关阅读:
    凡人修仙登录页面
    proxysql高可用~ keepalived+proxysql
    proxysql 系列 ~ 高可用架构
    mysql 案例 ~timeout相关问题与错误信息
    mysql 案例 ~ mysql字符集与大小写详解
    mysql案例~非常规操作汇总
    mysql原理~创建用户的那些事情
    mysql 案例 ~ 表空间迁移数据与数据导入
    开源统计数据库~行与列的讨论
    mysql 原理 ~ LRU 算法与buffer_pool
  • 原文地址:https://www.cnblogs.com/ainima/p/6330967.html
Copyright © 2020-2023  润新知