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

java理解

springboot

打包

mvn install:install-file -Dfile=<path-to-jar> -DgroupId=<group-id> -DartifactId=<artifact-id> -Dversion=<version> -Dpackaging=jar
<path-to-jar> 是你的 JAR 文件的路径。
<group-id> 是你的项目的组 ID。
<artifact-id> 是你的项目的构件 ID。
<version> 是你的项目的版本号。mvn install:install-file -Dfile=D:\ojdbc6-11.2.0.1.0.jar -DgroupId=com.oracle -DartifactId=ojdbc6 -Dversion=11.2.0.1.0 -Dpackaging=jar

AOP

根据目标对象是否实现接口自动选择动态代理机制。

  • JDK 动态代理:适用于目标对象实现了接口的情况。

    JDK 动态代理是 Java 提供的一种动态创建代理对象的机制。它允许在运行时动态地创建一个代理类,该代理类实现了与目标对象相同的接口,并且可以拦截对目标对象方法的调用。通过这种方式,可以在不修改目标对象代码的情况下,对目标对象的方法调用进行增强(如添加日志、事务管理等)。

  • CGLIB 动态代理:适用于目标对象没有实现接口的情况。

通过aspect注解定义切面,可以结合自定义注解实现 不改变源代码情况下,在方法执行前后增加功能。

IOC

