厨师版Ioc及Ioc的模拟实现

  关于IOC:我们讲个故事吧!

有一个厨师,他在做一道菜的时候需要某种调味料(bean),可是他正好没有那瓶调味料(bean),这个时候他就必须去制作一瓶调味料(bean)出来。(这就像我们平时需要对象的时候一样:UserDao  userdao=new UserDaoImpl)这个时候厨师的工作就不得不跟制作调味料联系起来,这就是所谓的“耦合”。(耦合程度高通说来说就是,我没了你我活不了了。);

这个时候IOC里的控制反转出来了,它提出,开辟一个仓库(容器),里面放着各种各样的调味料(bean),当你需要某种调味料(bean)的时候只要给出调味料的名字(beanName)就可以直接去拿取,代码类似这样:(UserDao user=仓库.get("调味料名字"));这样你就可以直接拿到了调味料 (bean)而不用等到你没有的时候再去制作一瓶出来。这就是所谓的将控制权转移出来,它将生产调味料(bean)的工作直接让仓库(容器)来制作(生产);

接下来依赖注入出来了,它就更加地强大的了,它提出厨师只要有一个瓶子(private UserDao userdao),并且将瓶子盖打开(方法:setUserDao( UserDao userdao){this.userdao=userdao}即提供对于的set方法 )再给瓶子贴上一个标签注明要放什么材料(在xml文件中配置一下<property name="userdao",ref="xxbean"),那么这个时候你什么都不用做了,仓库(容器)会自动派人帮你将你所需的调味料(bean)放入到瓶子中 ;当你想换另一种调味料的时候只要将瓶子上的标签改成其他比如胡椒粉(这时要在xml文件中更改一下ref的bean就行了),依赖注入提高了代码的灵活性,你需要替换类的实现的时候,不需要去修改只要在xml配置文件里修改一下就行了;

总结一下我的总结:IOC的主要目的就是实现解耦!解耦!解耦!重要的事情说三遍.由厨师的列子来说就是.我是一个厨师我只做菜,我不做调味料~~我不是一个做调味料的,我不跟制作调味料有那么大的关系.   IOC的出现,厨师只要安心做好自己的事情(做菜),需要调味料直接去仓库拿取就行了!那么这样厨师跟调味料的制作之间的关系就分离开来了,这就是解耦!解耦!解耦!使两个东西的关系没那么紧密.

模拟IOC的实现,主要使用的技术是java的反射机制(模拟使用的是架构分为dao层,service层,controller层):

注:欢迎各位大佬的指点,小弟也在学习,说得不好多多包涵~

一.编写dao类,用于测试:

public interface IocDao {
    public void sayhello(); //一个用来测试的接口
}

二.编写dao的实现类:

public class IocDaoImpl implements IocDao {
    @Override
    public void sayhello() {
        // TODO Auto-generated method stub
        System.out.println("hello word");//实现我们的dao接口里的方法
    }

}

三.编写service类:

public interface IocDaoService {
    public void sayhello();//业务类接口,这里就跟dao一样
}

四.编写service的实现类:

public class IocDaoServiceImpl implements IocDaoService {
    private IocDao iocDao;   //创建一个接口.
    public IocDao getIocDao() {
        return iocDao;
    }
    //编写IocDao接口对应的set方法用于依赖注入
    //依赖注入的方式有三种:接口注入,构造方法注入,set注入;
    //此处为set注入
    public void setIocDao(IocDao iocDao) {
        this.iocDao = iocDao;
    }
    @Override
    public void sayhello() {
        // TODO Auto-generated method stub
        iocDao.sayhello();//调用接口方法
    }

}

五.编写bean.xml配置文件.(这里的i你可以看成是IocDaoImpl类,iocService看成IocDaoServiceImpl,iocDao这是IocDaoServiceImpl里的一个属性,这个属性传入的参数值为“i”);

<beans>
  <bean id="i" class="com.hck.dao.impl.IocDaoImpl"/>
  <bean id="iocService" class="com.hck.service.impl.IocDaoServiceImpl">
     <property name="iocDao" ref="i"></property>
  </bean>
</beans>

六.编写工厂接口.

//模拟ClassPathXmlApplicationContext实现的一个接口BeanFactory
public interface BeanFactory {
    public Object getBean(String beanName);
}

七.编写ClassPathXmlApplicationContext去读取配置文件,并且根据bean.xml里的配置对象去生成各种bean,完成其中的注入工作.(最重要的部分Ioc的实现原理),一字一句都有注释

//模拟ClassPathXmlApplicationContext去读取配置文件
public class ClassPathXmlApplicationContext implements BeanFactory {
    //定义map集合来存放bean.xml里的bean的id跟其对应的实例化对象
    //<bean id="i" class="com.hck.dao.impl.IocDaoImpl"/>
    //那么类似的存放bean.put("i",new IocDaoImpl());这样子.
    Map<String, Object> beans=new HashMap<String,Object>();
   public  ClassPathXmlApplicationContext(String xmlPath){
            try {
                //创建SAXBuilder对象解析文档
                SAXBuilder saxBuilder = new SAXBuilder();
                //解析build里的参数是一个文件路径.
                Document document = saxBuilder.build(xmlPath);
                //document.getRootElement().getChildren("bean")获取所有<bean>标签内容
                List elements = document.getRootElement().getChildren("bean");
                //遍历<bean>对象
                for (int i = 0; i < elements.size(); i++) {
                    //获取第一个<bean>标签elements.get(0);
                    Element element = (Element) elements.get(i);
                    //获取<bean>标签里的<id>属性,
                    //<bean id="i" class="com.hck.dao.impl.IocDaoImpl"/>
                    //即String beanName="i";
                    String beanName = element.getAttributeValue("id");
                    //同上String  clazz="com.hck.dao.impl.IocDaoImpl";
                    String clazz = element.getAttributeValue("class");
                    //加载类对象并且实例化.Object object=new IocDaoImpl();
                    Object object = Class.forName(clazz).newInstance();//object是IocDaoServiceImpl
                    //将他们添加在map集合里,后面可以根据beanName直接获取到实例化对象.
                    beans.put(beanName, object);
                    //遍历<bean>标签下的<property>字标签.
                    //第一个标签没有字标签所以直接跳过.已第二个为例子
                    //<bean id="iocService" class="com.hck.service.impl.IocDaoServiceImpl">
                    //<property name="iocDao" ref="i"></property></bean>
                    List elements2 = element.getChildren("property");
                    for (int j = 0; j < elements2.size(); j++) {
                        //此处我们将获得<property name="iocDao" ref="i"></property></bean>
                        Element element2 = (Element) elements2.get(j);
                        //相当于String propertyName="iocDao";
                        String propertyName = element2.getAttributeValue("name");
                        //相当于String refBean="i";
                        String refBean = element2.getAttributeValue("ref");
                        //相当于String propertyName="IocDao";
                        //目的是为了得到一个方法的名字setIocDao,用于反射调用
                        propertyName = propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
                        //这里的methodName="setIocDao";
                        String methodName = "set" + propertyName;
                        //获取Map集合里Key="i"的值;i对应的是IocDaoImpl的实例化对象
                        //相当于 Object object2 =IocDaoImpl;
                        Object object2 = beans.get(refBean);
                        //获取IocDaoServiceImpl方法里的setIocDao方法.
                        //第一个方法是方法名,第二个参数是方法的参数类型.
                        Method method = object.getClass().getDeclaredMethod(methodName,
                                object2.getClass().getInterfaces());
                        //调用方法,并传入参数,完成依赖注入.
                        method.invoke(object, object2);
                    }
                }
                //            String beanName=document.getElementById(id).attributes().get("class");
                //            Object object=Class.forName(beanName).newInstance();
                //            return object;
            } catch (Exception e) {
                e.printStackTrace();
                // TODO: handle exception
            }
   }
/* (non-Javadoc)
 * @see com.hck.ioc.BeanFactory#getBean()
 */
@Override
public Object getBean(String beanName) {
    // TODO Auto-generated method stub
    return beans.get(beanName);
}
}

八.编写测试类

public class Ioc {
   public static void main(String[] args) {
    ClassPathXmlApplicationContext applicationContext=new ClassPathXmlApplicationContext("src/bean.xml");
    IocDaoService ids=(IocDaoService)applicationContext.getBean("iocService");
    ids.sayhello();
}
}

九.显示结果:

到这里Ioc的模拟就结束了.觉得容易有用的朋友可以点击一下推荐或者点击一下关注。么么哒~~

时间: 2024-08-30 06:18:27

厨师版Ioc及Ioc的模拟实现的相关文章

Spring IOC和IOC容器

IOC的核心理念即是控制反转.将对依赖的控制从具体业务对象手中转交到平台或框架中,需要的时候再由平台或框架注入到具体业务对象中.可以说依赖注入是控制反转的实现方式. IOC的优点: 降低代码耦合度 减少重复代码和冗余对象 提升可测试性 IoC容器是Spring的核心模块,是抽象了对象管理.依赖关系管理的框架解决方案. 在Spring IoC容器的设计中,有两个主要的容器系列,一个是实现了BeanFactory接口的简单容器系列,这系列容器只实现了容器的最基本功能:另一个是ApplicationC

