以前代码中的问题

案例环境目录
在这里插入图片描述
由于这里我们没有创建web工程,所以ui包代表web工程中的存放servlet的包,内容分别如下
dao包中的接口
在这里插入图片描述
dao包中的接口的实现类
在这里插入图片描述
service包中的接口
在这里插入图片描述
service包中的接口的实现类
在这里插入图片描述
ui包中的Client类
在这里插入图片描述
,我们可以看到其实这就是我们最开始学习web过程中最基本的结构,但是这有着一个致命的问题

问题1:耦合性太高

这样很强的耦合性就让我们代码的独立性很差,这是由于什么导致的呢?
这是由于
在这里插入图片描述
像这样使用new关键字创建对象导致的,如果当我们删除一个类后
在这里插入图片描述
他就会出现这种编译错误的问题
那我们如何解决这样的问题呢?
这时候我们就需要使用工厂模式来解耦,降低程序的耦合性,我们创建一个factory包,里面创建一个BeanFactory工厂类
在这里插入图片描述
那什么是Bean对象呢?

问题2:什么是Bean对象

Bean在计算机英语中表示可重用组件的意思,那什么又是可重用组件呢?

问题3:什么是可重用组件

在我们生活中手机由各个组件构成,比如屏幕、芯片、电池等等…
而在我们软件开发中一个项目也由很多个组件构成,比如我们的持久层、业务层还有显示层以及我们的实体类,这些组件中像我们的service就可以被很多显示层来使用,我们的dao可以被很多的service层来使用
那什么又是javabean呢?

问题4:什么是javabean

javabean并不只是实体类(javabean != 实体类),javabena的范围远大于实体类,实体类只是我们的可重用组件的一部分,而JavaBean表示的是用Java语言编写的可重用组件

根据上面这些问题的答案,我们就能明白我们的这个创建Bean工厂的对象是来创建我们的service和dao对象的,那我们该如何创建这两个对象呢?

问题5:如何创建这两个对象并且耦合性不会很高?

  1. 首先我们需要一个配置文件,用于配置我们的service和dao,配置文件中需要包含全限定类名和全限定类名的唯一标志(唯一标志=全限定类名)也就是key=value的形式
  2. 通过读取配置文件中的内容,反射创建对象

配置文件如下
在这里插入图片描述
编写BeanFactory中的内容,用于创建两个对象
在这里插入图片描述
这里我们需要注意,我们抛出的这个异常是个初始化错误,我们可以抛出io异常,但是我们本着配置文件加载失败的话就没有后面的内容的原则就直接抛出初始化错误,解释完这个细节后我们继续编写BeanFactory中的内容,得到初步的内容为

/**
 * 创建一个Bean对象的工厂
 * @author 14767
 */
public class BeanFactory {
    /**
     * 定义一个properties对象
     */
    private static Properties props;
    /**
     * 使用静态代码块为properties对象赋值
     */
    static {
        //实例化对象
        props = new Properties();
        //获取properties文件的流对象
        try {
            props.load(BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties"));
        } catch (Exception e) {
            throw new ExceptionInInitializerError("初始化properties失败");
        }
    }

    /**
     * 根据bean的名称获取bean对象
     * @param beanName
     * @return
     */
    public static Object getBean(String beanName){
        Object bean = null;
        String beanPath = props.getProperty(beanName);
        try {
            bean = Class.forName(beanPath).newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return bean;
    }
}

然后我们将原来new创建AccountServiceImpl和AccountDaoImpl对象的内容注释掉,使用工厂类进行创建,如下
在这里插入图片描述
然后我们执行后发现,也可以成功执行,这个时候如果我们再删除AccountServiceImpl类的话,我们就能看到我们编译已经不报错了
在这里插入图片描述
这说明程序的耦合性降低了(注意这里只是编译不报错,但是运行该报运行异常还是报运行异常的错误)

我们继续改进我们的BeanFactory类,最终形态

/**
 * 创建一个Bean对象的工厂
 * @author 14767
 */
public class BeanFactory {
    /**
     * 定义一个properties对象
     */
    private static Properties props;
    /**
     * 定义一个Map,用于存放我们要创建的对象,我们把它称之为容器
     */
    private static Map<String,Object> beans;
    /**
     * 使用静态代码块为properties对象赋值
     */

    static {
        //实例化对象
        props = new Properties();
        //获取properties文件的流对象
        try {
            props.load(BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties"));
            //初始化容器
            beans = new HashMap<String ,Object>();
            //出去配置文件中的所有key
            Enumeration<Object> keys = props.keys();
            while (keys.hasMoreElements()){
                String key = keys.nextElement().toString();
                //根据key获取value
                String beanPath = props.getProperty(key);
                //反射创建对象
                Object value = Class.forName(beanPath).newInstance();
                //把key和value存入容器当中
                beans.put(key,value);
            }
            System.out.println(beans);
        } catch (Exception e) {
            throw new ExceptionInInitializerError("初始化properties失败");
        }
    }

    /**
     * 根据bean的名称获取bean对象
     * @param beanName
     * @return
     */
    public static Object getBean(String beanName){
        return beans.get(beanName);
    }
}

posted @ 2021-01-11 12:09  谢海川  阅读(27)  评论(0)    收藏  举报