当前位置: 首页 > backend >正文

springboot 笔记

1. ​​注解(Annotation)​

  • ​是什么​​:代码里的特殊标记,像标签一样贴在类/方法/字段上
  • ​作用​​:用来给程序传递额外信息,比如@NeedLogin就是在说"这个方法需要登录"
  • ​特点​​:以@符号开头,不会直接影响代码逻辑

2. ​​元注解(Meta-Annotation)​

  • ​是什么​​:用来修饰其他注解的注解(注解的注解)
  • ​常见元注解​​:
    • @Target:规定注解能贴在哪里(类/方法/字段等)
    • @Retention:规定注解在什么时候有效(源码/编译/运行时)
    • @Documented:控制是否出现在JavaDoc文档里

反射机制(Reflection)​

  • ​是什么​​:程序运行时动态获取类信息的能力
  • ​怎么用​​:通过反射可以检测方法是否有@NeedLogin注解
  • ​典型代码​​:
method.isAnnotationPresent(NeedLogin.class) // 判断是否有注解

@Component 注解​

​作用​
  • ​标记一个类为 Spring 组件​​,让 Spring 自动扫描并创建它的实例(Bean),纳入容器管理。
  • 是 @Controller@Service@Repository 的通用父注解。
​使用场景​
  • 当某个类​​不属于 Controller、Service、DAO​​ 等特定层,但需要被 Spring 管理时使用。
  • 例如:工具类、第三方库的适配器等。
@Component // 告诉Spring:这个类需要被管理
public class EmailValidator {public boolean isValid(String email) {return email.contains("@");}
}
  • ​其他派生注解​​(功能相同,但语义更明确):
    • @Service:用于业务逻辑层
    • @Repository:用于数据访问层
    • @Controller:用于Web控制层

@Autowired 注解​

​作用​
  • ​自动依赖注入​​:Spring 自动找到匹配的 Bean 并赋值给字段、构造器或方法参数。
  • 是 Java 依赖注入(DI)的核心注解。
​注入方式​
  1. ​字段注入(最常用)​
    @Service
    public class UserService {@Autowired // 自动注入UserRepositoryprivate UserRepository userRepository;
    }

    ​构造器注入(推荐)

@Service
public class UserService {private final UserRepository userRepository;@Autowired // Spring 4.3+ 可省略public UserService(UserRepository userRepository) {this.userRepository = userRepository;}
}

​Setter 注入

@Service
public class UserService {private UserRepository userRepository;@Autowiredpublic void setUserRepository(UserRepository userRepository) {this.userRepository = userRepository;}
}

  • @Autowired 默认按类型(byType)匹配​​,如果有多个同类型 Bean,需配合 @Qualifier 指定名称。
  • 如果找不到 Bean,会抛出 NoSuchBeanDefinitionException。可通过 @Autowired(required=false) 设为可选依赖。

​@Target(ElementType.METHOD)​

  • ​ElementType​​:Java定义的枚举,表示注解可以贴的位置类型
    • METHOD:只能贴在方法上
    • TYPE:可以贴在类/接口上
    • FIELD:可以贴在字段上
  • ​作用​​:限制@NeedLogin只能用在方法前,不能乱贴

​@Retention(RetentionPolicy.RUNTIME)​

  • ​RetentionPolicy​​:定义注解的生命周期
    • SOURCE:仅在源码中有效(编译后消失)
    • CLASS:保留到编译后的class文件(运行时看不到)
    • RUNTIME:运行时仍然存在(可以通过反射读取)
  • ​为什么选RUNTIME​​:因为需要在程序运行时检查用户登录状态

@Around 注解详解​

@Around 是 Spring AOP 中最强大的通知(Advice)类型,允许你​​完全控制目标方法的执行​​,可以在方法调用前后插入自定义逻辑,甚至阻止方法执行或修改返回值。


​1. 核心特点​
特性说明
​完全控制​可以决定是否执行目标方法,以及如何修改参数和返回值
​最灵活的通知​结合了 @Before@After@AfterReturning@AfterThrowing 的功能
​必须明确调用目标方法​需通过 ProceedingJoinPoint.proceed() 手动触发目标方法执行
​可以处理异常​能捕获并处理目标方法抛出的异常

