
??????教程全知識點(diǎn)簡介:學(xué)習(xí)目標(biāo) 一、Spring簡介 2 初識Spring 3 Spring體系結(jié)構(gòu) 二、IOC和DI入門案例【重點(diǎn)】 五、Bean的生命周期【了解】 問題導(dǎo)入 1 生命周期相關(guān)概念介紹 2 代碼演示 3 Bean銷毀時(shí)機(jī) 六、依賴注入(DI配置) 1 依賴注入方式【重點(diǎn)】 2 依賴自動裝配【理解】 3 集合注入 今日目標(biāo) 一、第三方資源配置管理 1 管理DataSource連接池對象 2 加載properties屬性文件【重點(diǎn)】 四、Spring整合其他技術(shù)【重點(diǎn)】 二、AOP案例 1 案例-測量業(yè)務(wù)層接口萬次執(zhí)行效率 2 AOP切入點(diǎn)數(shù)據(jù)獲取 2 Spring事務(wù)角色【理解】 二、請求與響應(yīng) 1 請求映射路徑【重點(diǎn)】 2 請求參數(shù) 3 日期類型參數(shù)傳遞【重點(diǎn)】 4 響應(yīng) 三、REST風(fēng)格 1 REST簡介 2 RESTful入門案例 3 REST快速開發(fā)【重點(diǎn)】 今日內(nèi)容 一、SSM整合【重點(diǎn)】 1 SSM整合配置 三、異常處理器【理解】 1 異常介紹 2 異常處理器 一、分模塊開發(fā)與設(shè)計(jì) 1. 分模塊開發(fā)的意義 模塊拆分原則 2. 分模塊開發(fā)(模塊拆分) 二、依賴管理 1. 依賴傳遞 2. 可選依賴 4 可選依賴和排除依賴的區(qū)別 三、聚合與繼承 1. 聚合工程 3. 繼承關(guān)系 5. 聚合與繼承的區(qū)別 四、屬性管理 1. 屬性 2. 版本管理 五、多環(huán)境配置與應(yīng)用 1. 多環(huán)境配置作用 2. 跳過測試(了解) 六、私服 2. 私服倉庫分類 3. 資源上傳與下載 附件1:POM文件總體配置說明 一、MyBatisPlus簡介 1. 入門案例 二、標(biāo)準(zhǔn)數(shù)據(jù)層開發(fā) 2. Lombok插件介紹 四、DML編程控制 1. id生成策略控制(Insert) 2. 多記錄操作(批量Delete/Select) 3. 邏輯刪除(Delete/Update) 4. 樂觀鎖(Update)

??????????git倉庫code.zip 直接get:???https://gitlab.com/yiqing112/backend/-/blob/main/Java/Java熱門框架深入開發(fā)/note.md ???????
? 本教程項(xiàng)目亮點(diǎn)
?? 知識體系完整:覆蓋從基礎(chǔ)原理、核心方法到高階應(yīng)用的全流程內(nèi)容
?? 全技術(shù)鏈覆蓋:完整前后端技術(shù)棧,涵蓋開發(fā)必備技能
?? 從零到實(shí)戰(zhàn):適合 0 基礎(chǔ)入門到提升,循序漸進(jìn)掌握核心能力
?? 豐富文檔與代碼示例:涵蓋多種場景,可運(yùn)行、可復(fù)用
?? 工作與學(xué)習(xí)雙參考:不僅適合系統(tǒng)化學(xué)習(xí),更可作為日常開發(fā)中的查閱手冊
?? 模塊化知識結(jié)構(gòu):按知識點(diǎn)分章節(jié),便于快速定位和復(fù)習(xí)
?? 長期可用的技術(shù)積累:不止一次學(xué)習(xí),而是能伴隨工作與項(xiàng)目長期參考
??????全教程總章節(jié)


