WASNL-学习笔记
type: channel
link: https://note.wasnl.com/
description: 个人学习笔记
items: Spring MVC 知识地图
items: Spring MVC 请求生命周期
items: java
items: 反射 + AOP + 注解
items: JdbcTemplate
items: 未命名文档
items: Java随心记
items: Java 反射与动态代理 详细笔记
items: test
items: AI 开发治理入门笔记（初学者实战版）

Spring MVC 知识地图
type: item
date: 2026-06-10T18:36:08+08:00
description: 🌐 Spring MVC 知识地图一、核心架构与组件Spring MVC 核心 ├── DispatcherServlet（前端控制器） ├── HandlerMapping（处理器映射） │ ├── RequestMappingHandlerMapping （注解映射，最常用） │ ├── BeanNameUrlHandlerMapping │ └── SimpleUrlHandlerMapping ├── HandlerAdapter（处理器适配器） │ ├── RequestMappingHandlerAdapter │ ├── HttpRequestHandlerAdapter │ └── SimpleControllerHandlerAdapter ├── Handler / Controller（处理器） ├── ModelAndView（模型与视图封装） ├── ViewResolver（视图解析器） │ ├── InternalResourceViewResolver（JSP） │ ├── BeanNameViewResolver │ ├── XmlViewResolver │ ├── ContentNegotiatingViewResolver │ └── …… └── View（视图） ├── JSP / JSTL ├── Thymeleaf ├── FreeMarker └── ……二、请求处理完整流程客户端请求 → DispatcherServlet 接收 ├── 1. 通过 HandlerMapping 查找 Handler（返回 HandlerExecutionChain，包含拦截器） ├── 2. 通过 HandlerAdapter 执行 Handler（Controller） ├── 3. Handler 执行业务逻辑，返回 ModelAndView ├── 4. 通过 ViewResolver 解析 ModelAndView 得到 View 对象 └── 5. View 渲染，将模型数据填充到视图，生成响应三、控制器开发Controller 开发 ├── 注解 │ ├── @Controller / @RestController │ ├── @RequestMapping │ │ ├── @GetMapping │ │ ├── @PostMapping │ │ ├── @PutMapping │ │ ├── @DeleteMapping │ │ └── @PatchMapping │ └── @CrossOrigin（跨域） ├── 请求参数绑定 │ ├── @RequestParam │ ├── @PathVariable（路径变量） │ ├── @RequestHeader │ ├── @CookieValue │ ├── @MatrixVariable │ ├── @RequestBody（JSON/XML 等） │ ├── @ModelAttribute（表单/查询参数绑定到对象） │ ├── HttpServletRequest / HttpServletResponse │ └── MultipartFile（文件上传） ├── 返回类型 │ ├── String（视图名，配合 Model） │ ├── ModelAndView │ ├── void（直接操作 HttpServletResponse） │ ├── @ResponseBody / ResponseEntity（JSON/XML 响应） │ └── View、Model、Map 等 └── 异步处理 ├── Callable<T> ├── DeferredResult<T> └── ResponseBodyEmitter / SseEmitter / StreamingResponseBody四、数据绑定、类型转换与校验数据绑定与校验 ├── 类型转换 │ ├── PropertyEditor │ ├── Converter / ConverterFactory │ ├── Formatter（日期/数字等格式化） │ └── @InitBinder（自定义绑定规则，注册编辑器/校验器） ├── 数据校验 │ ├── JSR-380（Bean Validation）：@Valid / @Validated │ ├── BindingResult / Errors（校验结果） │ └── 自定义校验注解 └── WebDataBinder └── 控制绑定行为（允许/禁止字段等）五、RESTful Web 服务REST 支持 ├── @RestController = @Controller + @ResponseBo…

