【Spring】 02 - 程序之间的耦合
2020-09-12 本文已影响0人
itlu
1. 案例回顾传统JDBC操作
- 注册驱动;
- 获取连接 ;
- 获取操作数据库的预处理对象;
- 执行SQL查询数据库得到结果集;
- 遍历结果集;
- 释放资源;
1.1 创建一个Maven项目
- 在 file -> new - > project 下创建一个maven项目不使用骨架的方式:
![](https://img.haomeiwen.com/i17394504/53f632b90bd22e27.png)
- 引入相关数据库的依赖,mysql-connector :
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
</dependencies>
- 创建案例中需要使用的数据库和数据:
CREATE DATABASE spring CHARACTER SET utf8;
USE spring;
create table account(
id int primary key auto_increment,
name varchar(40),
money float
)character set utf8 collate utf8_general_ci;
insert into account(name,money) values('aaa',1000);
insert into account(name,money) values('bbb',1000);
insert into account(name,money) values('ccc',1000);
- 编写测试类进行测试 : 代码中 ,如果使用方式二注册驱动,当我们项目中没有了Mysql驱动的jar包的时候是无法通过编译的。
/**
* @author lyp
* <p>
* 传统JDBC 测试类
*/
public class JDBCTest {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
// 1. 注册驱动 方式一
// Class.forName("com.mysql.jdbc.Driver");
// 1. 注册驱动 方式二
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
// 2. 获取连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/spring", "root", "root");
// 3. 获取操作数据库的预处理对象
ps = conn.prepareStatement("select * from account");
// 4. 执行SQL查询数据库得到的结果集
rs = ps.executeQuery();
// 5. 遍历结果集
while (rs.next()) {
System.out.println(rs.getString("name") + " ");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
![](https://img.haomeiwen.com/i17394504/b063bed8fdbd513c.png)
![](https://img.haomeiwen.com/i17394504/c022bef52391fae3.png)
1.2 程序的耦合
-
耦合:程序之间的依赖关系;
-
类之间的依赖;
-
方法之间的依赖;
-
解耦:降低程序之间的依赖关系;
-
实际开发中应该做到:
编译期不依赖,运行时才依赖;
- 解决类之间的依赖:
第一步:使用反射创建对象,二是避免使用 new 关键字。
第二步:通过读取配置文件来获取需要创建的对象全限定类名。
1.3 传统代码中的问题分析
-
创建一个新的项目 。使用Maven但是不使用骨架。
-
这是一个模拟
zhuanzhang
的一个操作:从持久层到表现层。 -
创建一个持久层接口并创建一个实现类 :
/**
* 账户持久层接口
* @author lyp
*/
public interface AccountDao {
/**
* 保存账户信息
*/
void saveAccount();
}
/**
* 保存账户信息持久层实现类
* @author lyp
*/
public class AccountDaoImpl implements AccountDao {
/**
* 保存账户信息持久层实现类
*/
public void saveAccount() {
System.out.println("保存了账户信息.....");
}
}
- 创建一个业务层接口并创建其实现类 : 其中就会有一个类与类之间的依赖问题。
/**
* @author lyp
*
* 模拟账户业务层接口
*/
public interface AccountService {
/**
* 保存账户信息
*/
void saveAccount();
}
/**
* AccountService 业务层接口实现类
* @author lyp
*/
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao = new AccountDaoImpl();
public void saveAccount() {
accountDao.saveAccount();
}
}
![](https://img.haomeiwen.com/i17394504/3c33e82df7ad2fe7.png)
- 创建测试类(代替表现层)Client
/**
* 测试客户端
* @author lyp
*/
public class Client {
public static void main(String[] args) {
AccountService service = new AccountServiceImpl();
service.saveAccount();
}
}
![](https://img.haomeiwen.com/i17394504/ee042238c30914a3.png)
-
在以上的程序中,如果我将持久层,或者是业务层的任意一个的代码删除,程序将会出现错误而无法运行。
-
该如何解决?
使用工厂模式解耦。
1.4 编写工程类和配置文件
-
Bean: 在计算机英语中,是可重用组件的含义;
-
JavaBean:用Java语言编写的可重用组件。
JavaBean > 实体类
。 -
创建Bean对象的工厂:
第一个,需要一个配置文件来配置我们的service和dao,配置的内容是唯一标识,全限定类名(key : value)。
第二个,通过读取配置文件配置的内容,反射创建对象。
- 多例对象和单例对象的区别 :
单例对象的特点:只创建一次,从而类中的成员只会初始化一次。但是有线程问题。
多例对象的特点:对象被创建多次,造成效率低。执行效率没有单例对象高。
![](https://img.haomeiwen.com/i17394504/00f70d30f9e1e81a.png)
1.4.4 工厂模式解耦
-
创建一个 Beanfactory 工厂类 ,通过解析配置文件 以及 反射等方式创建对象。
-
编写配置文件 : key = value 。
accountService=com.lyp.service.impl.AccountServiceImpl
accountDao=com.lyp.dao.impl.AccountDaoImpl
- 编写 BeanFactory 创建单例和多例对象:
/**
* BeanFactory 使用 BeanFactory 创建对象
*
* @author lyp
*/
public class BeanFactory {
private static Properties props;
/**
* 用于存 创建好的 对象键值对
*/
private static Map<String, Object> beans;
// 在静态代码块中加载配置文件
static {
try {
props = new Properties();
InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
props.load(in);
// 初始化beans
beans = new HashMap<String, Object>();
// 获取到配置文件中的所有key
Enumeration keys = props.keys();
// 循环遍历该枚举类型获取每一个 key 并创建对象
while (keys.hasMoreElements()) {
String beanName = keys.nextElement().toString();
String beanPath = props.getProperty(beanName);;
Object value = Class.forName(beanPath).newInstance();
beans.put(beanName, value);
}
} catch (Exception e) {
// 这是一个错误 出现错误程序将不再执行
throw new ExceptionInInitializerError("初始化配置文件异常!");
}
}
/**
* 获取需要创建的bean对象
* 单例的
* @param className
* @return
*/
public static Object getBean(String className) {
return beans.get(className);
}
/**
* 获取需要的 bean 对象
* 得到的bean是一个多例的对象
*
* @param className
* @return
*/
/*public static Object getBean(String className) {
Object bean = null;
// 需要获取到配置文件中的属性
String beanPath = props.getProperty(className);
try {
// 每次都会调用默认构造函数创建对象
bean = Class.forName(beanPath).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return bean;
}*/
}
1.4.5 Demo地址
- Demo码云地址 : 实现简单的工厂模式创建单例多例对象