​2. 基本语法​
@Aspect
@Component
public class LoggingAspect {// 定义切点(拦截哪些方法)@Pointcut("execution(* com.example.service.*.*(..))")public void serviceMethods() {}// Around 通知@Around("serviceMethods()")public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {// 1. 目标方法执行前的逻辑log.info("方法调用前: " + joinPoint.getSignature().getName());// 2. 执行目标方法(可跳过或修改参数)Object result = joinPoint.proceed(); // 3. 目标方法执行后的逻辑log.info("方法调用后,返回值: " + result);return result; // 可以修改返回值}
}

@Documented​

  • ​作用​​:让这个注解在使用时,能显示在自动生成的JavaDoc文档中
  • ​对比​​:不加这个时,即使方法用了@NeedLogin,生成的API文档也不会显示这个标记

  1. @interface定义了一个注解@NeedLogin
  2. 用元注解@Target限制它只能贴到方法上
  3. @Retention保证运行时能通过反射检测到它
  4. @Documented让它出现在文档中
  5. 实际使用时,其他代码通过​​反射机制​​检测到这个注解,执行登录检查逻辑

@Bean 注解​
  • ​作用​​:告诉 Spring ​​这个方法会返回一个对象,并交给 Spring 容器管理​​(类似 XML 配置中的 <bean>)。
  • ​使用场景​​:常用于配置线程池、数据库连接池等需要全局管理的对象。
  • ​示例​​:
@Configuration
public class AppConfig {@Beanpublic Executor asyncExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(5);executor.setMaxPoolSize(10);executor.setQueueCapacity(100);return executor;}
}

​解释​​:这里定义了一个线程池 asyncExecutor,Spring 会管理它的生命周期,其他地方可以直接 @Autowired 注入使用。

@Service
public class UserService {@Async  // 该方法会异步执行(在另一个线程运行)public void sendEmail(String email) {log.info("发送邮件给: {}", email);}
}
@Async 注解​
  • ​作用​​:让方法​​异步执行​​(不阻塞主线程,提高并发性能)。
  • ​使用条件​​:
    • 必须配合 @EnableAsync 使用(在启动类或配置类上)。
    • 方法不能是 private 或 final(因为 Spring 需要代理)。

Spring AOP 详解​

​Spring AOP(Aspect-Oriented Programming,面向切面编程)​​ 是 Spring 框架的核心模块之一,用于​​解耦横切关注点​​(如日志、事务、权限等),让业务逻辑更纯净。它通过动态代理技术,在运行时将额外逻辑(称为“通知”)织入到目标方法中。


​1. 核心概念​
术语说明
​切面(Aspect)​封装横切逻辑的模块(如 LoggingAspect),包含通知和切点定义。
​连接点(Join Point)​程序执行的点(如方法调用、异常抛出),Spring AOP 仅支持方法级别的连接点。
​通知(Advice)​切面在特定连接点执行的动作(如 @Before@Around)。
​切点(Pointcut)​通过表达式匹配哪些连接点需要被拦截(如 execution(* com.example.*.*(..)))。
​目标对象(Target)​被代理的原始对象(如 UserService)。
​代理(Proxy)​Spring 生成的增强对象,在调用目标方法时插入切面逻辑。

​2. AOP 的实现原理​

Spring AOP 基于​​动态代理​​,具体分两种:

  1. ​JDK 动态代理​​(默认)
    • 要求目标类必须实现接口(如 UserService 实现 IUserService)。
    • 代理对象会实现相同接口,拦截方法调用。
  2. ​CGLIB 代理​
    • 通过继承目标类生成子类代理,适用于无接口的类。
    • 需添加 @EnableAspectJAutoProxy(proxyTargetClass = true) 强制启用。