??????本篇主要內(nèi)容
二、AOP案例
1 案例-測量業(yè)務(wù)層接口萬次執(zhí)行效率
問題導(dǎo)入
能不能描述一下環(huán)繞通知里面的實(shí)現(xiàn)步驟?
1.1 需求和分析
需求:任意業(yè)務(wù)層接口執(zhí)行均可顯示其執(zhí)行效率(執(zhí)行時(shí)長)
分析:
①:業(yè)務(wù)功能:業(yè)務(wù)層接口執(zhí)行前后分別記錄時(shí)間,求差值得到執(zhí)行效率
②:通知類型選擇前后均可以增強(qiáng)的類型——環(huán)繞通知
1.2 代碼實(shí)現(xiàn)
【前置工作】環(huán)境準(zhǔn)備
Spring整合mybatis對spring_db數(shù)據(jù)庫中的Account進(jìn)行CRUD操作
Spring整合Junit測試CRUD是否OK。
在pom.xml中添加aspectjweaver切入點(diǎn)表達(dá)式依賴
... ...
【第一步】編寫通知類
@Component
@Aspect
public class ProjectAdvice {
//匹配業(yè)務(wù)層的所有方法
@Pointcut("execution(* com.itheima.service.*Service.*(..))")
private void servicePt(){}
//設(shè)置環(huán)繞通知,在原始操作的運(yùn)行前后記錄執(zhí)行時(shí)間
@Around("ProjectAdvice.servicePt()") //本類類名可以省略不寫
public void runSpeed(ProceedingJoinPoint pjp) throws Throwable {
//獲取執(zhí)行的簽名對象
Signature signature = pjp.getSignature();
//獲取接口/類全限定名
String className = signature.getDeclaringTypeName();
//獲取方法名
String methodName = signature.getName();
//記錄開始時(shí)間
long start = System.currentTimeMillis();
//執(zhí)行萬次操作
for (int i = 0; i < 10000; i++) {
pjp.proceed();
}
//記錄結(jié)束時(shí)間
long end = System.currentTimeMillis();
//打印執(zhí)行結(jié)果
System.out.println("萬次執(zhí)行:"+ className+"."+methodName+"---->" +(end-start) + "ms");
}
}
【第二步】在SpringConfig配置類上開啟AOP注解功能
@Configuration
@ComponentScan("com.itheima")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class,MybatisConfig.class})
@EnableAspectJAutoProxy //開啟AOP注解功能
public class SpringConfig {
}
【第三步】運(yùn)行測試類,查看結(jié)果
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class AccountServiceTestCase {
@Autowired
private AccountService accountService;
@Test
public void testFindById(){
Account account = accountService.findById(2);
}
@Test
public void testFindAll(){
List<Account> list = accountService.findAll();
}
}

2 AOP切入點(diǎn)數(shù)據(jù)獲取
問題導(dǎo)入
在環(huán)繞通知中可以獲取到哪些數(shù)據(jù)?
2.1 獲取參數(shù)
說明:在前置通知和環(huán)繞通知中都可以獲取到連接點(diǎn)方法的參數(shù)們
- JoinPoint對象描述了連接點(diǎn)方法的運(yùn)行狀態(tài),可以獲取到原始方法的調(diào)用參數(shù)
@Before("pt()")
public void before(JoinPoint jp) {
Object[] args = jp.getArgs(); //獲取連接點(diǎn)方法的參數(shù)們
System.out.println(Arrays.toString(args));
}
- ProccedJointPoint是JoinPoint的子類
@Around("pt()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
Object[] args = pjp.getArgs(); //獲取連接點(diǎn)方法的參數(shù)們
System.out.println(Arrays.toString(args));
Object ret = pjp.proceed();
return ret;
}
2.2 獲取返回值
說明:在返回后通知和環(huán)繞通知中都可以獲取到連接點(diǎn)方法的返回值
- 拋出異常后通知可以獲取切入點(diǎn)方法中出現(xiàn)的異常信息,使用形參可以接收對應(yīng)的異常對象
@AfterReturning(value = "pt()",returning = "ret")
public void afterReturning(String ret) { //變量名要和returning="ret"的屬性值一致
System.out.println("afterReturning advice ..."+ret);
}
- 環(huán)繞通知中可以手工書寫對原始方法的調(diào)用,得到的結(jié)果即為原始方法的返回值
@Around("pt()")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
// 手動調(diào)用連接點(diǎn)方法,返回值就是連接點(diǎn)方法的返回值
Object ret = pjp.proceed();
return ret;
}
2.3 獲取異常
說明:在拋出異常后通知和環(huán)繞通知中都可以獲取到連接點(diǎn)方法中出現(xiàn)的異常
- 拋出異常后通知可以獲取切入點(diǎn)方法中出現(xiàn)的異常信息,使用形參可以接收對應(yīng)的異常對象
@A
## 三、Spring事務(wù)管理
### 1 Spring事務(wù)簡介【重點(diǎn)】
#### 問題導(dǎo)入
Spring提供的事務(wù)管理是數(shù)據(jù)層的事務(wù)還是業(yè)務(wù)層的事務(wù)?
#### 1.1 Spring事務(wù)作用
- 事務(wù)作用:在數(shù)據(jù)層保障一系列的數(shù)據(jù)庫操作同成功同失敗
- Spring事務(wù)作用:在數(shù)據(jù)層或**==業(yè)務(wù)層==**保障一系列的數(shù)據(jù)庫操作同成功同失敗

