业务层的抽取和业务层方法的实现详解
业务层的抽取和业务层方法的实现详解
1. 业务层的作用和重要性
业务层的核心职责
- 业务逻辑处理:实现具体的业务规则和流程
- 事务管理:确保业务操作的原子性
- 服务编排:协调多个DAO操作完成复杂业务
- 异常处理:统一的业务异常处理机制
- 权限控制:业务级别的权限验证
2. 业务层的分层架构
标准的三层架构
表现层 (Controller/View)↓
业务层 (Service) ← 我们重点关注的层次↓
数据访问层 (DAO)↓
数据库 (Database)
3. 业务层的抽取策略
3.1 按业务领域划分
// 用户相关业务
UserService├── UserRegistrationService├── UserAuthenticationService└── UserProfileService// 账户相关业务
AccountService├── AccountTransferService├── AccountQueryService└── AccountManagementService// 交易相关业务
TransactionService├── PaymentService├── WithdrawalService└── TransferService
3.2 按功能复杂度划分
// 简单业务:直接CRUD操作
BasicAccountService// 复杂业务:涉及多个领域
ComplexTransferService// 组合业务:多个简单业务的组合
CompositeBusinessService
4. 业务层接口设计
4.1 业务层接口定义
package com.bank.service;import com.bank.entity.Account;
import com.bank.entity.Transaction;
import com.bank.exception.BusinessException;import java.math.BigDecimal;
import java.util.List;/*** 账户业务服务接口* 定义所有账户相关的业务操作*/
public interface AccountService {// ==================== 账户管理业务 ====================/*** 开户业务* @param account 账户信息* @return 开户结果* @throws BusinessException 业务异常*/boolean openAccount(Account account) throws BusinessException;/*** 销户业务* @param accountId 账户ID* @return 销户结果* @throws BusinessException 业务异常*/boolean closeAccount(Long accountId) throws BusinessException;/*** 账户状态管理* @param accountId 账户ID* @param status 状态* @return 操作结果* @throws BusinessException 业务异常*/boolean manageAccountStatus(Long accountId, Integer status) throws BusinessException;// ==================== 账户查询业务 ====================/*** 查询账户详情* @param accountId 账户ID* @return 账户信息* @throws BusinessException 业务异常*/Account getAccountDetail(Long accountId) throws BusinessException;/*** 查询用户所有账户* @param userId 用户ID* @return 账户列表* @throws BusinessException 业务异常*/List<Account> getUserAccounts(Long userId) throws BusinessException;/*** 查询账户余额* @param accountId 账户ID* @return 账户余额* @throws BusinessException 业务异常*/BigDecimal getAccountBalance(Long accountId) throws BusinessException;// ==================== 资金业务 ====================/*** 存款业务* @param accountId 账户ID* @param amount 存款金额* @param remark 备注* @return 存款结果* @throws BusinessException 业务异常*/boolean deposit(Long accountId, BigDecimal amount, String remark) throws BusinessException;/*** 取款业务* @param accountId 账户ID* @param amount 取款金额* @param remark 备注* @return 取款结果* @throws BusinessException 业务异常*/boolean withdraw(Long accountId, BigDecimal amount, String remark) throws BusinessException;/*** 转账业务* @param fromAccountId 转出账户* @param toAccountId 转入账户* @param amount 转账金额* @param remark 备注* @return 转账结果* @throws BusinessException 业务异常*/boolean transfer(Long fromAccountId, Long toAccountId, BigDecimal amount, String remark) throws BusinessException;// ==================== 交易查询业务 ====================/*** 查询账户交易流水* @param accountId 账户ID* @param startDate 开始日期* @param endDate 结束日期* @return 交易列表* @throws BusinessException 业务异常*/List<Transaction> getAccountTransactions(Long accountId, String startDate, String endDate) throws BusinessException;/*** 查询交易详情* @param transactionId 交易ID* @return 交易详情* @throws BusinessException 业务异常*/Transaction getTransactionDetail(Long transactionId) throws BusinessException;
}
5. 业务层实现详解
5.1 基础业务服务实现
package com.bank.service.impl;import com.bank.dao.AccountDAO;
import com.bank.dao.TransactionDAO;
import com.bank.dao.UserDAO;
import com.bank.entity.Account;
import com.bank.entity.Transaction;
import com.bank.entity.User;
import com.bank.exception.BusinessException;
import com.bank.service.AccountService;
import com.bank.util.TransactionManager;import java.math.BigDecimal;
import java.util.Date;
import java.util.List;/*** 账户业务服务实现*/
public class AccountServiceImpl implements AccountService {// 依赖的DAO组件private final AccountDAO accountDAO;private final TransactionDAO transactionDAO;private final UserDAO userDAO;// 事务管理器private final TransactionManager transactionManager;/*** 构造方法注入依赖*/public AccountServiceImpl(AccountDAO accountDAO, TransactionDAO transactionDAO,UserDAO userDAO,TransactionManager transactionManager) {this.accountDAO = accountDAO;this.transactionDAO = transactionDAO;this.userDAO = userDAO;this.transactionManager = transactionManager;}// ==================== 账户管理业务实现 ====================@Overridepublic boolean openAccount(Account account) throws BusinessException {// 参数验证validateAccount(account);try {// 开启事务transactionManager.beginTransaction();// 1. 验证用户是否存在User user = userDAO.findById(account.getUserId());if (user == null) {throw new BusinessException("USER_NOT_EXIST", "用户不存在");}// 2. 验证账户是否已存在if (accountDAO.existsByAccountNumber(account.getAccountNumber())) {throw new BusinessException("ACCOUNT_EXISTS", "账户已存在");}// 3. 设置账户默认值account.setBalance(BigDecimal.ZERO);account.setStatus(1); // 正常状态account.setCreateTime(new Date());account.setUpdateTime(new Date());// 4. 创建账户boolean success = accountDAO.insert(account);if (!success) {throw new BusinessException("CREATE_ACCOUNT_FAILED", "创建账户失败");}// 5. 记录开户交易流水Transaction transaction = createTransaction(account.getId(), Transaction.TransactionType.OPEN_ACCOUNT, BigDecimal.ZERO, "开户");transactionDAO.insert(transaction);// 提交事务transactionManager.commit();return true;} catch (Exception e) {// 回滚事务transactionManager.rollback();if (e instanceof BusinessException) {throw (BusinessException) e;}throw new BusinessException("OPEN_ACCOUNT_ERROR", "开户业务异常", e);}}@Overridepublic boolean closeAccount(Long accountId) throws BusinessException {try {transactionManager.beginTransaction();// 1. 验证账户是否存在Account account = accountDAO.findById(accountId);if (account == null) {throw new BusinessException("ACCOUNT_NOT_EXIST", "账户不存在");}// 2. 验证账户状态if (account.getStatus() == 0) {throw new BusinessException("ACCOUNT_ALREADY_CLOSED", "账户已销户");}// 3. 验证账户余额if (account.getBalance().compareTo(BigDecimal.ZERO) != 0) {throw new BusinessException("ACCOUNT_BALANCE_NOT_ZERO", "账户余额不为零,无法销户");}// 4. 更新账户状态account.setStatus(0); // 销户状态account.setUpdateTime(new Date());boolean success = accountDAO.update(account);if (!success) {throw new BusinessException("CLOSE_ACCOUNT_FAILED", "销户失败");}// 5. 记录销户流水Transaction transaction = createTransaction(accountId, Transaction.TransactionType.CLOSE_ACCOUNT, BigDecimal.ZERO, "销户");transactionDAO.insert(transaction);transactionManager.commit();return true;} catch (Exception e) {transactionManager.rollback();if (e instanceof BusinessException) {throw (BusinessException) e;}throw new BusinessException("CLOSE_ACCOUNT_ERROR", "销户业务异常", e);}}// ==================== 资金业务实现 ====================@Overridepublic boolean deposit(Long accountId, BigDecimal amount, String remark) throws BusinessException {// 参数验证validateAmount(amount);try {transactionManager.beginTransaction();// 1. 验证账户Account account = validateAndGetAccount(accountId);// 2. 执行存款BigDecimal newBalance = account.getBalance().add(amount);boolean success = accountDAO.updateBalance(accountId, newBalance);if (!success) {throw new BusinessException("DEPOSIT_FAILED", "存款操作失败");}// 3. 记录交易流水Transaction transaction = createTransaction(accountId, Transaction.TransactionType.DEPOSIT, amount, remark);transactionDAO.insert(transaction);transactionManager.commit();return true;} catch (Exception e) {transactionManager.rollback();if (e instanceof BusinessException) {throw (BusinessException) e;}throw new BusinessException("DEPOSIT_ERROR", "存款业务异常", e);}}@Overridepublic boolean withdraw(Long accountId, BigDecimal amount, String remark) throws BusinessException {// 参数验证validateAmount(amount);try {transactionManager.beginTransaction();// 1. 验证账户Account account = validateAndGetAccount(accountId);// 2. 验证余额是否充足if (account.getBalance().compareTo(amount) < 0) {throw new BusinessException("INSUFFICIENT_BALANCE", "账户余额不足");}// 3. 执行取款BigDecimal newBalance = account.getBalance().subtract(amount);boolean success = accountDAO.updateBalance(accountId, newBalance);if (!success) {throw new BusinessException("WITHDRAW_FAILED", "取款操作失败");}// 4. 记录交易流水Transaction transaction = createTransaction(accountId, Transaction.TransactionType.WITHDRAW, amount.negate(), // 取款为负数remark);transactionDAO.insert(transaction);transactionManager.commit();return true;} catch (Exception e) {transactionManager.rollback();if (e instanceof BusinessException) {throw (BusinessException) e;}throw new BusinessException("WITHDRAW_ERROR", "取款业务异常", e);}}@Overridepublic boolean transfer(Long fromAccountId, Long toAccountId, BigDecimal amount, String remark) throws BusinessException {// 参数验证validateAmount(amount);if (fromAccountId.equals(toAccountId)) {throw new BusinessException("TRANSFER_TO_SELF", "不能向自己转账");}try {transactionManager.beginTransaction();// 1. 验证转出账户Account fromAccount = validateAndGetAccount(fromAccountId);// 2. 验证转入账户Account toAccount = validateAndGetAccount(toAccountId);// 3. 验证转出账户余额if (fromAccount.getBalance().compareTo(amount) < 0) {throw new BusinessException("INSUFFICIENT_BALANCE", "转出账户余额不足");}// 4. 执行转账操作BigDecimal fromNewBalance = fromAccount.getBalance().subtract(amount);BigDecimal toNewBalance = toAccount.getBalance().add(amount);boolean success1 = accountDAO.updateBalance(fromAccountId, fromNewBalance);boolean success2 = accountDAO.updateBalance(toAccountId, toNewBalance);if (!success1 || !success2) {throw new BusinessException("TRANSFER_FAILED", "转账操作失败");}// 5. 记录交易流水(两条)Transaction fromTransaction = createTransaction(fromAccountId, Transaction.TransactionType.TRANSFER_OUT, amount.negate(), "转账至账户:" + toAccount.getAccountNumber() + "," + remark);Transaction toTransaction = createTransaction(toAccountId, Transaction.TransactionType.TRANSFER_IN, amount, "收到账户:" + fromAccount.getAccountNumber() + "转账," + remark);transactionDAO.insert(fromTransaction);transactionDAO.insert(toTransaction);transactionManager.commit();return true;} catch (Exception e) {transactionManager.rollback();if (e instanceof BusinessException) {throw (BusinessException) e;}throw new BusinessException("TRANSFER_ERROR", "转账业务异常", e);}}// ==================== 查询业务实现 ====================@Overridepublic Account getAccountDetail(Long accountId) throws BusinessException {try {Account account = accountDAO.findById(accountId);if (account == null) {throw new BusinessException("ACCOUNT_NOT_EXIST", "账户不存在");}return account;} catch (Exception e) {throw new BusinessException("QUERY_ACCOUNT_ERROR", "查询账户详情异常", e);}}@Overridepublic List<Account> getUserAccounts(Long userId) throws BusinessException {try {return accountDAO.findByUserId(userId);} catch (Exception e) {throw new BusinessException("QUERY_USER_ACCOUNTS_ERROR", "查询用户账户列表异常", e);}}@Overridepublic List<Transaction> getAccountTransactions(Long accountId, String startDate, String endDate) throws BusinessException {try {// 验证账户存在validateAndGetAccount(accountId);// 查询交易流水return transactionDAO.findByAccountIdAndDateRange(accountId, startDate, endDate);} catch (Exception e) {throw new BusinessException("QUERY_TRANSACTIONS_ERROR", "查询交易流水异常", e);}}// ==================== 私有辅助方法 ====================/*** 验证账户参数*/private void validateAccount(Account account) throws BusinessException {if (account == null) {throw new BusinessException("ACCOUNT_NULL", "账户信息不能为空");}if (account.getUserId() == null) {throw new BusinessException("USER_ID_NULL", "用户ID不能为空");}if (account.getAccountNumber() == null || account.getAccountNumber().trim().isEmpty()) {throw new BusinessException("ACCOUNT_NUMBER_NULL", "账户号码不能为空");}}/*** 验证金额参数*/private void validateAmount(BigDecimal amount) throws BusinessException {if (amount == null) {throw new BusinessException("AMOUNT_NULL", "金额不能为空");}if (amount.compareTo(BigDecimal.ZERO) <= 0) {throw new BusinessException("AMOUNT_INVALID", "金额必须大于零");}}/*** 验证并获取账户*/private Account validateAndGetAccount(Long accountId) throws BusinessException {Account account = accountDAO.findById(accountId);if (account == null) {throw new BusinessException("ACCOUNT_NOT_EXIST", "账户不存在");}if (account.getStatus() != 1) {throw new BusinessException("ACCOUNT_STATUS_INVALID", "账户状态异常");}return account;}/*** 创建交易记录*/private Transaction createTransaction(Long accountId, Transaction.TransactionType type, BigDecimal amount, String remark) {Transaction transaction = new Transaction();transaction.setAccountId(accountId);transaction.setType(type.getValue());transaction.setAmount(amount);transaction.setRemark(remark);transaction.setTransactionTime(new Date());transaction.setCreateTime(new Date());return transaction;}
}
6. 业务异常处理
6.1 业务异常类
package com.bank.exception;/*** 业务异常类*/
public class BusinessException extends Exception {private final String errorCode;private final String errorMessage;public BusinessException(String errorCode, String errorMessage) {super(errorCode + ": " + errorMessage);this.errorCode = errorCode;this.errorMessage = errorMessage;}public BusinessException(String errorCode, String errorMessage, Throwable cause) {super(errorCode + ": " + errorMessage, cause);this.errorCode = errorCode;this.errorMessage = errorMessage;}// Getter方法public String getErrorCode() {return errorCode;}public String getErrorMessage() {return errorMessage;}
}
6.2 异常代码枚举
package com.bank.constant;/*** 业务异常代码枚举*/
public enum ErrorCode {// 账户相关异常ACCOUNT_NOT_EXIST("ACCOUNT_001", "账户不存在"),ACCOUNT_EXISTS("ACCOUNT_002", "账户已存在"),ACCOUNT_BALANCE_NOT_ZERO("ACCOUNT_003", "账户余额不为零"),ACCOUNT_STATUS_INVALID("ACCOUNT_004", "账户状态异常"),// 用户相关异常USER_NOT_EXIST("USER_001", "用户不存在"),// 交易相关异常INSUFFICIENT_BALANCE("TRANSACTION_001", "余额不足"),TRANSFER_TO_SELF("TRANSACTION_002", "不能向自己转账"),AMOUNT_INVALID("TRANSACTION_003", "金额无效"),// 系统异常SYSTEM_ERROR("SYSTEM_001", "系统异常");private final String code;private final String message;ErrorCode(String code, String message) {this.code = code;this.message = message;}public String getCode() {return code;}public String getMessage() {return message;}
}
7. 事务管理器
7.1 事务管理器接口
package com.bank.util;/*** 事务管理器接口*/
public interface TransactionManager {/*** 开启事务*/void beginTransaction() throws Exception;/*** 提交事务*/void commit() throws Exception;/*** 回滚事务*/void rollback() throws Exception;
}
7.2 JDBC事务管理器实现
package com.bank.util;import java.sql.Connection;
import java.sql.SQLException;/*** JDBC事务管理器实现*/
public class JDBCTransactionManager implements TransactionManager {private final ThreadLocal<Connection> connectionHolder = new ThreadLocal<>();@Overridepublic void beginTransaction() throws Exception {Connection conn = connectionHolder.get();if (conn != null) {throw new Exception("事务已开启");}conn = DataSourceUtil.getConnection();conn.setAutoCommit(false);connectionHolder.set(conn);}@Overridepublic void commit() throws Exception {Connection conn = connectionHolder.get();if (conn == null) {throw new Exception("没有开启事务");}try {conn.commit();} finally {conn.setAutoCommit(true);conn.close();connectionHolder.remove();}}@Overridepublic void rollback() throws Exception {Connection conn = connectionHolder.get();if (conn == null) {throw new Exception("没有开启事务");}try {conn.rollback();} finally {conn.setAutoCommit(true);conn.close();connectionHolder.remove();}}/*** 获取当前线程的事务连接*/public Connection getConnection() {return connectionHolder.get();}
}
8. 业务层工厂类
8.1 服务工厂
package com.bank.factory;import com.bank.dao.AccountDAO;
import com.bank.dao.TransactionDAO;
import com.bank.dao.UserDAO;
import com.bank.dao.impl.AccountDAOImpl;
import com.bank.dao.impl.TransactionDAOImpl;
import com.bank.dao.impl.UserDAOImpl;
import com.bank.service.AccountService;
import com.bank.service.impl.AccountServiceImpl;
import com.bank.util.JDBCTransactionManager;
import com.bank.util.TransactionManager;/*** 业务服务工厂类*/
public class ServiceFactory {private static final TransactionManager transactionManager = new JDBCTransactionManager();/*** 获取账户服务实例*/public static AccountService getAccountService() {AccountDAO accountDAO = new AccountDAOImpl();TransactionDAO transactionDAO = new TransactionDAOImpl();UserDAO userDAO = new UserDAOImpl();return new AccountServiceImpl(accountDAO, transactionDAO, userDAO, transactionManager);}// 可以添加其他服务的工厂方法// public static UserService getUserService() { ... }// public static TransactionService getTransactionService() { ... }
}
9. 业务层测试
9.1 业务服务测试
package com.bank.test;import com.bank.entity.Account;
import com.bank.exception.BusinessException;
import com.bank.factory.ServiceFactory;
import com.bank.service.AccountService;import java.math.BigDecimal;
import java.util.Date;/*** 业务服务测试类*/
public class AccountServiceTest {public static void main(String[] args) {AccountService accountService = ServiceFactory.getAccountService();try {// 测试开户Account account = new Account();account.setUserId(1L);account.setAccountNumber("62220200010001");account.setAccountType(1);account.setCreateTime(new Date());boolean openResult = accountService.openAccount(account);System.out.println("开户结果: " + openResult);// 测试存款boolean depositResult = accountService.deposit(account.getId(), new BigDecimal("1000.00"), "测试存款");System.out.println("存款结果: " + depositResult);// 测试查询余额BigDecimal balance = accountService.getAccountBalance(account.getId());System.out.println("账户余额: " + balance);// 测试转账(需要先创建另一个账户)// boolean transferResult = accountService.transfer(account.getId(), 2L, new BigDecimal("500.00"), "测试转账");// System.out.println("转账结果: " + transferResult);} catch (BusinessException e) {System.err.println("业务异常: " + e.getErrorCode() + " - " + e.getErrorMessage());e.printStackTrace();}}
}
10. 最佳实践总结
10.1 业务层设计原则
- 单一职责原则:每个服务类只负责一个业务领域
- 依赖倒置原则:依赖抽象接口,不依赖具体实现
- 开闭原则:对扩展开放,对修改关闭
- 事务一致性原则:一个业务方法对应一个事务
10.2 业务方法设计要点
- 参数验证:在方法开始处验证所有输入参数
- 业务规则验证:验证业务规则和约束条件
- 事务边界:合理划分事务边界
- 异常处理:统一异常处理,提供有意义的错误信息
- 日志记录:记录重要的业务操作日志
10.3 性能考虑
- 数据库连接:合理使用连接池
- 事务粒度:控制事务粒度,避免长事务
- 批量操作:对批量操作进行优化
- 缓存策略:合理使用缓存提升性能
通过这样的业务层设计和实现,可以构建出结构清晰、可维护性强、业务逻辑完整的应用程序。