Spring IOC之IOC基础

学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的,今天和大家分享网上的一些技术大牛们对Spring框架的IOC的理解以及谈谈我对Spring Ioc的理解. 首先要分享的是Iteye的开涛这位技术牛人对Spring框架的IOC的理解,写得非常通俗易懂,以下内容全部来自原文,原文地址:http://jinnianshilongnian.iteye.com/bl

【Spring IoC】IoC介绍(一)

IoC(Inversion of Control)的职责:原先由程序员主动通过new实例化对象这个事情,现在交由Spring负责,即由IoC容器负责. Spring 容器是 Spring 框架的核心.容器将创建对象,把它们连接在一起,配置它们,并管理他们的整个生命周期从创建到销毁.Spring 容器使用依赖注入(DI)来管理组成一个应用程序的组件.这些对象被称为 Spring Beans. 通过阅读配置元数据提供的指令,容器知道对哪些对象进行实例化,配置和组装.配置元数据可以通过 XML,Jav

模拟服务容器Ioc

服务容器是一个用于管理类依赖和执行依赖注入的强大工具. 一个类要被容器所能够提取,必须要先注册至这个容器.既然称这个容器叫做服务容器,那么我们需要某个服务,就得先注册.绑定这个服务到容器,那么提供服务并绑定服务至容器的东西就是服务提供器(ServiceProvider). 依赖注入和控制反转是对同一件事情的不同描述,它们描述的角度不同.依赖注入是从应用程序的角度在描述,应用程序依赖容器创建并注入它所需要的外部资源.而控制反转是从容器的角度在描述,容器控制应用程序,由容器反向的向应用程序注入应用程

Spring系列之谈谈对Spring IOC的理解

学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IOC .DI这两个概念是模糊不清的,是很难理解的,今天和大家分享网上的一些技术大牛们对Spring框架的IOC的理解以及谈谈我对Spring Ioc的理解. 一.分享Iteye的开涛对Ioc的精彩讲解首先要分享的是Iteye的开涛这位技术牛人对Spring框架的IOC的理解,写得非常通俗易懂,以下内容全部来自原文 1.1.IoC是什么 Ioc—Inversi

好程序员Java干货分享Spring框架之IOC原理

好程序员Java干货分享Spring框架之IOC原理,前言:Spring框架是我们进行企业级开发的最常用框架,本章我们将了解Spring框架,并学习Spring的IOC特性以及IOC的实现原理:注解和反射. Spring框架简介 Spring是一种轻量级的控制反转(IOC)和面向切面编程(AOP)的容器框架,能够为企业级开发提供一站式服务. Spring的优点有 1.方便解耦,简化开发 通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度

spring基于注解的IOC(2)

spring第二天:spring基于注解的IOC以及IoC的案例1.spring中ioc的常用注解 用于创建对象的:Component.Controller.Service.Repository 用于注入数据的:Autowired.Qualifier.Resource.Value 用于改变作用范围的:Scope . 和生命周期相关:PreDestroy .PostConstruct 2.案例使用xml方式和注解方式实现单表的CRUD操作 持久层技术选择:dbutils3.改造基于注解的ioc案例

IOC小结

DIP:依赖倒置 IOC:控制反转 DI:依赖注入 反射的写法: 配置文件里: 第三方工厂里: 泛型实现 IOC容器最终版: 使用IOC容器  例如:autofac.unity等 依赖注入:构造函数注入.属性注入.方法注入(按此先后顺序注入) 推荐:构造函数注入(可以不用声明特性) 配置  配置文件: 原文地址:https://www.cnblogs.com/fl-1998/p/12699613.html

Spring核心技术之IoC和AOP

IOC: IoC,即控制反转,就是有容器控制程序之间的关系,而非传统实现中,由程序代码直接用new实现.控制权由应用代码中转到了外部容器,因此称作控制反转.IoC又称DI,依赖注入,所谓依赖注入,即组件之间的依赖关系由容器在运行期决定,也就是由容器动态的将某种依赖关系注入到组件之中(系统开机,USB设备加载,运行在计算机中的Win OS依赖USB设备进行数据存取,然后写入win文件访问组件) 在一个业务类中,如果要用到ClassA,是不是要new一个ClassA对象?这个就等于是业务类主动的去创