Spring MVC 请求生命周期
type: item
date: 2026-06-10T17:17:33+08:00
description: Spring MVC 请求生命周期SpringBoot 2.7 + Java8 企业级开发一、整体架构图 —— 一次请求的完整流水线HTTP Request -> http://你的项目/getUser?id=1 │ ▼ ┌─────────────────────┐ │ Tomcat │ 内嵌 Servlet 容器，最早接收请求 │ Servlet Container │ └─────────────────────┘ │ ▼ ┌─────────────────────┐ │ Filter 过滤器链 │ Servlet 级别的“门卫”，工作在 Spring MVC 之前 └─────────────────────┘ │ ▼ ┌─────────────────────┐ │ DispatcherServlet │ Spring MVC 的“总控”，分发请求的核心 └─────────────────────┘ │ ▼ ┌─────────────────────┐ │ HandlerInterceptor │ Spring 自己的拦截器，更懂 Controller │ preHandle │ 请求到达 Controller 前执行 └─────────────────────┘ │ ▼ ┌─────────────────────┐ │ Controller │ 你写的接口，@RestController / @GetMapping └─────────────────────┘ │ ▼ ┌─────────────────────┐ │ Service │ 业务逻辑层 └─────────────────────┘ │ ▼ ┌─────────────────────┐ │ DAO/JdbcTemplate │ 数据访问层，执行 SQL └─────────────────────┘ │ ▼ ┌─────────────────────┐ │ MySQL │ 数据库 └─────────────────────┘ │ ▼ Controller返回结果 返回 Java 对象 │ ▼ Interceptor.postHandle 所有拦截器的 postHandle │ ▼ ViewResolver / JSON序列化 前后端分离时转成 JSON 字符串 │ ▼ Interceptor.afterCompletion 资源清理、日志记录 │ ▼ Response → 浏览器二、企业项目真实执行顺序（必背）虚假的顺序：Tomcat -> Interceptor -> Controller实际严格顺序：Tomcat -> Filter -> DispatcherServlet -> Interceptor -> Controller -> Service -> DAO -> MySQL为什么是这个顺序？Filter 是 Servlet 规范 定义的，工作在容器级别，比 Spring 更底层；Interceptor 是 Spring MVC 内部 的，只有在 DispatcherServlet 接收请求之后才生效。也就是说：Filter 可以拦截所有请求（包括静态资源），而 Interceptor 只能拦截进入 Spring MVC 的请求。三、Filter 和 Interceptor 区别 —— 两个不同级别的“保安”1. Filter（Servlet 级别）定义方式：实现 javax.servlet.Filter 接口执行时机：Tomcat → Filter → Spring MVC特点：工作在容器层，不依赖 Spring，拿不到 Controller、方法等 Spring 上下文信息。典型用途：JWT 登录校验（直接解析 token，失败直接返回 401）XSS 过滤（清洗 等危险字符）请求日志（记录每个请求的耗时、URL）跨域处理（CorsFilter 统一设置响应头）2. Interceptor（Spring MVC 级别）定义方式：实现 org.springframework.web.servlet.HandlerInterceptor 接口执行时机：DispatcherServlet → Interceptor → Controller特点：能获取到 Handler（Controller 方法）、参数、返回结果等，是 Spring 生态内的拦截手段。典型用途：用户信息注入（从 token 解析用户信息，放入 UserContext）权限校验（admin / user 角色判断）操作日志（记录“谁在何时做了什么”）API 访问统计（PV / UV 计数）面试标准答案Filter 先执行，Interceptor 后执行。…

