暑期自学 Day 15 | Spring (一)
- 两个内核:反转控制 IoC (Inverse of Control),面向切面编程 AOP (Aspect Oriented Programming)
- 优势:
- 方便程序解耦,简化开发过程
- AOP 编程支持(解决 OOP 实现不了的功能)
- 声明式事务支持
- 方便程序测试
- 方便集成各种框架
- 降低 JavaEE API 使用难度
解耦
代码解释程序间的耦合
一个模拟存储账户的应用
持久层接口: spring/selflearning/dao/IAccountDao.java
package spring.selflearning.dao;
/*
持久层
*/
public interface IAccountDao {
/*
模拟保存账户
*/
void saveAccount();
}
持久层实现类: spring/selflearning/dao/impl/AccountDaoImpl.java
package spring.selflearning.dao.impl;
import spring.selflearning.dao.IAccountDao;
/*
账户持久层实现类
*/
public class AccountDaoImpl implements IAccountDao {
public void saveAccount() {
System.out.println("保存了账户");
}
}
业务层接口: spring/selflearning/service/IAccountService.java
package spring.selflearning.service;
public interface IAccountService {
/*
业务层接口
*/
void saveAccount();
}
业务层实现类: spring/selflearning/service/impl/AccountServiceImpl.java
此处由于需要通过新建对象的方式调用持久层,所以与持久层有依赖关系,一旦持久层被更改,程序将报错。
package spring.selflearning.service.impl;
import spring.selflearning.dao.IAccountDao;
import spring.selflearning.dao.impl.AccountDaoImpl;
import spring.selflearning.service.IAccountService;
/*
账户业务层实现类
*/
public class AccountServiceImpl implements IAccountService {
// 业务层调用持久层
private IAccountDao accountDao = new AccountDaoImpl(); // 业务层由于new了持久层实现类,具有强耦合性
public void saveAccount() {
accountDao.saveAccount();
}
}
表现层: spring/selflearning/ui/Client.java
表现层也需要新建业务层对象,所以有依赖关系。
package spring.selflearning.ui;
import spring.selflearning.dao.IAccountDao;
import spring.selflearning.service.IAccountService;
import spring.selflearning.service.impl.AccountServiceImpl;
/*
模拟表现层,用于调用业务层
*/
public class Client {
public static void main(String[] args) {
IAccountService as = new AccountServiceImpl(); // 表现层由于new了业务层实现类,具有强耦合性
as.saveAccount();
}
}
解耦的思路
- 用反射创建对象,避免使用 new 关键字
- 读取配置文件获取要创建的对象全限定类名 (方便更改依赖包)
使用工厂模式解耦
- 工厂模式做了什么?
- 为了解耦,我们使用一个创建 Bean 对象的工厂
- Bean 是可重用组件,持久层可以被业务层重用,业务层可以被表现层重用,因此在上面的代码示例中可以创建业务层和持久层对象
- 步骤:使用一个配置文件配置service和dao,然后通过读取配置文件内容反射创建对象。配置文件(.xml 或 .properties)的内容是 service 和 dao 的全限定类名。
利用工厂模式读取配置代码示例: spring/selflearning/factory/BeanFactory.java
这段代码利用 BeanFactory 读取配置文件,并自定义了获取可重用组件对象的方法。
package spring.selflearning.factory;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
// Bean: 可重用组件
public class BeanFactory {
private static Properties props;
// 为 props 对象赋值
static {
props = new Properties(); // 实例化对象
InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties"); // 不使用 new 创建流对象而使用getClassLoader()是为了防止配置文件位置的更改。
try {
props.load(in);
} catch (IOException e) {
throw new ExceptionInInitializerError("初始化Properties失败!");
}
}
// 根据 Bean 的名称获取 Bean 对象
public Object getBean(String beanName) {
Object bean = null;
try {
String beanPath = props.getProperty(beanName);
bean = Class.forName(beanPath).newInstance();
} catch (Exception e) {
e.printStackTrace();
}
return bean;
}
}
配置文件: resources/bean.properties
accountService=spring.selflearning.service.impl.AccountServiceImpl
accountDao=spring.selflearning.dao.impl.AccountDaoImpl
表现层解耦: spring/selflearning/ui/Client.java
package spring.selflearning.ui;
//import spring.selflearning.dao.IAccountDao;
import spring.selflearning.factory.BeanFactory;
import spring.selflearning.service.IAccountService;
//import spring.selflearning.service.impl.AccountServiceImpl;
/*
模拟表现层,用于调用业务层
*/
public class Client {
public static void main(String[] args) {
// IAccountService as = new AccountServiceImpl(); // 表现层由于new了业务层实现类,具有强耦合性
IAccountService as = (IAccountService) BeanFactory.getBean("accountService"); // 解耦,将getBean()得到的Object类强转为所需类型
as.saveAccount();
}
}
业务层解耦: spring/selflearning/service/impl/AccountServiceImpl.java
package spring.selflearning.service.impl;
import spring.selflearning.dao.IAccountDao;
//import spring.selflearning.dao.impl.AccountDaoImpl;
import spring.selflearning.factory.BeanFactory;
import spring.selflearning.service.IAccountService;
/*
账户业务层实现类
*/
public class AccountServiceImpl implements IAccountService {
// 业务层调用持久层
// private IAccountDao accountDao = new AccountDaoImpl(); // 业务层由于new了持久层实现类,具有强耦合性
private IAccountDao accountDao = (IAccountDao) BeanFactory.getBean("accountDao"); // 解耦,将getBean()得到的Object类强转为所需类型
public void saveAccount() {
accountDao.saveAccount();
}
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: