Spring IOC原理解析与自定义IOC实例讲解

目录

一、IOC综合介绍

1、总结性介绍

2、使用技术的原理介绍

 3、IOC的通俗讲解

4、 使用IOC框架应该注意的点

 二、自定义IOC的实现(反射+工厂模式+properties配置文件)

1、需要被注入的对象AccountDao

2、properties配置文件resource下面

 3、自定义MyBeanFactory生成对象

4、模拟需要对象注入时:


一、IOC综合介绍

1、总结性介绍

控制反转(Inversion of Control,缩写为IOC):把创建对象的权利交给框架,是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。

IOC的一个重点是在系统运行中,通过依赖注入动态的向某个对象提供它所需要的其他对象。它的实现原理是工厂模式+反射+xml解析或者注解解析。

大致过程简介:
    1、读取配置文件
    2、遍历处理配置文件,得到beanPath(对象的全路径名)。
    3、通过反射获取到对象,并存入bean容器。
    4、当需要某个对象的时候,就去调用getBean(String beanName)注入对象。

2、使用技术的原理介绍

 对于以下技术,会使用即可明白本文所写内容

  1.  java的反射机制 
  2. 设计模式——工厂模式
  3. 设计模式——代理模式

 3、IOC的通俗讲解

首先想说说IoC(Inversion of Control,控制倒转)。这是spring的核心,贯穿始终。所谓IoC,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系。这是什么意思呢,举个简单的例子,我们是如何找女朋友的?常见的情况是,我们到处去看哪里有长得漂亮身材又好的mm,然后打听她们的兴趣爱好、qq号、电话号、ip号、iq号………,想办法认识她们,投其所好送其所要,然后嘿嘿……这个过程是复杂深奥的,我们必须自己设计和面对每个环节。传统的程序开发也是如此,在一个对象中,如果要使用另外的对象,就必须得到它(自己new一个,或者从JNDI中查询一个),使用完之后还要将对象销毁(比如Connection等),对象始终会和其他的接口或类藕合起来。

  那么IoC是如何做的呢?有点像通过婚介找女朋友,在我和女朋友之间引入了一个第三者:婚姻介绍所。婚介管理了很多男男女女的资料,我可以向婚介提出一个列表,告诉它我想找个什么样的女朋友,比如长得像李嘉欣,身材像林熙雷,唱歌像周杰伦,速度像卡洛斯,技术像齐达内之类的,然后婚介就会按照我们的要求,提供一个mm,我们只需要去和她谈恋爱、结婚就行了。简单明了,如果婚介给我们的人选不符合要求,我们就会抛出异常。整个过程不再由我自己控制,而是有婚介这样一个类似容器的机构来控制。Spring所倡导的开发方式就是如此,所有的类都会在spring容器中登记,告诉spring你是个什么东西,你需要什么东西,然后spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由 spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。如果你还不明白的话,我决定放弃。

IoC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的。比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。A需要依赖 Connection才能正常运行,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的。那么DI是如何实现的呢? Java 1.3之后一个重要特征是反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的。

该处内容来自:
作者:超级谷歌     来源:CSDN 原文:https://blog.csdn.net/it_man/article/details/4402245

4、 使用IOC框架应该注意的点

1、由于IOC容器生成对象是通过反射方式,在运行效率上有一定的损耗。如果你要追求运行效率的话,就必须对此进行权衡。

2、具体到IOC框架产品(比如Spring)来讲,需要进行大量的配制工作,比较繁琐,对于一些小的项目而言,客观上也可能加大一些工作成本。

3、IOC框架产品本身的成熟度需要进行评估,如果引入一个不成熟的IOC框架产品,那么会影响到整个项目,所以这也是一个隐性的风险。

        我们大体可以得出这样的结论:一些工作量不大的项目或者产品,不太适合使用IOC框架产品。另外,如果团队成员的知识能力欠缺,对于IOC框架产品缺乏深入的理解,也不要贸然引入。最后,特别强调运行效率的项目或者产品,也不太适合引入IOC框架产品,像WEB2.0网站就是这种情况。

 二、自定义IOC的实现(反射+工厂模式+properties配置文件)

1、需要被注入的对象AccountDao

package test.myIoc;

public class AccountDao {
    //提供一个方法,方便测试显示
    void show(){
        System.out.println("accoutDao注入成功");
    }
}

2、properties配置文件resource下面

accountDao=test.myIoc.AccountDao

 3、自定义MyBeanFactory生成对象

请详细阅读该代码的注释

package test.myIoc;

import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * 创建Bean对象
 *  第一步:定义一个配置文件 来配置我们dao
 *      key(唯一标识)=value(全限定名)
 *  第二步:通过读取配置文件,反射生成对象
 *
 */
public class MyBeanFactory {

    private static Properties prop = new Properties();
    private static Map<String,Object> beans ;
    static{
        try{
            InputStream in = MyBeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
            //1、加载配置文件
            prop.load(in);
            //2、初始化容器实例
            beans = new HashMap<String,Object>();
            //3、遍历枚举
            Enumeration<Object> keys = prop.keys();
            //遍历key
            while (keys.hasMoreElements()){
                //取出key
                String key = keys.nextElement().toString();
                //4、根据key获取value
                String beanPath = prop.getProperty(key);
                //5、反射创建对象
                Object o = Class.forName(beanPath).newInstance();
                //6、存入容器
                beans.put(key,o );
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     *对象的创建时机分两种:
     * ApplicationContext:只要一读取配置文件,默认情况下就会创建对象。
     * BeanFactory:什么使用什么时候创建对象。
     */
    //方式1:7、需要对象时,注入
    public static <T> T getBean(String beanName){
        return (T) beans.get(beanName);
    }

    //方式2:7、需要对象时,注入
//    public static <T> T getBean(String beanName){
//        Object o = null;
//        try{
//            String beanPath = prop.getProperty(beanName);
//            o = Class.forName(beanPath).newInstance();
//        }catch (Exception e){
//            e.printStackTrace();
//        }
//        return (T) o;
//    }

}

4、模拟需要对象注入时:

package test.myIoc;

public class Test {
    public static void main(String[] args) {
        AccountDao dao = (AccountDao)MyBeanFactory.getBean("accountDao");
        System.out.println(dao);
        dao.show();
    }
}

结果展示:

test.myIoc.AccountDao@13221655
accoutDao注入成功

 到这里,一个简单版的IOC就实现了,我相信看到这里大家对于Spring IOC的实现原理应该是有一个简单的了解了的。

(关于使用工厂模式去实现IOC,大家可参考博文:https://blog.csdn.net/fuzhongmin05/article/details/61614873

读取配置文件,生成对象,存入集合的详细过程,可参考:https://blog.csdn.net/it_man/article/details/4402245

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值