java
type: item
date: 2026-06-08T18:30:14+08:00
description: 1. 策略模式 ⭐⭐⭐⭐⭐消灭 if-else 的核心武器，基于 Spring 容器自动选择策略。步骤：定义策略接口public interface Strategy { String getType(); void execute(); }实现多个策略并用 @Component 注册@Component public class StrategyA implements Strategy { @Override public String getType() { return "A"; } @Override public void execute() { /* ... */ } } @Component public class StrategyB implements Strategy { @Override public String getType() { return "B"; } @Override public void execute() { /* ... */ } }创建策略选择器@Component public class StrategySelector { private final Map<String, Strategy> strategyMap = new HashMap<>(); // 4. Spring自动注入所有Strategy实现到Map（详见文档末尾“注入条件”） public StrategySelector(Map<String, Strategy> strategyMap) { // 遍历注入的Map，按业务key重组 strategyMap.values().forEach(s -> this.strategyMap.put(s.getType(), s)); } // 5. 选择策略 public Strategy getStrategy(String type) { Strategy strategy = strategyMap.get(type); if (strategy == null) { throw new IllegalArgumentException("No strategy for: " + type); } return strategy; } }2. 工厂模式 ⭐⭐⭐⭐⭐创建对象的“万能工厂”，通过 Spring 容器自动装配产品族。步骤：定义产品接口public interface Product { String getType(); void doSomething(); }多个产品实现并注册@Component public class ProductA implements Product { @Override public String getType() { return "A"; } @Override public void doSomething() { /*...*/ } } @Component public class ProductB implements Product { @Override public String getType() { return "B"; } @Override public void doSomething() { /*...*/ } }创建工厂类（Spring自动注入所有产品）@Component public class ProductFactory { private final Map<String, Product> productMap; // 构造器注入：Spring会将所有Product的实现注入到Map中（key=bean名称，默认类名首字母小写） public ProductFactory(Map<String, Product> productMap) { this.productMap = productMap; } public Product create(String type) { Product product = productMap.get(type); // 或自定义getType()映射 if (product == null) throw new IllegalArgumentException("Unknown product type"); return product; } }与策略模式的区别：工厂侧重于创建/获取对象，策略侧重行为互换，但 Spring 集成写法相似。3. 责任链模式 ⭐⭐⭐⭐⭐多个处理器依次尝试，直到有人处理。步骤：定义请求上下文public class RequestContext { private boolean…

反射 + AOP + 注解
type: item
date: 2026-06-03T16:33:01+08:00
description: 反射 + AOP + 注解 讲解目录注解（Annotation）什么是注解元注解与自定义注解如何在反射中读取注解反射（Reflection）反射的核心类：Class、Method、Field动态创建对象、调用方法、访问字段反射与注解的结合AOP（面向切面编程）AOP 的核心概念Spring AOP 的实现原理（代理）通知类型与切入点表达式如何在切面中使用反射和注解三剑合璧实战案例案例1：自定义 @Log 日志记录案例2：自定义 @RequirePermission 权限控制总结与关系图谱一、注解（Annotation）1.1 什么是注解？注解是 Java 5 引入的一种元数据，它本身不影响代码逻辑，但可以被编译、运行时工具或框架读取，从而赋予代码额外的语义或行为。常见注解如 @Override、@Deprecated、@Autowired 等。1.2 元注解定义注解时需要用到的注解，共有四个：元注解作用@Target指定注解能用在哪里（类、方法、字段等）@Retention指定注解的存活周期（源码、字节码、运行时）@Documented是否包含在 JavaDoc 中@Inherited是否允许子类继承父类的注解@Retention 的取值：RetentionPolicy.SOURCE：只在源码中存在，编译时丢弃（如 @Override）RetentionPolicy.CLASS：在字节码中存在，但运行时不可见（默认）RetentionPolicy.RUNTIME：运行时可通过反射读取（自定义注解必须选这个）1.3 自定义一个注解import java.lang.annotation.*; @Target(ElementType.METHOD) // 只能用在方法上 @Retention(RetentionPolicy.RUNTIME) // 运行时保留 public @interface Loggable { String value() default ""; // 注解属性 }使用：@Loggable("删除用户") public void deleteUser(Long id) { ... }1.4 在反射中读取注解无论是类、方法还是字段，反射 API 都提供了读取注解的方法：getAnnotation(Class<T> annotationClass) —— 获取指定类型的注解getAnnotations() —— 获取所有注解（含继承）getDeclaredAnnotations() —— 获取直接声明的注解（不含继承）isAnnotationPresent(Class<?> annotationClass) —— 判断是否存在某注解示例：读取方法上的 @LoggableMethod method = ...; // 通过反射拿到方法对象 Loggable log = method.getAnnotation(Loggable.class); if (log != null) { System.out.println("描述：" + log.value()); }二、反射（Reflection）2.1 反射的核心类类作用获取方式Class类的元信息对象.getClass()、类名.class、Class.forName("全类名")Method方法信息Class 对象的 getMethod(...)、getDeclaredMethods() 等Field字段信息Class 对象的 getField(...)、getDeclaredFields() 等Constructor构造器信息Class 对象的 getConstructor(...)、getDeclaredConstructors() 等2.2 获取 Class 对象的三种方式// 1. 通过类名.class Class<String> clz1 = String.class; // 2. 通过实例的 getClass() String s = "hello"; Class<?> clz2 = s.getClass(); // 3. 通过完全限定名字符串 Class<?> clz3 = Class.forName("java.lang.String");2.3 获取 Method 对象方法说明getMethod(name, paramTypes...)获取指定名称和参数的 public 方法（含继承）getMethods()获取所有 public 方法（含继承）getDeclaredMethod(name, paramTypes...)获取本类中声明的方法（不含继承，可访问私有）getDeclaredMethods()获取本类中声明的所有方法（不含继承）示例：获…

JdbcTemplate
type: item
date: 2026-06-03T11:29:59+08:00
description: Spring JDBC + JdbcTemplate 学习笔记（方法驱动格式）本笔记聚焦于 JdbcTemplate 中常用的数据库操作方法。每个方法均按以下结构介绍：方法：方法签名/名称作用：该方法解决什么问题参数：主要参数的含义和类型方法案例：代码示例（可直接运行）实例说明：对案例的详细解释，包括注意事项前置环境：Spring 6 + HikariCP + HSQLDB，配置了 DataSource 和 JdbcTemplate Bean。第一章：准备工作与环境配置1.1 Maven 依赖<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>6.0.0</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>6.0.0</version> </dependency> <dependency> <groupId>com.zaxxer</groupId> <artifactId>HikariCP</artifactId> <version>5.0.1</version> </dependency> <dependency> <groupId>org.hsqldb</groupId> <artifactId>hsqldb</artifactId> <version>2.7.1</version> </dependency>1.2 Spring 配置类（AppConfig）@Configuration @ComponentScan @PropertySource("jdbc.properties") public class AppConfig { @Value("${jdbc.url}") String jdbcUrl; @Value("${jdbc.username}") String jdbcUsername; @Value("${jdbc.password}") String jdbcPassword; @Bean DataSource dataSource() { HikariConfig config = new HikariConfig(); config.setJdbcUrl(jdbcUrl); config.setUsername(jdbcUsername); config.setPassword(jdbcPassword); return new HikariDataSource(config); } @Bean JdbcTemplate jdbcTemplate(DataSource dataSource) { return new JdbcTemplate(dataSource); } }1.3 数据库初始化（自动建表）@Component public class DatabaseInitializer { @Autowired JdbcTemplate jdbcTemplate; @PostConstruct void init() { jdbcTemplate.update("CREATE TABLE IF NOT EXISTS users (" + "id BIGINT IDENTITY PRIMARY KEY, " + "email VARCHAR(100) NOT NULL UNIQUE, " + "password VARCHAR(100), " + "name VARCHAR(100))"); } }第二章：核心方法详解（按格式组织）方法一：queryForObject() – 查询单行记录并映射为对象作用：执行查询 SQL，期望返回一条记录，并将结果集的第一行通过 RowMapper 转换成 Java 对象。若查询结果为空或大于一行则抛出异常。参数：String sql – SQL 语句（可使用 ? 占位符）RowMapper<T> rowMapper – 将 ResultSet 当前行映射为 T 对象的函数式接口Object... args – 可变参数，按顺序替换 SQL 中的 ?方法案例：根据 email 查询用户public User getUserByEmail(String email) { String sql = "SELECT id, email, password, name FROM users WHERE email = ?"; ret…

未命名文档
type: item
date: 2026-06-02T17:14:54+08:00
description: 注意：Java 8 环境下，javax.annotation（@PostConstruct、@PreDestroy、@Resource）是 JDK 自带的，无需额外添加依赖。Spring Boot 2.7 使用 Spring Framework 5.x，完美支持 JSR-250 规范。一、Bean 的作用域（Scope）Spring 中的 Bean 默认是 单例（Singleton），即整个容器内只有一个实例。也可以通过 @Scope 指定为 原型（Prototype），每次获取都创建新实例。1.1 Singleton（单例）—— 默认创建时机：容器启动时（除非设置为 @Lazy）。销毁时机：容器正常关闭时，会调用 @PreDestroy 方法。获取结果：每次注入或 getBean() 返回同一个对象。@Component // 默认 singleton public class MailService { // ... }1.2 Prototype（原型）行为：每次获取（@Autowired 或 getBean）都会创建一个全新的实例。生命周期差异：容器负责创建 → 依赖注入 → 调用 @PostConstruct。容器不负责销毁：即使你在原型 Bean 中写了 @PreDestroy，Spring 不会自动调用它。需要你自己写代码清理（例如手动调用销毁方法）。声明方式：@Component @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) // 或 @Scope("prototype") public class MailSession { @PostConstruct public void init() { System.out.println("原型 Bean 初始化，每次都会调用"); } @PreDestroy public void destroy() { System.out.println("原型 Bean 销毁 — 不会被 Spring 自动调用"); } }最佳实践：如果没有特殊需求，优先使用 singleton。prototype 适合那些有状态且不宜共享的对象，但要记得手动管理资源释放。二、注入 List —— 自动收集同一类型的所有 Bean当你需要在一个地方使用某个接口的 所有实现类 时，可以直接注入 List<T>，Spring 会自动把该接口的所有 Bean 放进列表。示例：多个 Validator 实现public interface Validator { void validate(String email, String password, String name); } @Component // 自动被收集 public class EmailValidator implements Validator { @Override public void validate(String email, String password, String name) { // email 校验逻辑 } } @Component public class PasswordValidator implements Validator { @Override public void validate(String email, String password, String name) { // password 校验逻辑 } } @Component public class NameValidator implements Validator { @Override public void validate(String email, String password, String name) { // name 校验逻辑 } }注入 List@Component public class Validators { @Autowired private List<Validator> validators; // Spring 自动注入所有 Validator 实现 public void validate(String email, String password, String name) { for (Validator v : validators) { v.validate(email, password, name); } } }控制顺序 —— @Order默认顺序不确定，可以用 @Order 注解指定（数字越小优先级越高）。@Component @Order(1) public class EmailValidator impleme…

Java随心记
type: item
date: 2026-06-02T14:19:53+08:00
description: 一、常用工具与集合操作1.1 Arrays.asList()作用：将数组转换为 List。注意：返回的 List 是固定大小的，不支持 add/remove 操作。List<String> list = Arrays.asList("a", "b", "c");1.2 CollUtil.toMap()（Hutool 工具）把一个 List 转换成 Map。参数1：要转换的列表。参数2：key 的生成方式（如 Stock::getSkuId）。参数3：value 的生成方式，Function.identity() 表示用对象本身作为 value。Map<Long, Stock> map = CollUtil.toMap(stocks, Stock::getSkuId, Function.identity());1.3 IdentityHashMap比较冷门，判断 key 是否相同依据 对象的引用地址（==），而不是 equals() / hashCode()。二、数据查询策略2.1 联表查询 vs 分开查 + Map 组装方式适用场景联表查询数据量不大、关联简单、不需要对查出的用户数据做额外处理分开查 + Map 组装数据分布在不同的服务器、微服务架构，或者需要灵活组装三、Java 集合框架3.1 集合体系概览Collection 是除 Map 外所有集合类的根接口。java.util 包主要提供三种类型的集合：List、Set、Map。统一使用 Iterator 遍历集合。3.2 ListArrayList：基于动态数组，内存连续。LinkedList：基于双向链表，节点有前后指针。List 允许添加 null。使用 List.of() 创建不可变 List（不支持 null 元素）。List<Integer> list = List.of(1, 2, 5);Iterator 遍历：boolean hasNext() 判断是否有下一个元素。E next() 返回下一个元素。boolean contains(Object o) 判断是否包含某元素。int indexOf(Object o) 返回元素索引，不存在返回 -1。重要：使用 contains()、indexOf() 等方法时，元素类必须正确覆写 equals()。String、Integer 等标准库类已经正确实现了 equals()，所以可以直接使用。3.3 编写 equals() 方法理论原则：自反性、对称性、传递性、一致性。实践写法（直接套用）：先确定实例相等的逻辑（哪些字段相等就算相等）。用 instanceof 判断类型，类型匹配后再比较字段。使用 Objects.equals() 比较引用类型字段，避免空指针。public boolean equals(Object o) { if (o instanceof Person p) { return Objects.equals(this.name, p.name) && this.age == p.age; } return false; }3.4 MapMap 遍历是无序的。底层是哈希表，通过哈希函数将 key 转换成数组下标，直接定位，查找速度极快 O(1)。作为 key 的对象必须正确覆写 equals() 和 hashCode()，相等的 key 调用 equals 必须返回 true。3.5 Queue 队列实现先进先出（FIFO）的数据结构。常用方法：add() / offer()：添加元素到队尾。remove() / poll()：从队首获取并删除元素。element() / peek()：从队首获取但不删除。避免将 null 添加到队列。四、编码与安全4.1 URL 编码使用 java.net.URLEncoder 对任意字符串进行 URL 编码。4.2 哈希算法目的：验证原始数据是否被篡改。MessageDigest 常见用途：计算文件校验和实现文件秒传存储用户密码防止数据重复生成 API 签名4.3 AES 加密最可靠的 AES 加密模式：AES-GCM。五、多线程与并发5.1 线程基础守护线程（Daemon）JVM 退出时不等待守护线程结束，直接强制终止。非守护线程（用户线程）结束时 JVM 才会退出。设置方法：在 start() 前调用 setDaemon(true)。核心业务线程不能设置为守护线程。典型用途：垃圾回收、日志监控、心跳检测。t.join()让当前线程等待 t 线程执行结束。生产环境禁用，容易造成阻塞，推荐用 Future 等异步方式。Thread.sleep(long millis)静态方法，哪个线程调用，哪个线程睡觉。线程中断线程结束即 run() 方法执行完毕。目标…

Java 反射与动态代理 详细笔记
type: item
date: 2026-06-02T11:51:50+08:00
description: Java 反射与动态代理 详细笔记一、反射的核心思想反射：在程序运行时，动态获取某个类的完整信息（类名、方法、字段、父类、接口等），并能动态创建对象、调用方法、访问字段。不需要在编译时知道具体类名，可以在运行时根据字符串类名加载类。常用于框架（Spring、MyBatis）、通用工具（IDE 自动补全）、动态代理等。二、Class 类：一切反射的入口2.1 每个类都有唯一的 Class 对象JVM 在第一次加载一个类时，会在内存中为该类创建一个 Class 实例（俗称“说明书”）。这个 Class 实例保存了该类的全部信息（类名、包、方法、字段、父类、接口等）。无论通过哪种方式获取，同一个类的 Class 实例是同一个对象（可用 == 比较）。2.2 获取 Class 实例的三种方法// 方法1：通过类名.class（最直接，编译时已知类） Class<String> cls1 = String.class; // 方法2：通过实例的 getClass() 方法 String s = "hello"; Class<?> cls2 = s.getClass(); // 实际返回 String.class // 方法3：通过 Class.forName(完整类名)（运行时根据字符串加载） Class<?> cls3 = Class.forName("java.lang.String");三者获得的是同一个 Class 对象：cls1 == cls2 == cls3三、通过反射访问字段（Field）3.1 获取字段的方法（返回值是 java.lang.reflect.Field）方法说明能否得到父类字段getField(String name)获取 public 字段（包括父类）✅ 能getDeclaredField(String name)获取当前类声明的任意字段（不限访问修饰符）❌ 不能，只看当前类getFields()获取所有 public 字段（包括父类）✅ 能getDeclaredFields()获取当前类声明的所有字段（不包括父类）❌ 不能3.2 访问私有字段通过 getDeclaredField 拿到私有 Field 对象后，调用 setAccessible(true) 打破封装。然后可以 get(obj) / set(obj, value) 读写该私有字段。class Person { private String name; } Class<Person> cls = Person.class; Field field = cls.getDeclaredField("name"); field.setAccessible(true); // 允许访问私有字段 Person p = new Person(); field.set(p, "Alice"); String name = (String) field.get(p); // "Alice"四、通过反射调用方法（Method）4.1 获取方法的方法（返回值是 java.lang.reflect.Method）方法说明包括父类getMethod(String name, Class<?>... parameterTypes)获取某个 public 方法✅ 包括getDeclaredMethod(...)获取当前类声明的某个方法（不限修饰符）❌ 不包括getMethods()获取所有 public 方法✅ 包括getDeclaredMethods()获取当前类声明的所有方法❌ 不包括4.2 调用方法拿到 Method 对象后，调用 invoke(Object obj, Object... args)。如果方法是 static，第一个参数传 null。// 示例：调用 String 的 length() 方法 String str = "hello"; Method m = String.class.getMethod("length"); int len = (int) m.invoke(str); // len = 5五、通过反射调用构造器（Constructor）5.1 获取构造器方法说明getConstructor(Class<?>... parameterTypes)获取某个 public 构造器getDeclaredConstructor(...)获取任意修饰符的构造器（包括 private）getConstructors() / getDeclaredConstructors()获取所有构造器5.2 创建实例通过 Constructor.newInstance(Object... initargs) 创建对象。比 Class.newInstance()…

test
type: item
date: 2026-05-27T11:53:45+08:00
description: AI Native 实战开发流程：以“管理员后台”为例（通用模板）本流程基于《AI Native 开发治理笔记》的治理理念，以 v3 管理后台 的一个典型功能“退款审核”为案例，展示如何用 AI 工程化方法交付一个安全、合规、可积累的生产级功能。该流程可复用到任何管理员后台的 CRUD、审批、报表、导出等场景。一、总体开发阶段概览阶段核心动作参与角色产出物（存入对应目录）1. 知识准备补充原始资料与业务规则人docs/、business/2. 任务规划编写 task 与选择 workflow人ai/tasks/current/、ai/workflows/3. AI 分析对齐让 AI 只分析，不写代码，对齐方案AI + 人分析报告（对话产物）4. AI 开发实现AI 按约束编码AI代码变更（apps/）5. 质量审查AI 自检 + 人复核AI + 人ai/reviews/6. 知识沉淀提炼通用经验与开发日志AI + 人ai/engineering-knowledge/、ai/development-logs/7. 交付上线最终验证与合并人可运行代码二、前置条件：工程骨架已搭建假设团队已经按治理笔记建立了以下目录和基础文件：v3-system/ ├── apps/ # 现有管理后台代码 ├── docs/ # 已有数据库 DDL、API 文档 ├── business/ # 已有 order/wallet/refund 等业务规则 ├── ai/ │ ├── tasks/current/ │ ├── workflows/ │ ├── reviews/ │ ├── engineering-knowledge/ │ └── development-logs/ ├── AGENTS.md # 已编写全局 AI 规则 └── CLAUDE.md如果还没有，必须先按笔记完成骨架搭建，否则后续流程会因为缺少约束而失控。三、实战步骤详解（以退款审核为例）阶段 1：知识准备——让 AI 有据可依目标：确保 AI 看到的“真相”是完整且准确的。人需要做的事情：检查 docs/是否存在 refund_order 表的 DDL？字段、索引、注释是否完整？是否有关联的 wallet、wallet_transaction 表结构？支付回调相关的第三方文档是否可访问？如果不全，立即用 mysqldump --no-data 导出最新结构放入 docs/db/。编写/更新 business/refund/rules.md 按照笔记模板，补充退款专属规则，例如：# 退款规则 1. 仅支付成功订单可退款 2. 退款必须审核（状态机：PENDING_AUDIT → APPROVED / REJECTED） 3. 退款执行时原子增加用户余额（UPDATE wallet SET balance = balance + ? WHERE user_id = ?） 4. 幂等：退款单 APPROVED 后重复请求直接返回成功 5. 记录 wallet_transaction 类型为 REFUND检查 business/wallet/invariants.md 确认余额不变量（balance >= 0）等规则已存在。产出物：更新后的 docs/ 和 business/，AI 的“知识底座”建立完毕。阶段 2：任务规划——画好 AI 的“活动圈”目标：精确控制 AI 本次能做什么、不能做什么。人需要做的事情：创建任务文件 ai/tasks/current/TASK-REFUND-APPROVE.md 按模板填写（关键字段见笔记第七章），示例要点：Goal：开发退款审核通过接口Allowed Modules：RefundController、RefundService、RefundDao，表 refund_order, wallet, wallet_transactionForbidden Modules：auth, distributor, goods，以及任何前端代码Technical Requirements：JdbcTemplate、@Transactional、Redis 锁、幂等Deliverables：修改的文件、SQL 变更、风险点选择或编写 workflow 如果 ai/workflows/add-admin-api.md 已存在，则沿用；否则参考笔记第八章编写一个。workflow 定义了标准开发步骤：分析 → 方案 → 编码 → 自检。产出物：TASK-REFUND-APPROVE.md 和确认使用的 workflow。阶段 3：AI 分析对齐——让 AI 先“说出来”再动手目标：AI 在不写代码的前提下，给出完整技术方案，由人确认，避免方向错误。操作步骤：新…

AI 开发治理入门笔记（初学者实战版）
type: item
date: 2026-05-27T11:22:44+08:00
description: 目标：你不是学习：“怎么让 AI 帮你写几段代码”而是学习：“怎么真正用 AI 开发一个长期项目”下面这份。我会完全按：真实开发流程给你讲。一、先理解：AI 开发真正的问题是什么？很多新人以为：AI开发是：“会 Prompt”其实不是。真正问题是：AI 有三个巨大问题问题结果AI 会乱改代码改到别的模块AI 会忘记业务状态机错误AI 会忘记上下文第二天继续不了所以：真正的 AI 开发：本质是：管理 AI不是：单纯使用 AI二、真正 AI 工程的核心思想你以后：不要这样：错误方式“帮我开发后台”因为：AI 会：无限扩散改很多文件忘记事务忘记权限忘记 review正确方式你以后：每次只做：一个明确任务例如：开发用户分页接口不是：开发整个后台三、真正完整目录（你以后就这样）v3-system/ ├── apps/ ├── docs/ ├── business/ ├── ai/ │ ├── tasks/ │ ├── workflows/ │ ├── reviews/ │ ├── engineering-knowledge/ │ └── development-logs/ ├── AGENTS.md └── CLAUDE.md下面。我一个一个给你解释。四、docs（原始资料）作用存：项目原始资料例如：docs/ ├── auth.sql ├── business.sql ├── 管理员API.md └── 产品需求.md谁创建？你AI 能修改吗？不能为什么？因为：docs 是：原始真相AI：不能：修改真相五、business（最重要）这个：是：整个系统最重要的东西business 是什么？business：保存：业务规则例如：订单状态钱包规则分销规则提现规则为什么一定需要 business？因为：AI：根本不懂你的业务它只能猜。举例如果：你没有 business。AI 可能：允许：已完成订单退款但实际上：你业务：禁止完成后退款所以：业务规则：必须：你定义六、business 实际怎么写？文件business/order.md内容（真实版）# Order State Machine CREATED → PAID → DELIVERING → FINISHED 退款： PAID → REFUND_PENDING → REFUNDED 禁止： - FINISHED退款 - CREATED退款七、AGENTS.md（AI宪法）这个：超级重要。它是什么？它是：AI全局规则类似：公司制度文件AGENTS.md内容（初学者推荐版）# Global AI Rules ## SQL Rules - Never use SELECT * - Never update without WHERE - Always check indexes --- ## Scope Rules Never modify unrelated modules. --- ## Architecture Rules - Controller handles params only - Service handles business only - DAO handles SQL only --- ## Transaction Rules Critical operations must use transactions. --- ## Review Rules Always review: - transaction - sql - security - invariants八、为什么 AGENTS 很重要？因为：AI：非常容易乱来例如：你开发：用户分页AI：突然：改 auth改 wallet改 distributor很常见。所以：必须：提前立规矩九、tasks（最关键）本质本次任务 + AI边界为什么 task 最重要？因为：它决定：AI 允许做什么task 文件ai/tasks/admin-user-page.mdtask 内容（真实版）# Goal 开发： GET /admin/user/page --- # Features 支持： - phone - status - create_time 分页： - page - pageSize --- # Allowed Modules - user --- # Forbidden Modules - auth - wallet - distributor --- # Requirements 1. JdbcTemplate 2. Explain SQL 3. Prevent SQL Injection 4. Soft Delete Only --- # Deliverables Output: - modified files …