# SpringDemo202601
**Repository Path**: nieps/spring-demo202601
## Basic Information
- **Project Name**: SpringDemo202601
- **Description**: spring案例
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2026-01-23
- **Last Updated**: 2026-01-28
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Spring笔记
早期开发:
* jsp ----本质servlet
> jsp1.0---- java代码和html混合
>
> ~~~jsp
>
>
> <%
> String name="张三";
> %>
> 名称:<%= name %>
>
>
> ~~~
>
>
>
> jsp2.0 ----jstl
>
> ~~~jsp
>
>
>
> 名称:${name}
>
>
> ~~~
jsp+javabean
java类封装你的操作------调用其它类
~~~java
//A类方法
public void save(){
B b =new B();
b.method()....
}
//B类 默认操作mysql数据库
//新的需求 ---增加redis 做为缓存 -----第一想法修改B的实现
//有新的需求 不去修改 而是扩展
//假如接口 I---声明方法 -----B类的实现
//Redis---实现
~~~

降低偶合度:依赖于抽象,不依赖于具体实现
抽象:
* 抽象类 抽象类与子类是 is a的关系 有血缘关系
* 接口 功能的声明
ssh
## Hello示例
MVC
M: model 模型层 业务层

### 工厂实现类

### 实现步骤
1. 新建maven工程
2. 引入依赖
~~~xml
org.springframework
spring-context
6.2.15
compile
~~~
3. 定义java类的实现 (定义业务类: 接口+实现类)
4. 定义配置文件\*.xml 文件 spring配置文件
~~~xml
~~~
5. 定义工厂类的实例(读取上面的配置文件 根据配置的 bean 通过反射创建对应类的实例,保存到内存中,使用的时候直接从内存获取)
~~~java
public void testApp() {
//创建工厂类实例 目的的获取目标类的实例
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
//从工厂类中获取实现
CustomerService customerService=applicationContext.getBean("customerService",CustomerService.class);
//调用方法
customerService.query();
}
~~~
### spring中bean 的生命周期 (面试题)
1. bean的定义
2. bean的实例化 (创建实例)----调用构造方法 很少定义构造方法
3. 注入依赖
4. 调用初始化方法 只会实例化一次
5. bean的使用
6. 销毁
### 关于bean 的作用域 (面试题 了解)
* singleton 单例 所有bean 在整个应用中只有一个实例 (默认的)
* prototype 原型 每次调用创建一个新的对象 (很少用)
* request 每一次请求创建一个对象
* session 一个会话创建一个对象
* application 整个应用创建一个对象
### 依赖注入 的方式
* **set注入** 要给注入的属性提供set方法 才能注入 (常用)
* 构造注入 通过构造函数注入
## 初化化实现
* 属性 init-method="方法名"
* 实现接口 InitializingBean ,重写afterPropertiesSet方法 (代码侵入 )
* **注解(推荐使用的)@PostConstruct** (后面介绍)
## 销毁 (释放资源 一般不用)
* 属性 destroy-method ="方法名"
* 实现接口 DisposableBean ,重写destroy方法
* 注解(推荐使用) @PreDestroy (后面演示)
## autowire自动装配
bean之间的依赖关系 ,交给spring自动管理
自动装配的类型:
* default 默认 需要手动注入 通过property 或构造注入
* **byType 根据类型自动装配** 对应注解:@Autowire 默认按类型自动状态
> 1. 当容器发现Bean中的依赖属性,会去容器中查找对应的实例,如果找到了注入 ,找不到默认为null
>
> 2. 如果同一类型有多个bean,在注入时就会报错:如
>
> ~~~
> No qualifying bean of type 'com.by.dao.CustomerDao' available: expected single matching bean but found 2: customerDao,customerDao2
> ~~~
>
> 解决办法:通过属性 primary="true", 作用:当有多个可用类型时,优先选择设置该属性的bean
* **byName 按名称自动装配** 去查询容器中与要注入的属性名一致的bean ,找到就注入,找不到 不注入 @Resource
* constructor 构造注入 必须提供要注入的属性的 构造方法 才可注入(且参数是按照类型注入)
* no 不注入
补充:
* 泛型 类泛型、方法泛型 类型参数化
* 反射 掌握基本应用
* 可以熟悉元注解
* 设计模式: 单例 工厂(简单工厂、抽象工厂)
## 作业 CRM原型
1. 把整个系统的表设计 (要求使用建模软件: pdmaner powerdesigner)
2. 根据原型 编写mapper
## 元注解
**元注解,本质是注解的注解。**
共有5个:
- @Documented – 注解是否将包含在JavaDoc中
- **@Retention – 什么时候使用该注解**
- **@Target – 注解用于什么地方**
- @Inherited – 是否允许子类继承该注解
- @Repeatable 指定重复注解 (查看Mybatis定义插件时用的注解 )
### 注解的作用域 @Retention
* SOURCE 说明该注解 只存在于源码文件中
* CLASS 说明该注解在源码、字节码文件中都 有
* RUNTIME 说明该注解在源码、字节码文件及运行时都 有
### @target
说明自定义 的注解能够使用在哪些地方
## Spring 注解
MVC三层模型:
* C 控制层
* M 业务层
* dao数据访问层

