容器工厂

发布时间 2023-06-01 16:19:17作者: 186的博客

一、通过工厂+反射+配置文件创建对象
简单的说就是以后我们不用自己new对象了,对象的实例化都交给工厂来完成,我们需要对象的时候直接问工厂拿一个就行,一会我们会来看一个例子。在这里有一点要说明,spring IOC与工厂模式并不是完全相同的,最大的不同在于普通的工厂模式内部还是使用new来创建对象,但是spring IOC是用反射来创建对象,这么做有什么好处呢?

/**
 * @author wangl
 * @date 2023/5/31
 * 容器工厂
 */
public class ContainerFactory {

    /**
     * 容器
     */
    private static Map<String, Object> container = new HashMap<>();

    /**
     * 在静态代码块中初始化整个容器工厂,解析properties文件中配置的对象,
     * 创建实例放入到Map集合中
     */
    static {
        //加载配置文件
        //1、创建Propertise对象
        Properties prop = new Properties();
        //根据Properties文件的位置创建一个输入流,给Properties对象进行操作
        //InputStream 输入流-用完就关闭
        //getClassLoader:类加载器
        //getResourceAsStream 找到项目的src目录
        try (InputStream input = ContainerFactory.class.getClassLoader().getResourceAsStream("Bean.properties")){


            //加载并读取properties文件的内容
            prop.load(input);

            //循环遍历prop对象得到每一个properties
            //把创建好的实例Map集合中key
            //map.put(key,input)
            prop.forEach((key,value) -> {
                //key.toString(),newInstance()))
                Object instance = newInstance(value.toString());
                container.put(key.toString(),instance);
                    });

//

        } catch (Exception e) {
            throw new RuntimeException("解析失败",e);
        }
    }

        private static  Object newInstance(String className) {
            try {
                //通过完成整类名加载class对象
                Class<?>clazz = Class.forName(className);
                return clazz.getConstructor().newInstance();
            }catch (Exception e){
                throw new RuntimeException("解释失败");
            }
        }
    /**
     * 容器工厂方法
     */
    public static <T> T getBean(String name) {
        return (T)container.get(name);
    }


}

配置文件如下

iphone = edu.nf.product.IPhone
miphone = edu.nf.product.MiPhone

spring IOC的思想与工厂模式基本是一样的,只是创建对象的方式从“new”变成了反射,这就带来了很大的灵活性。不过,现在阅读spring源码还为时过早,于是我自己写了一个简单的例子来模拟spring IOC的基本原理。
首先,如果我们要用反射创建对象,全类名是必不可少的(反射不太记得的朋友请好好复习一下反射),然后我们还需要一个类名,用来告诉工厂我们需要哪个对象(就像上面getShape方法传入的参数shapeType一样),这个名字可以随便取,但是不能重复。这样我们就有了创建对象的两个要素,然后我们需要一个key-value对把这两个关联起来。然后就形成了这样一个模式:我们传入类名,工厂去查询key-value对,找到对应的全类名,然后通过全类名利用反射创建对象,再返回给我们。是不是很简单呢?