Files
springboot-scaffold/target/classes/static/ioc.html
likingcode c04235c655 feat: Spring Boot 学习脚手架 v2.0
- 新增 IoC 容器学习模块
- 新增 AOP 切面编程学习模块
- 新增 MyBatis 集成学习模块
- 新增事务管理学习模块
- 新增用户/产品/订单 CRUD
- 新增 7 个交互式学习页面
- 集成性能监控切面
2026-03-07 08:37:40 +00:00

175 lines
8.8 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>IoC 容器学习 - Spring Boot</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: #f5f5f5; }
.container { max-width: 1400px; margin: 0 auto; padding: 20px; }
.header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px 20px; text-align: center; margin-bottom: 20px; border-radius: 10px; }
.header h1 { font-size: 2em; }
.nav { display: flex; gap: 10px; margin-bottom: 20px; flex-wrap: wrap; justify-content: center; }
.nav a { padding: 10px 20px; background: white; border-radius: 20px; text-decoration: none; color: #333; font-size: 0.9em; }
.nav a:hover, .nav a.active { background: #667eea; color: white; }
.card { background: white; border-radius: 10px; padding: 20px; margin-bottom: 20px; box-shadow: 0 2px 10px rgba(0,0,0,0.08); }
.card h3 { color: #667eea; margin-bottom: 15px; border-bottom: 2px solid #eee; padding-bottom: 10px; }
.concept-box { background: #f8f9fa; border-left: 4px solid #667eea; padding: 15px; margin: 10px 0; border-radius: 5px; }
.concept-box h4 { color: #333; margin-bottom: 10px; }
.btn { padding: 10px 20px; background: #667eea; color: white; border: none; border-radius: 5px; cursor: pointer; margin: 5px; }
.btn:hover { background: #5a6fd6; }
.btn-secondary { background: #6c757d; }
.result { background: #1e1e1e; color: #d4d4d4; padding: 15px; border-radius: 5px; margin-top: 10px; font-family: monospace; font-size: 0.9em; overflow-x: auto; max-height: 400px; overflow-y: auto; }
table { width: 100%; border-collapse: collapse; margin: 10px 0; }
th, td { padding: 10px; text-align: left; border-bottom: 1px solid #eee; }
th { background: #f8f9fa; font-weight: 600; }
tr:hover { background: #f8f9fa; }
.badge { padding: 4px 8px; border-radius: 4px; font-size: 0.8em; }
.badge-primary { background: #667eea; color: white; }
.badge-success { background: #28a745; color: white; }
.badge-warning { background: #ffc107; color: #333; }
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>📦 IoC 容器学习</h1>
<p>控制反转 (Inversion of Control) 与依赖注入 (Dependency Injection)</p>
</div>
<div class="nav">
<a href="index.html">🏠 首页</a>
<a href="ioc.html" class="active">📦 IoC</a>
<a href="aop.html">🔪 AOP</a>
<a href="mybatis.html">💾 MyBatis</a>
<a href="transaction.html">🔄 事务</a>
<a href="users.html">👥 用户</a>
<a href="api.html">🔌 API</a>
</div>
<div class="card">
<h3>📚 核心概念</h3>
<div class="concept-box">
<h4>什么是 IoC</h4>
<p><strong>控制反转 (Inversion of Control)</strong>:将对象的创建和管理交给 Spring 容器,而不是由开发者手动创建。</p>
<p><strong>依赖注入 (Dependency Injection)</strong>IoC 的一种实现方式通过构造器、Setter 或字段将依赖注入到对象中。</p>
</div>
<div class="concept-box">
<h4>为什么用 IoC</h4>
<ul>
<li><strong>解耦</strong>:对象之间不直接依赖,通过接口交互</li>
<li><strong>可测试</strong>:方便使用 Mock 对象进行单元测试</li>
<li><strong>可维护</strong>:集中管理对象生命周期</li>
<li><strong>AOP 支持</strong>:便于实现切面编程</li>
</ul>
</div>
</div>
<div class="card">
<h3>🔍 查看所有 Bean</h3>
<p>Spring 容器中管理的所有 Bean 对象</p>
<button class="btn" onclick="loadBeans()">刷新 Bean 列表</button>
<button class="btn btn-secondary" onclick="document.getElementById('beansResult').innerHTML=''">清空</button>
<div id="beansResult" class="result"></div>
</div>
<div class="card">
<h3>📊 Bean 作用域</h3>
<table>
<tr><th>作用域</th><th>说明</th><th>使用场景</th></tr>
<tr><td><span class="badge badge-primary">singleton</span></td><td>默认,整个应用只有一个实例</td><td>无状态的服务、配置类</td></tr>
<tr><td><span class="badge badge-success">prototype</span></td><td>每次请求都创建新实例</td><td>有状态的对象</td></tr>
<tr><td><span class="badge badge-warning">request</span></td><td>每个 HTTP 请求一个实例</td><td>Web 应用</td></tr>
<tr><td><span class="badge badge-warning">session</span></td><td>每个 HTTP 会话一个实例</td><td>用户会话数据</td></tr>
</table>
<button class="btn" onclick="testScopes()">测试作用域</button>
<div id="scopesResult" class="result"></div>
</div>
<div class="card">
<h3>⚡ 性能统计</h3>
<p>实时监控方法执行时间和调用次数</p>
<button class="btn" onclick="loadPerformance()">刷新统计</button>
<button class="btn btn-secondary" onclick="resetPerformance()">重置统计</button>
<div id="performanceResult" class="result"></div>
</div>
<div class="card">
<h3>💉 依赖注入方式对比</h3>
<table>
<tr><th>方式</th><th>优点</th><th>缺点</th><th>推荐度</th></tr>
<tr><td>构造器注入</td><td>明确依赖、不可变、易测试</td><td>参数多时代码长</td><td>⭐⭐⭐⭐⭐</td></tr>
<tr><td>Setter 注入</td><td>可选依赖、灵活</td><td>可能为 null</td><td>⭐⭐⭐</td></tr>
<tr><td>字段注入</td><td>代码简洁</td><td>隐藏依赖、难测试</td><td></td></tr>
</table>
</div>
</div>
<script>
async function loadBeans() {
const result = document.getElementById('beansResult');
result.textContent = '加载中...';
try {
const res = await fetch('/api/learning/ioc/beans');
const data = await res.json();
result.innerHTML = `<strong>总 Bean 数: ${data.total}</strong>\n\n用户相关 Bean:\n${data.userBeans.map(b => ' - ' + b).join('\n')}`;
} catch (e) {
result.textContent = '加载失败: ' + e.message;
}
}
async function testScopes() {
const result = document.getElementById('scopesResult');
try {
const res = await fetch('/api/learning/ioc/scopes');
const data = await res.json();
result.innerHTML = JSON.stringify(data, null, 2);
} catch (e) {
result.textContent = '测试失败: ' + e.message;
}
}
async function loadPerformance() {
const result = document.getElementById('performanceResult');
result.textContent = '加载中...';
try {
const res = await fetch('/api/learning/ioc/performance');
const data = await res.json();
if (Object.keys(data).length === 0) {
result.textContent = '暂无性能数据,请先调用一些 API';
return;
}
let html = '<table><tr><th>方法</th><th>调用次数</th><th>错误数</th><th>平均耗时(ms)</th><th>最大耗时(ms)</th></tr>';
for (const [key, val] of Object.entries(data)) {
html += `<tr><td>${key}</td><td>${val.count}</td><td>${val.errors}</td><td>${val.avgMs}</td><td>${val.maxMs}</td></tr>`;
}
html += '</table>';
result.innerHTML = html;
} catch (e) {
result.textContent = '加载失败: ' + e.message;
}
}
async function resetPerformance() {
try {
await fetch('/api/learning/ioc/performance/reset', { method: 'POST' });
loadPerformance();
} catch (e) {
alert('重置失败: ' + e.message);
}
}
loadBeans();
loadPerformance();
</script>
</body>
</html>