面试题: @Autowired和@Resource的区别?
## @Resource注解
`@Resource` 注解的包名取决于你使用的 JDK 和相关框架的版本。主要有以下三种情况:
#### 📦 1. JDK 8 及更早版本
在这些版本中,`@Resource` 是 Java EE API 的一部分,直接包含在 JDK 中。
- **包名:** `javax.annotation.Resource`
#### 📦 2. JDK 9 至 JDK 16
从 JDK 9 开始,Java 实行了模块化(Jigsaw),移除了内置的 Java EE API,因此 `@Resource` 不再包含在 JDK 中。
- **你需要:** 手动添加第三方依赖。
- **包名:** 通常仍然是 `javax.annotation.Resource`,通过引入 `javax.annotation:javax.annotation-api` 依赖来使用。
#### 📦 3. JDK 17 及更高版本 (Jakarta EE 9+)
从 Java EE 转移到 Eclipse 基金会后,项目更名为 Jakarta EE,并从版本 9 开始将所有包名从 `javax.*` 更改为 `jakarta.*`。
- **包名:** `jakarta.annotation.Resource`
- **你需要:** 引入 `jakarta.annotation:jakarta.annotation-api` 依赖。
------
### 📌 总结
| 环境 | 包名 | 说明 |
| :----------- | :---------------------------- | :------------------------------------------- |
| **JDK 8** | `javax.annotation.Resource` | JDK 内置,无需额外依赖。 |
| **JDK 9-16** | `javax.annotation.Resource` | 需要手动添加 `javax.annotation-api` 依赖。 |
| **JDK 17+** | `jakarta.annotation.Resource` | 需要手动添加 `jakarta.annotation-api` 依赖。 |
### 💡 特别提示:Spring 框架版本的影响
如果你在使用 Spring 框架,还需要注意框架版本的兼容性:
- **Spring 5.x**:主要支持 `javax.annotation` 包。
- **Spring 6.x**:最低要求 JDK 17,并全面迁移到了 `jakarta.annotation` 包。
## Spring注解

