Spring Ioc 的实现方式

本文探讨了SpringIoC的概念及其实现方式,通过具体的应用场景,如数据库配置的灵活切换,展示了如何利用Spring的控制反转(IOC)和依赖注入(DI)特性,通过配置文件和工厂类实现实例化对象的动态选择,从而提高代码的灵活性和可维护性。

如何理解Spring Ioc:https://www.cnblogs.com/chenssy/p/9576769.html

应用程序切换数据库配置场景实例:

程序包括Dao层接口和实现类,Service层接口和实现类,工厂层静态方法类,测试类

Dao层下,创建了一个接口类(userDao)和不同的数据库实现类(MySqlDaoImpl和OracelDaoImpl),MysqlDao和OracelDao实现类分别继承了相同的接口并对方法进行的重写。

//接口
interface void findInfo();
//实现类
@Override
    public void findInfo() {
        System.out.println("MySQl");
    }

@Override
    public void findInfo() {
        System.out.println("Oracle");
    }

Service层下,创建了一个接口类(userService)和一个实现类(userServiceImpl),在实现类userServiceImpl实现接口后,可以在其类中声明接口UserDao并实例化不同的数据库实现类,从而达到切换数据库的目的。注意此时切换数据库控制权由实现类userServiceImpl的代码决定。但这一方法并不能达到灵活切换配置的目的,切换数据库时需要变动实现类userServiceImpl的代码。

//接口
interface   getConfig();
//实现类
private UserDao userDao= new MySqlDaoImpl();
    @Override
    public void getConfig() {
        userDao.findInfo();
    }

为了解决这一窘境,切换换数据库时尽量保证简单,于是引出配置文件配置来决定接口类UserDao究竟实例化哪个实现类。那么如何巧妙的把配置文件放到类中生效呢?为此采取了以下的办法。

(1)建立中间类:Factory类,使用getInstance( )方法控制数据库接口UserDao的实例化对象,这就意味着,userServiceImpl不再具有切换数据库的权利。同时这样一种转让操作权利的的模式有个专业性名词就叫Spring中的控制反转IOC/DI,数据库实现类实例化由主动创建变为被动接受。那么中间类Factory又是如何处理UserDao是实例化哪个数据库实现类的呢?

private UserDao userDao= userDaoFactory.getInstance();
    @Override
    public void getConfig() {
        userDao.findInfo();
    }

(2)在resource文件夹建立userDao.properties配置,并在配置中添加字段key:userdao value:数据库实现类的限定类名。看到这里建立配置文件的目的就一目了然了。Factory又再次转让控制权到userDao.properties,而userDao.propertie配置文件通过改变value即限定类名的值切换数据库配置。这也就意味着Factory的选择数据库实现类的权力转移到properties配置文件中,成为联系userDao.properties配置文件和userServiceImpl类中间人,通过properties中的指定字段决定究竟把哪个数据库实现类给实例化。那此时就涉及到properties配置文件的读取问题和为什么仅仅通过数据库实现类的全类名就可以达到实例化类的效果。

//properties的配置
userdao=com.cn.dao.impl.OracleUserDao

(3)读取properties文件:通过properties类操作方法实现①load(InputStream is)加载文件、getProperty(key)获取value的值,即类的限定类名。而这些操作全部在userDaoFactory类中实现。那么获取限定类名又是如何直接实例化进行返回的呢?

public static UserDao getInstance() {
        UserDao userDao=null;
        try {
            Properties ps = new Properties();
            //获得配置文件
            InputStream is=userDaoFactory.class.getClassLoader().getResourceAsStream("userDao.properties");
            //加载配置文件
            ps.load(is);
            //根据配置文件Key获取value,即限定类名
            String userDaoFullName = ps.getProperty("userdao");
            //动态加载类获得类的反射对象
            Class<?> userDaoClass = Class.forName(userDaoFullName);
            //对的反射对象进行实例化
            userDao = (UserDao) userDaoClass.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return userDao;
    }

(4)测试

public static void main( String[] args )
    {
        userService userService = new userServiceImpl();
        userService.getConfig();
    }

总结:

为什么需要Spring IOC容器?

现在是对于用户模块,可以写一个UserDaoFactory的工厂类,如果有很多模块,比如支付模块、订单模块、新闻模块等,就意味着每个模块都需要写对于的XXXDaoFacory的工厂类。这样工作量太大,能否有统一的方法解决程序员呢?

Spring提供了一个通用的工厂类,所以的对象的创建都可以用Spring对应的工厂,整个工厂就是所谓的IOC容器。

该IOC容器的底层实现技术是工厂+反射技术+xml的解析。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值