Spring 之 factory工厂模式的解耦
在实际开发中我们可以把三层的对象都使用配置文件配置起来,当启动服务器应用加载的时候,让一个类中的
方法通过读取配置文件,把这些对象创建出来并存起来。在接下来的使用的时候,直接拿过来用就好了。
那么,这个读取配置文件,创建和获取三层对象的类就是工厂。
上一小节解耦的思路有 2 个问题:
1、存哪去?
分析:由于我们是很多对象,肯定要找个集合来存。这时候有 Map 和 List 供选择。
到底选 Map 还是 List 就看我们有没有查找需求。有查找需求,选 Map。
所以我们的答案就是
在应用加载时,创建一个 Map,用于存放三层对象。
我们把这个 map 称之为容器。
2、还是没解释什么是工厂?
工厂就是负责给我们从容器中获取指定对象的类。这时候我们获取对象的方式发生了改变。
原来:
我们在获取对象时,都是采用 new 的方式。是主动的。
现在:
我们获取对象时,同时跟工厂要,有工厂为我们查找或者创建对象。是被动的
这就是
控制反转-Inversion Of Contr
![
代码的演示:
曾经代码中的问题分析-----------------------------》
模拟一下:
创建新的module:-----》 接口
这些都是 之前做过的 实现类 多态new的现象 就是要避免 和 解耦的 可以用的 优化
业务层 在调用 持久层 也在 表现层 到 持久层 都会共有的 问题s
我们maven的坐标啊 地方就是 jar 的方式 (没有坐标的)没有浏览器与web
在模拟一个表现层 (实际里这里就是一个 servlet)
我们呈现 了好多的依赖 这就是我们要解决的
maven的pom 文件还是 有个 mysql 就行
mysql
mysql-connector-java
5.1.6
----dao里
package com.fhw.dao;
/* 账户持久层接口*/
public interface IAccountDao {
/* 模拟保存账户的操作*/
void saveAccount();
}
package com.fhw.dao.impl;
import com.fhw.dao.IAccountDao;
/* 账户持久层实现类*/
public class IAccountDaoImpl implements IAccountDao {
public void saveAccount() {
// System.out.println("保存了账户");
}
}
-seervice 里
package com.fhw.service;
/*账户 :业务层的接口
-
/
public interface IAcconutService {
/*- 模拟保存账户
*/
void saveAccount();
}
----package com.fhw.service.impl;
- 模拟保存账户
import com.fhw.dao.IAccountDao;
import com.fhw.factory.BeanFactory;
import com.fhw.service.IAcconutService;
public class IAccountServiceImpl implements IAcconutService{
/private IAccountDao accountDao=new IAccountDaoImpl();/
IAccountDao accountDao= (IAccountDao) BeanFactory.getBean("accountDao");
public void saveAccount() {
accountDao.saveAccount();
System.out.println();
}
}
properties配置文件
accountService =com.fhw.service.impl.IAccountServiceImpl
accountDao=com.fhw.dao.impl.IAccountDaoImpl
-----核心的 ``factory工厂类------------
``package com.fhw.factory;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/*
-
c创建一个 Bean对象
-
Bean 在计算机英语里是 可重用组件
-
javaBean: 不同于java实体类 大于实体类 java编写的可重用组件
-
javabean 来 创建 我们的 Service 与到的对象
-
1: 需要 配置文件 来 配置Service与 dao
*配置内容 :唯一标示= 全限定类名 就是 key =value 的配置文件 -
xml 或 propertise 都行
-
2:通过配置文件的内容来 反射创建对象
-
现在 选用简单 propertise 应用
-
*/
public class BeanFactory {
//定义一个 properties 对象
private static Properties props;
//优化 改造 定义map容器 用于存放我们要创建的 对象
private static Map<String ,Object> beans;
// static 为对象 赋值
static{
try {
// 实例化对象
props = new Properties();
//还是类加载器 :反射解耦 方便多了
InputStream in=BeanFactory.class.getClassLoader().getResourceAsStream(“bean.properties”);
props.load(in);
//实例化容器
beans=new HashMap<String,Object>();
//取出配置文件里所有的 key
Enumeration keys = props.keys();
//遍历枚举
while (keys.hasMoreElements()){
String key = keys.nextElement().toString();
//根据key 来获取value
String beanpath = props.getProperty(key);
//反射创建对象
Object value=Class.forName(beanpath).newInstance();
beans.put(key,value);
}} catch (Exception e) {// 这里若 读取失败 //直接throw 指定异常 给信息即可 throw new ExceptionInInitializerError("初始化properties 失败!"); }
}
/**
- 根据bean 的名称获取 对象 是单例模式
- @param beanName
- @return
/
public static Object getBean(String beanName){
return beans.get(beanName);
}
/ public static Object getBean(String beanName){//写活 : Object 或 T泛型 get那个 参数指定
Object bean=null;
try {
String beanPath = props.getProperty(beanName);
//反射获取 到
bean = Class.forName(beanPath).newInstance();
}catch (Exception e){
e.printStackTrace();
}
return bean;
}*/
}
/*当单例放到方法里
定义方法的时候 调用方法 就重新加载 也是初始化 所以也能保证每次初始化-----》 单例也可以----》但是BeanFactory的就是反射的构造函数NewInstance
-----BeanFactory 创建对象是的反射 里的newInstance()=》这句 话的出场–每次都会调用 默认 构造函数 创建对象
所以每次都是 新的 -------》Spring也 不能识别 只能的java GC 机制 来回收
现在就 只能用一次 newInstance()要保留=》存到那=》容器
于是我们就要一个Map 里的key value ----------*/