## AOP
纵向抽取: 抽象类 是对类的 抽象 通过继承达到复用
横向抽取:把不相干的类 共同的业务或逻辑提取出来,在不改变原有代码的情况下,将提取的业务增加到目标类的执行上。
### 静态代理
* 目标对象(目标类) 要代理 的对象
* 代理 对象(代理类)
* 要求目标类与代理类实现相同的接口
### 动态代理
jdk动态代理与cglib代理
| 对比维度 | JDK 动态代理 | CGLIB 动态代理 |
| :----------- | :----------------------------------------------------------- | :----------------------------------------------------------- |
| **实现原理** | 基于接口,在运行时动态生成一个实现指定接口的代理类。 | 基于继承,在运行时通过生成被代理类的子类来实现代理。 |
| **依赖条件** | 被代理类**必须**实现至少一个接口。 | 被代理类**无需**实现接口,但不能是 `final` 类。 |
| **方法限制** | 只能代理接口中定义的方法。 | 可代理被代理类的所有非 `final` 方法,但无法代理 `final` 或 `private` 方法。 |
| **底层技术** | 使用 Java 原生的反射机制 (`java.lang.reflect.Proxy`)。 | 使用 ASM 字节码操作框架直接生成字节码。 |
| **性能特点** | 初始化开销较低,方法调用通过反射,JDK8+ 后性能已非常接近 CGLIB。 | 初始化生成字节码开销较高,但方法调用性能略好,差距在 JDK8+ 后已很小。 |
| **依赖要求** | JDK 原生支持,无额外依赖。 | 需引入 CGLIB/ASM 依赖(Spring-core 已包含)。 |
### 术语
* **切面** 包含**切点**(用于说明在哪些类的哪些方法上使用 增强)和**增强**(要在目标方法上增加的逻辑代码) (切面是一个类,里面定义了很多你要在目标方法上增加的代码)
* 关于新增逻辑 三种说法 advice
> 1. 增强
> 2. 横切关注点
> 3. 通知
### 切点表达式
~~~java
execution(返回类型 方法名 (参数) )
~~~
## 定时任务
* Timer
* 定时线程池
* Spring Task (单体结构)
* XXL-JOB 分布式任务调度
## 作业
定时给用户发邮件,生成一人验证码
~~~java
String code="a..ZA..Z0..9"
~~~
## event
用户下单:OrderService
* 保存订单
* 保存订单明细
* 更新库存... ( 通知库存系统 扣减库存)
* 更新会员积分
~~~java
public class OrderSerice{
StockService stock;
int save(){
//生成订单
//保存明细
stock.updateStock();//更新库存
}
}
~~~
~~~java
public class StockService{
int updateStock(){
}
}
~~~
假如: 库存系统 StockService
核心组件:
* 事件 就是个Java类,传递的数据
* 事件发布者 通知相关组件更新数据
* 事件监听器 @EventListener 观察者
### 实现
#### 定义事件对象
就是组件通信要传递的参数,这里是普通javabean
~~~java
public class OrderEvent {
int goodsId;
int num;
}
~~~
#### 主题 (被观察者 生成订单--通知其它业务)
~~~java
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
ApplicationContext context;
@Override
public void save() {
System.out.println("保存订单");
System.out.println("保存订单明细 ");
//发布事件
context.publishEvent(new OrderEvent(1,3));
System.out.println("------------");
}
}
~~~
#### 监听者(观察者 当生成订单时要联动实现数据变化的)
~~~java
@Service
public class StockServiceImpl implements StockService {
@EventListener(value = {OrderEvent.class})//监听OrderEvent事件
@Override
public void updateStock(OrderEvent event) {
System.out.println("更新库存,商品"+event.getGoodsId()+" 减少数量:"+event.getNum());
}
}
~~~
## 观察者设计模式(Observer Design Pattern)
观察者设计模式是一种**行为型设计模式**,核心思想是定义**对象间一对多的依赖关系**:当一个被观察对象(主题)的状态发生改变时,其所有依赖的观察对象(观察者)会被**自动通知并更新**,实现**状态变化的解耦传递**。
发布订阅
角色:
* 观察者-----抽象
* 被观察者----抽象
## 异步任务
实现条件:
* 启用异步任务 @EnableAsync
* 定义异步任务方法 @Async
* 配置线程池
~~~java
@Bean
public ThreadPoolTaskExecutor taskExecutor(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//核心线程数
executor.setCorePoolSize(5);
//最大线程数
executor.setMaxPoolSize(10);
//线程队列最大线程数
executor.setQueueCapacity(20);
executor.initialize();
return executor;
}
~~~
应用场景:
通常是耗时操作:
* 发送短信
* 发送邮件
* 执行数据库备份
* 导入导出excel文件
## 登录逻辑
1. 输入用户名 密码 验证码
2. 业务逻辑
> 1. 判断验证码是否正确 正确进入2
>
> 2. 根据用户名查询用户,如果没找到,账号不存在 ,找到了 进入3
>
> 3. 把**用户提交过来的密码加密** ,然后与数据库加密过的密码比较 相等就是正确 ,否则用户名或密码不正确
>
>