spring-ioc控制翻转的实现原理

spring的控制反转

组织结构

在开发中,我们常使用这样的项目结构,在没有使用spring框架的时候,通常使用这样的代码去实例化一个对象

 IProductDao productDao1 = new ProductDaoImpl();

使用spring之后,常使用下面的方式进行创建对象。

  1. 自动装配,使用spring @Autowired注解的方式
@Autowired
private IProductDao productDao1;
  1. 使用构造器的方式注解
private IProductDao productDao1;
@Autowired //构造器注入  
private (IProductDao dao) {  
    this.productDao1 = dao;  
}

使用spring之后,=号后面的内容就不要我们在进行书写了。把创建的对象权利交给了spring容器了,这就是spring的控制反转。

实现方式1

spring内部其实就是一个大的工厂,首先可以通过创建工厂的方式来进行创建。

public class DaoFactory {
    /**构造器私有化*/
    private DaoFactory(){
    }

    /**创建一个Dao对象*/
    public static Object createDao(String daoName){
        if ("productDao".equals(daoName)){
            return new ProductDaoImpl();
        }else if("userDao".equals(daoName)){
            return new UserDaoImpl();
        }
        return null;
    }

    public static void main(String[] args) {

    }
}

但是,这种创建方式效率不够高,硬编码的方式,可移植化低,只能创建少数几个类型的对象。

实现方式2

通过配置dao.properties文件的方式,将bean信息写入配置文件中,然后根据反射的方式进行创建对象。

配置文件文件内容

productDao=factory.dao.impl.ProductDaoImpl
userDao=factory.dao.impl.UserDaoImpl
public class DaoFactory {
    /*** 构造器私有化*/
    private DaoFactory(){ }
    //不需要外部进行访问
    private static Properties pros = new Properties();
    // 在静态代码块中加载
    static{
        try {
            pros.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("factory/config/dao.properties"));
        } catch (Exception e) { e.printStackTrace(); }
    }

    public static Object createDao(String daoName){
       //根据key拿到相应value,创建这个类的全限定名称
        String className = pros.getProperty(daoName);
        //拿到全限名,根据反射创建对象
        try{
            Class clz =  Class.forName(className);
            return clz.newInstance();
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {
        IProductDao productDao =(IProductDao) DaoFactory.createDao("productDao");
        System.out.println(productDao);
        IUserDao userDao = (IUserDao) DaoFactory.createDao("userDao");
        System.out.println(userDao);
    }
}

但是使用这种方式的缺陷就是,通过工厂创建的方式,需要使用强制转换的方式。能够使用泛型方法来解决这个问题。

将上面的函数修改为

public static  T createDao(String daoName){
       //根据key拿到相应value,创建这个类的全限定名称
        String className = pros.getProperty(daoName);
        //拿到全限名,根据反射创建对象
        try{
            Class clz =  Class.forName(className);
            return (T)clz.newInstance();
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

相同类型的对象,使用一个缓存。

public static  T createDao(String daoName) {
        //根据key拿到相应value,创建这个类的全限定名称
        String className = pros.getProperty(daoName);
        //拿到全限名,根据反射创建对象
        try {
            T t = (T) cacheMap.get(daoName);
            if (t == null) {
                Class clz = Class.forName(className);
                t = (T) clz.newInstance();
                //把对象放到缓存里面去
                cacheMap.put(daoName, t);
            }
            return t;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

你可能感兴趣的:(spring-ioc控制翻转的实现原理)