​3. 通知(Advice)类型​
注解执行时机示例用途
@Before目标方法​​执行前​参数校验、日志记录
@After目标方法​​执行后​​(无论是否异常)资源清理
@AfterReturning目标方法​​成功返回后​记录返回值
@AfterThrowing目标方法​​抛出异常后​异常处理、告警通知
@Around​完全控制​​目标方法执行事务管理、性能监控

MDC(Mapped Diagnostic Context)核心总结​

​(1)MDC 是什么?​
  • ​本质​​:一个线程绑定的键值对存储(基于 ThreadLocal),用于​​在日志中携带上下文信息​​(如 requestIduserId)。
  • ​典型用途​​:分布式系统日志追踪(如排查某个请求的所有日志)。
​(2)MDC 的作用​

场景作用
​日志关联​让同一请求的所有日志自动带上 requestId,方便排查问题
​多线程环境​默认线程安全(每个线程独立存储)
​减少代码侵入​无需手动在每条日志中写 requestId,通过 %X{key} 自动输出

// 存值
MDC.put("requestId", "123");  
// 取值
String id = MDC.get("requestId");  
// 清理(防止内存泄漏)
MDC.clear();  
特殊情况:异步线程中 MDC 丢失怎么办?​
​(1)问题原因​
  • ThreadLocal 的隔离性​​:子线程默认不继承父线程的 MDC(新线程拿不到父线程的 requestId)。
    @Bean
    public Executor asyncExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setTaskDecorator(new MDCAwareTaskDecorator()); // 自动复制 MDCreturn executor;
    }

    效果​​:子线程日志自动继承父线程的 MDC。

拦截器 vs 过滤器:

特性​过滤器(Filter)​​拦截器(Interceptor)​
​所属层次​Servlet 规范(底层,任何Web框架通用)Spring MVC 提供(仅Spring生态可用)
​实现接口​javax.servlet.Filterorg.springframework.web.servlet.HandlerInterceptor
​执行时机​在 Servlet 之前(请求进入DispatcherServlet前)在 Controller 方法前后(DispatcherServlet内)
​依赖注入​不支持Spring依赖注入(需手动获取Bean)支持Spring依赖注入(如 @Autowired
​获取上下文​只能获取Servlet API(Request/Response)可获取Spring上下文(如方法参数、注解信息)
​典型场景​全局日志、编码转换、跨域处理权限校验、参数预处理、日志增强

http://www.xdnf.cn/news/9259.html

相关文章:

  • Redis核心数据结构操作指南:字符串、哈希、列表详解
  • 【K8S】K8S基础概念
  • Java spingboot项目 在docker运行,需要含GDAL的JDK
  • 飞牛fnNAS手机相册备份及AI搜图
  • 博图SCL基础知识-表达式及赋值运算
  • 甲醇 燃料 不也有碳排放吗?【AI回答版】
  • 得物Java开发面试题及参考答案(下)
  • Linux操作系统概述
  • 【Canvas与日月星辰】烈日当空
  • 关于git的使用
  • 【漏洞与预防】Microsoft Windows 文件资源管理器欺骗漏洞预防
  • 【免费】【无需登录/关注】Base64 图片转换工具网页
  • 【Java】DelayQueue
  • LangGraph(七)——Workflows
  • 基于物联网(IoT)的电动汽车(EVs)智能诊断
  • Java组合、聚合与关联:核心区别解析
  • AWS WebRTC:获取信令服务节点和ICE服务节点
  • 深度解读 Qwen3 大语言模型的关键技术
  • 【Elasticsearch】ingest对于update操作起作用吗?
  • Android15 Camera Hal设置logLevel控制日志输出
  • vue2使用el-tree实现两棵树间节点的拖拽复制
  • LeetCode 2894.分类求和并作差:数学O(1)一行解决
  • Java提取markdown中的表格
  • go并发与锁之sync.Mutex入门
  • 国11阶乘约数-质因数分解
  • C/C++的OpenCV的锐化
  • vue 前端请求跨域解决办法
  • 九级融智台阶与五大要素协同的量子化解析
  • MGAug:图像变形潜空间中的多模态几何增强|文献速递-深度学习医疗AI最新文献
  • 端口 3389 服务 ms - wbt - server 漏洞修复方法