三大框架SSH成长路程(十七)

17 篇文章 0 订阅
12 篇文章 0 订阅

一步步重构容器实现Spring框架——从一个简单的容器开始(八)

从这篇博客开始,我们从一个简单的容器开始,一步步的重构,最后实现一个基本的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容器类,使得组件不能脱离容器独立存在,显然,这是一种“侵入式”的管理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值