#### 1.2 需求和分析
- 需求:實(shí)現(xiàn)任意兩個(gè)賬戶間轉(zhuǎn)賬操作
- 需求微縮:A賬戶減錢,B賬戶加錢
- 分析:
①:數(shù)據(jù)層提供基礎(chǔ)操作,指定賬戶減錢(outMoney),指定賬戶加錢(inMoney)
②:業(yè)務(wù)層提供轉(zhuǎn)賬操作(transfer),調(diào)用減錢與加錢的操作
③:提供2個(gè)賬號和操作金額執(zhí)行轉(zhuǎn)賬操作
④:基于Spring整合MyBatis環(huán)境搭建上述操作
- 結(jié)果分析:
①:程序正常執(zhí)行時(shí),賬戶金額A減B加,沒有問題
②:程序出現(xiàn)異常后,轉(zhuǎn)賬失敗,但是異常之前操作成功,異常之后操作失敗,整體業(yè)務(wù)失敗
#### 1.3 代碼實(shí)現(xiàn)
##### 【前置工作】環(huán)境準(zhǔn)備
> Spring整合Mybatis相關(guān)代碼(依賴、JdbcConfig、MybatisConfig、SpringConfig)省略。
```java
public interface AccountDao {
@Update("update tbl_account set money = money + #{money} where name = #{name}")
void inMoney(@Param("name") String name, @Param("money") Double money);
@Update("update tbl_account set money = money - #{money} where name = #{name}")
void outMoney(@Param("name") String name, @Param("money") Double money);
}
public interface AccountService {
/**
* 轉(zhuǎn)賬操作
* @param out 傳出方
* @param in 轉(zhuǎn)入方
* @param money 金額
*/
public void transfer(String out,String in ,Double money) ;
}
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
public void transfer(String out,String in ,Double money) {
accountDao.outMoney(out,money);
int i = 1/0;
accountDao.inMoney(in,money);
}
[Vaadin 文檔](https://vaadin.com/docs)
[Checkstyle 文檔](https://checkstyle.sourceforge.io/)
}
【第一步】在業(yè)務(wù)層接口上添加Spring事務(wù)管理
public interface AccountService {
//配置當(dāng)前接口方法具有事務(wù)
@Transactional
public void transfer(String out,String in ,Double money) ;
}
注意事項(xiàng)
- Spring注解式事務(wù)通常添加在業(yè)務(wù)層接口中而不會添加到業(yè)務(wù)層實(shí)現(xiàn)類中,降低耦合
- 注解式事務(wù)可以添加到業(yè)務(wù)方法上表示當(dāng)前方法開啟事務(wù),也可以添加到接口上表示當(dāng)前接口所有方法開啟事務(wù)
【第二步】設(shè)置事務(wù)管理器(將事務(wù)管理器添加到IOC容器中)
說明:可以在JdbcConfig中配置事務(wù)管理器
//配置事務(wù)管理器,mybatis使用的是jdbc事務(wù)
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource){
DataSourceTransactionManager dtm = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
注意事項(xiàng)
- 事務(wù)管理器要根據(jù)實(shí)現(xiàn)技術(shù)進(jìn)行選擇
- MyBatis框架使用的是JDBC事務(wù)
【第三步】開啟注解式事務(wù)驅(qū)動
@Configuration
@ComponentScan("com.itheima")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class,MybatisConfig.class})
//開啟注解式事務(wù)驅(qū)動
@EnableTransactionManagement
public class SpringConfig {
}
【第四步】運(yùn)行測試類,查看結(jié)果
[FastJSON 文檔](https://github.com/alibaba/fastjson)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class AccountServiceTest {
@Autowired
private AccountService accountService;
@Test
public void testTransfer() throws IOException {
accountService.transfer("Tom","Jerry",100D);
}
}
2 Spring事務(wù)角色【理解】
問題導(dǎo)入
什么是事務(wù)管理員,什么是事務(wù)協(xié)調(diào)員?