• 【SSH进阶之路】一步步重构容器实现Spring框架——解决容器对组件的“侵入式”管理的两种方案--主动查找和控制反转(九)


    目录

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

      

           对于IOC的原理,我们曾经写过一篇博文,【SSH进阶之路】Spring的IOC逐层深入——为什么要使用IOC[实例讲

    解](二),对比学习可以对同一个问题理解的更加深刻。

           上篇博文【SSH进阶之路】一步步重构容器实现Spring框架——从一个简单的容器开始(八),我们为了去掉接口

    对具体实现的依赖关系,封装了一个特别简陋的容器,最后给大家抛出了一个问题:如何让组件不再依赖容器?这篇

    博文主要是通过两种解决方案来解决这个问题,最后对比各自的优缺点。


    服务定位器


           解决方案之一就是使用服务定位器(Service Locator),我们也可以叫主动查找。服务定位器用来封装复杂的查

    找逻辑,同时对外开放简单的查找方法,所有组件都可以将查找请求委派给服务定位器。

           服务定位器可是一个简单的类,也可以是一种复杂的机制,如JNDI。不同的容器有着不同的查找机制。

    下面是一个简单的服务定位器:

    public class ServiceLocator {
    	
    	static{
    		//该类加载的时候执行一次
    		Container.init();
    	}
    	public static Object getDao(){
    		return Container.getComponent("dao4Mysql");
    //		return Container.getComponent("dao4Oracle");
    	}
    }
    修改ServiceImpl的查找逻辑:

    import com.tgb.container.ServiceLocator;
    import com.tgb.container.dao.Dao;
    import com.tgb.container.service.Service;
    
    public class ServiceImpl implements Service {
    	// 从服务器定位器查找所需的接口
    	private Dao dao = (Dao) ServiceLocator.getDao();;  
    	
    	@Override
    	public void serviceMethod() {
    		dao.daoMethod();
    	}
    
    }
    
    UML类图:

            

            原先由ServiceImpl到Container的依赖线上添加了ServiceLocator,组件不再直接依赖于容器,实现了“非侵入

    式”管理。


    控制反转(IoC)


           解决方案之二就是使用控制反转,我们将控制权交给容器,在运行期才由容器决定将具体的实现动态的“注入”到

    调用类的对象中。

           Ioc是一种通用的设计原则,DI(依赖注入)则是具体的设计模式。依赖注入有三种方式,我们使用的是Setter注入。


    修改Service接口:

    import com.tgb.container.dao.Dao;
    
    
    public interface Service {
    	//增加注入接口的方法
    	public void setDao(Dao dao);
    	public void serviceMethod();
    }
    修改ServiceImpl:

    import com.tgb.container.dao.Dao;
    import com.tgb.container.service.Service;
    
    public class ServiceImpl implements Service {
    	private Dao dao;  
    	//依赖注入
    	public void setDao(Dao dao) {
    		this.dao= dao;
    	}
    	
    	@Override
    	public void serviceMethod() {
    		dao.daoMethod();
    	}
    }
    修改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 {
    	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);
    			
    			//容器维护依赖关系
    			service.setDao(dao4Mysql);
    		}
    	}
    
    	/**
    	 * 查找组件
    	 * 
    	 * @param id
    	 * @return
    	 */
    	public static Object getComponent(String id) {
    		return components.get(id);
    	}
    }
    UML类图:

           

           由ServiceImpl到Container的依赖线可以直接抹掉了!

           Setter注入易于使用,但是会有安全问题。第一次注入之后,有可能再一次调用setter方法,改变了原有的依赖。

    这种对依赖的无意修改会带来无法预料的后果。所以需要有安全检查机制。


    对比


           解决组件不再依赖容器,我们使用了两种方案:服务定位器和控制反转。

           1、使用服务定位器查找组件,这是一种主动查找的行为。这种查找有一个缺点:组件需要知道如何查找资源。组件和容器依赖变成了组件和服务定位器的依赖。

           2、然后,我们使用了控制反转,这是一种被动查找的行为。容器主动将资源推送给组件,组件则以一种合适的方式来接受资源。反转资源获取方向,这就是大名鼎鼎的Ioc(控制反转)。


           从类图中我们可以发现,容器需要知道各个组件,容器和组件的耦合度还是很高的,下篇博文【SSH进阶之路】 

    一步步重构容器实现Spring框架——配置文件+反射实现IoC容器(十),我们利用配置文件+反射进一步降低耦合度。

      

          源码下载


  • 相关阅读:
    advisor调优工具优化sql(基于sql_id)
    关于等待事件cursor: pin S
    队列等待之enq: TX
    HTML5+CSS3从入门到精通 中文pdf完整版[229MB] 下载
    unity 控制透明度
    unity 限制模型移动的边界
    unity监测按下键的键值并输出+unity键值
    unity EventTrigger与模型
    wpf 获取桌面上的鼠标位置
    unity 代码更换ugui中image的关联素材
  • 原文地址:https://www.cnblogs.com/ainima/p/6330966.html
Copyright © 2020-2023  润新知