通过 IoC,Spring 容器负责管理对象的生命周期和依赖关系,而不是由开发者手动管理。

  • @Repository:标记一个类为数据访问层组件,通常用于数据库操作。
  • @Qualifier:用于指定注入的 Bean 的名称,当存在多个同类型的 Bean 时,可以使用该注解来明确指定注入哪一个 Bean。
  • @Primary:用于指定默认注入的 Bean,当存在多个同类型的 Bean 时,Spring 容器会优先注入标记为 @Primary 的 Bean。
  • @Cacheable` 是 Spring 缓存框架提供的一个注解,用于声明一个方法的结果是可缓存的。当方法被调用时,Spring 会检查缓存中是否已经存在相应的值。如果存在,则直接从缓存中返回结果,而不会执行方法体;如果不存在,则执行方法体并将结果存入缓存,以便下次调用时可以直接从缓存中获取。
  • @Transactional: 被标记的方法如果出现**RuntimeExceptionError**会回滚事物。
    1. Spring 事务的隔离级别有哪些?
      • READ_UNCOMMITTED:最低的隔离级别,允许读取未提交的数据,可能出现脏读。
      • READ_COMMITTED:允许读取已提交的数据,避免了脏读,但可能出现不可重复读。
      • REPEATABLE_READ(默认级别):保证在同一个事务中多次读取数据的结果是一致的,避免了不可重复读,但可能出现幻读。
      • SERIALIZABLE:最高的隔离级别,完全隔离并发事务,避免了脏读、不可重复读和幻读,但性能开销最大。
    2. 什么是脏读、不可重复读和幻读?
      • 脏读:一个事务读取了另一个事务未提交的数据。
      • 不可重复读:一个事务在两次读取同一数据时,数据被另一个事务修改,导致两次读取的结果不一致。
      • 幻读:一个事务在两次读取同一范围的数据时,数据被另一个事务插入或删除,导致两次读取的结果不一致。

线程池

线程池的基本概念

  1. 什么是线程池?
    • 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建了线程后,从队列中取出任务并执行。
    • 线程池的主要目的是减少线程创建和销毁的开销,提高线程的复用性。
  2. 线程池的主要优点是什么?
    • 减少线程创建和销毁的开销:线程池会复用已创建的线程,减少线程创建和销毁的次数。
    • 提高响应速度:任务提交后可以直接从线程池中获取线程执行,减少了线程创建的时间。
    • 提高线程的可管理性:线程池可以对线程进行统一管理,如设置线程的最大数量、队列大小等。
    • 避免资源耗尽:通过限制线程的最大数量,避免系统资源耗尽。
  3. 线程池的主要组成部分是什么?
    • 线程池管理器:负责创建和管理线程池。
    • 工作线程:线程池中实际执行任务的线程。
    • 任务队列:用于存储待执行任务的队列。
    • 任务接口:所有任务必须实现的接口,以便工作线程可以执行。

线程池的实现原理

  1. Java 中的线程池是如何实现的?
    • Java 的线程池主要通过 java.util.concurrent 包中的 Executor 框架实现。
    • Executor 是一个接口,定义了执行任务的方法。
    • ExecutorServiceExecutor 的子接口,提供了更丰富的功能,如线程池的管理。
    • ThreadPoolExecutorExecutorService 的实现类,提供了线程池的核心实现。
  2. ThreadPoolExecutor 的构造参数有哪些?
    • corePoolSize:核心线程数,线程池中始终保持的线程数量。
    • maximumPoolSize:最大线程数,线程池中允许的最大线程数量。
    • keepAliveTime:非核心线程的空闲存活时间。
    • unitkeepAliveTime 的时间单位。
    • workQueue:任务队列,用于存储待执行任务的队列。
    • threadFactory:线程工厂,用于创建线程。
    • handler:拒绝策略,当任务队列满且线程数达到最大值时,如何处理新任务。
  3. 线程池的拒绝策略有哪些?
    • AbortPolicy:直接抛出 RejectedExecutionException
    • CallerRunsPolicy:由调用线程执行任务。
    • DiscardPolicy:直接丢弃任务。
    • DiscardOldestPolicy:丢弃队列中最老的任务,然后尝试提交新任务。

线程池的使用方法

  1. 如何创建一个线程池?

    • 使用 ThreadPoolExecutor 的构造方法创建线程池。

    • 示例:

      import java.util.concurrent.*;public class ThreadPoolExample {public static void main(String[] args) {ThreadPoolExecutor executor = new ThreadPoolExecutor(2, // 核心线程数4, // 最大线程数60L, // 空闲存活时间TimeUnit.SECONDS, // 时间单位new LinkedBlockingQueue<Runnable>(100) // 任务队列);for (int i = 0; i < 10; i++) {executor.execute(() -> {System.out.println("Task executed by: " + Thread.currentThread().getName());});}executor.shutdown();}
      }
      
  2. 如何关闭线程池?

    • 使用 shutdown() 方法关闭线程池,等待所有任务完成。
    • 使用 shutdownNow() 方法立即关闭线程池,尝试中断正在执行的任务。
  3. 如何提交任务到线程池?

    • 使用 execute(Runnable command) 方法提交任务。
    • 使用 submit(Callable<T> task) 方法提交任务并返回 Future 对象。

线程池的性能优化

  1. 如何优化线程池的性能?
    • 合理设置线程池大小:根据系统的硬件资源和任务类型,合理设置核心线程数和最大线程数。
    • 选择合适的任务队列:根据任务的特点选择合适的任务队列,如 LinkedBlockingQueueArrayBlockingQueue
    • 设置合理的拒绝策略:根据业务需求选择合适的拒绝策略,避免任务丢失。
    • 监控线程池状态:通过 ThreadPoolExecutor 提供的方法监控线程池的状态,如 getActiveCount()getCompletedTaskCount() 等。

线程池的高级特性

  1. 什么是线程池的饱和策略?

    • 当任务队列满且线程数达到最大值时,线程池会采取的策略。可以通过 RejectedExecutionHandler 接口自定义饱和策略。
  2. 如何自定义线程工厂?

    • 实现 ThreadFactory 接口,自定义线程的创建逻辑。

    • 示例:

      import java.util.concurrent.*;public class CustomThreadFactory implements ThreadFactory {private final String threadNamePrefix;public CustomThreadFactory(String threadNamePrefix) {this.threadNamePrefix = threadNamePrefix;}@Overridepublic Thread newThread(Runnable r) {return new Thread(r, threadNamePrefix + "-Thread-" + Thread.currentThread().getId());}public static void main(String[] args) {ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(100),new CustomThreadFactory("MyCustomThread"));for (int i = 0; i < 10; i++) {executor.execute(() -> {System.out.println("Task executed by: " + Thread.currentThread().getName());});}executor.shutdown();}
      }
      

线程池的常见问题

  1. 线程池中的线程是如何复用的?
    • 线程池中的线程在执行完一个任务后,会返回线程池,等待下一个任务。如果线程池中的线程数量超过核心线程数且空闲时间超过 keepAliveTime,则会销毁多余的线程。
  2. 线程池中的线程是如何销毁的?
    • 当线程池中的线程数量超过核心线程数且空闲时间超过 keepAliveTime 时,多余的线程会被销毁。
    • 当调用 shutdown() 方法时,线程池会等待所有任务完成后再销毁所有线程。
    • 当调用 shutdownNow() 方法时,线程池会尝试中断正在执行的任务,并立即销毁所有线程。
  3. 线程池中的任务是如何调度的?
    • 线程池中的任务通过任务队列进行调度。任务队列可以是阻塞队列(如 LinkedBlockingQueueArrayBlockingQueue)或非阻塞队列(如 SynchronousQueue)。
    • 线程池会从任务队列中取出任务并分配给空闲的线程执行。

线程池的监控

  1. 如何监控线程池的状态?
    • 使用 ThreadPoolExecutor 提供的方法监控线程池的状态,如:
      • getActiveCount():获取当前活跃的线程数。
      • getCompletedTaskCount():获取已完成的任务数。
      • getTaskCount():获取任务总数。
      • getPoolSize():获取线程池中的线程数。
      • getLargestPoolSize():获取线程池中曾经出现的最大线程数。

设计模式

装饰器加适配器

理解:

准备一个接口,两个实现类,实现类一实现基本功能,实现类二中将实现类一注入进去,调用实现类一的方法,在方法前后添加特殊逻辑。

应用场景:

流程里用不用适配器,就看一点:各环节接口对不上,但又得一起干活。 对不上(参数、格式、方法名不一样),又改不了其中一方,就用适配器当“翻译”;能对上,或者能直接改接口,就不用折腾。

示例:

public interface ZSQservice {String ZSQService(String arg0, String arg1);
}
@Service
public class ZSQserviceImpl implements ZSQservice {@Overridepublic String ZSQService(String arg0, String arg1) {System.out.println("ZSQservice impl, arg0=" + arg0 + ", arg1=" + arg1);return "return, arg0=" + arg0 + ", arg1=" + arg1;}
}
@Slf4j
@Service
public class ZSQLOGIMPL implements ZSQservice {private ZSQservice zsqservice;public ZSQLOGIMPL(@Qualifier("ZSQEncryImpl")ZSQservice zsqservice) {this.zsqservice = zsqservice;}@Overridepublic String ZSQService(String arg0, String arg1) {log.info("执行前记录参数 arg0=" + arg0 + ", arg1=" + arg1);String returnJson = zsqservice.ZSQService(arg0, arg1);log.info("执行后记录结果 "+returnJson);return returnJson;}
}
@Slf4j
@Service
public class ZSQEncryImpl implements ZSQservice {private ZSQservice zsqservice;public ZSQEncryImpl(@Qualifier("ZSQserviceImpl") ZSQservice zsqservice) {this.zsqservice = zsqservice;}@Overridepublic String ZSQService(String arg0, String arg1) {log.info("数据加密中");String json = zsqservice.ZSQService(arg0, arg1);log.info("数据加密完成");return json;}
}
  @Testvoid zsqTest(){ZSQservice zsQservice = new ZSQLOGIMPL(new ZSQEncryImpl(new ZSQserviceImpl()));zsQservice.ZSQService("1","2");}
: 执行前记录参数 arg0=1, arg1=2
: 数据加密中ZSQservice impl, arg0=1, arg1=2
: 数据加密完成
: 执行后记录结果 return, arg0=1, arg1=2

代理模式

只要装饰器模式不添加特定功能就是代理,也可以看aop是spring自动进行代理的。

AOP加自定义注解

示例:

1. 添加依赖

pom.xml 中添加 Spring AOP 的依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2. 自定义注解

2.1 @LogAction

作用:记录方法的执行日志,包括方法名、入参和出参。
属性

  • action:描述日志内容,可选,默认值为 "日志记录"
package com.example.annotation;import java.lang.annotation.*;@Target({ElementType.METHOD, ElementType.TYPE})  // 可以标注在方法或类上
@Retention(RetentionPolicy.RUNTIME)  // 运行时保留
public @interface LogAction {String action() default "日志记录";  // 默认值
}

3. 自定义注解例子

3.1 @LogAction 示例
package com.example.service;import com.example.annotation.LogAction;
import org.springframework.stereotype.Service;
http://www.dtcms.com/a/328450.html

相关文章:

  • 解决微前端子应用嵌入后样式被覆盖
  • 深度解析 AS32S601 芯片 CAN Bus Off 机制:从原理到应用的全流程指南
  • 浏览器CEFSharp+X86+win7 之 全球外贸电商平台订单管理(十)
  • 前后端分离项目中Spring MVC的请求执行流程
  • uni-app实战教程 从0到1开发 画图软件 (学会画图)
  • Ceph BlueStore存储引擎详解
  • 【数据结构】并查集:从入门到精通
  • 《Linux基础知识-1》
  • docker-compose搭建 redis 集群
  • 阿里巴巴开源多模态大模型-Qwen-VL系列论文精读(一)
  • VBS 时间函数
  • 基于 libwebsockets 库实现的 WebSocket 服务器类
  • Shader warning in ‘Universal Render Pipeline/Particles/Simple Lit‘
  • provide()函数和inject()函数
  • 【UEFI系列】Super IO
  • VUE+SPRINGBOOT从0-1打造前后端-前后台系统-语音评测
  • 嵌入式学习(day25)文件IO:open read/write close
  • VGG改进(2):基于Local Attention的模型优化
  • 书籍数组中未出现的最小正整数(8)0812
  • 《飞算JavaAI:新一代智能编码引擎,革新Java研发范式》
  • 跑腿平台开发实战:同城O2O系统源码的模块化与可扩展性方案
  • 每日一练:将一个数字表示成幂的和的方案数;动态规划、深度优先搜索
  • 【Altium designer】快速建立原理图工程的步骤
  • 2025开放计算技术大会|开源开放推动系统创新 加速AIDC全球协作
  • 过拟合、欠拟合与方差/偏差的关系
  • Langchain结合deepseek:框架+模型的AI测试实践
  • 小白学习pid环控制-实现篇
  • 杰里平台7083G 如何支持4M flash
  • 【oracle闪回查询】记录字段短时间被修改的记录
  • MyBatis-Plus核心内容