美文网首页
spring-ioc控制翻转的实现原理

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

作者: 小明与小明 | 来源:发表于2020-09-17 17:57 被阅读0次

    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> 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> 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控制翻转的实现原理

          本文链接:https://www.haomeiwen.com/subject/vucryktx.html