Appearance
自我介绍
技术考查点:
- 语言表达能力
- 逻辑思维能力
- 对自身优势和经历的总结能力
回答: 您好,我叫[姓名],毕业于[毕业院校]的[专业]。在校期间,我系统学习了[相关专业课程],并通过[实践项目或实习经历]积累了一定的[专业技能]经验。毕业后,我加入了[上家公司名称],在那里我参与了[主要项目名称],负责[具体工作职责],通过这个项目,我提升了[具体能力提升]。我对[应聘岗位相关技能或领域]有浓厚的兴趣,并且一直在不断学习和研究,希望能加入贵公司,为公司的发展贡献自己的力量。
流程图:
代码示例: 由于自我介绍主要是语言表达,暂无代码示例。
seata如何保证最终一致性的
技术考查点:
- 对分布式事务的理解
- 对Seata框架的掌握
回答: Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 主要通过 AT(自动补偿)、TCC(Try-Confirm-Cancel)、SAGA 和 XA 四种模式来保证分布式事务的最终一致性。以 AT 模式为例,它是一种无侵入的分布式事务解决方案,其核心思想是在业务数据和回滚日志记录在同一个本地事务中提交,从而保证本地事务的原子性。在全局事务层面,Seata 会通过协调器(TC)来管理各个分支事务的状态,确保在全局事务提交或回滚时,各个分支事务能够正确地执行相应的操作。
流程图:
代码示例:
java
// 引入 Seata 依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
// 在业务方法上添加 @GlobalTransactional 注解
@GlobalTransactional
public void businessMethod() {
// 业务逻辑
}
保持最终一致性的方案
技术考查点:
- 对分布式系统最终一致性的理解
- 掌握常见的最终一致性方案
回答: 常见的保持最终一致性的方案有消息队列、TCC 模式、SAGA 模式等。以消息队列为例,它的核心思想是将业务操作拆分成多个步骤,并通过消息队列来异步处理这些步骤。在业务操作执行过程中,将需要处理的消息发送到消息队列中,然后由消费者从消息队列中获取消息并进行处理。通过这种方式,可以保证在出现异常时,消息可以被重试,从而保证最终一致性。
流程图:
代码示例:
java
// 引入 RabbitMQ 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
// 发送消息到 RabbitMQ
@Autowired
private RabbitTemplate rabbitTemplate;
public void sendMessage(String message) {
rabbitTemplate.convertAndSend("exchangeName", "routingKey", message);
}
// 消费 RabbitMQ 消息
@RabbitListener(queues = "queueName")
public void receiveMessage(String message) {
// 处理消息
}
AOP 在项目中的应用
技术考查点:
- 对 AOP 编程的理解
- 实际项目应用能力
回答: 在项目中,我们使用 AOP 主要实现了以下几个功能:
- 日志记录:在方法执行前后记录日志,方便调试和监控。
- 权限验证:在方法执行前进行权限验证,确保用户有访问权限。
- 事务管理:在方法执行前后进行事务管理,确保数据的一致性。
- 性能监控:统计方法的执行时间,分析系统性能。
流程图:
代码示例:
java
// 示例代码:使用 AOP 实现日志记录
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void beforeAdvice(JoinPoint joinPoint) {
System.out.println("Before method: " + joinPoint.getSignature().getName());
}
@After("execution(* com.example.service.*.*(..))")
public void afterAdvice(JoinPoint joinPoint) {
System.out.println("After method: " + joinPoint.getSignature().getName());
}
}
多个 AOP 是如何执行的
技术考查点:
- 对 AOP 执行顺序的理解
- 对 Spring AOP 原理的掌握
回答: 在 Spring AOP 中,多个 AOP 通知的执行顺序是由 AOP 代理的实现机制决定的。Spring AOP 有两种代理方式:JDK 动态代理和 CGLIB 代理。在 JDK 动态代理中,多个 AOP 通知会按照它们在配置文件或注解中的顺序依次执行;在 CGLIB 代理中,多个 AOP 通知会按照它们在字节码中的顺序依次执行。同时,Spring AOP 还支持通过 @Order 注解来指定 AOP 通知的执行顺序,值越小的通知越先执行。
流程图:
代码示例:
java
// 定义 AOP 通知类 1
@Aspect
@Component
@Order(1)
public class Aspect1 {
@Before("execution(* com.example.service.*.*(..))")
public void beforeAdvice1(JoinPoint joinPoint) {
System.out.println("Before advice 1");
}
}
// 定义 AOP 通知类 2
@Aspect
@Component
@Order(2)
public class Aspect2 {
@Before("execution(* com.example.service.*.*(..))")
public void beforeAdvice2(JoinPoint joinPoint) {
System.out.println("Before advice 2");
}
}
写代码: map 转 list
技术考查点:
- 对 Java 集合框架的掌握
- 代码实现能力
回答: 在 Java 中,可以使用多种方式将 Map 转换为 List。以下是几种常见的实现方式:
- 将 Map 的键转换为 List
- 将 Map 的值转换为 List
- 将 Map 的键值对转换为 List
代码示例:
java
import java.util.*;
public class MapToListExample {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map.put("key1", 1);
map.put("key2", 2);
map.put("key3", 3);
// 将 Map 的键转换为 List
List<String> keyList = new ArrayList<>(map.keySet());
System.out.println("Key List: " + keyList);
// 将 Map 的值转换为 List
List<Integer> valueList = new ArrayList<>(map.values());
System.out.println("Value List: " + valueList);
// 将 Map 的键值对转换为 List
List<Map.Entry<String, Integer>> entryList = new ArrayList<>(map.entrySet());
System.out.println("Entry List: " + entryList);
}
}
Spring 事务什么时候会失效
技术考查点:
- 对 Spring 事务管理的理解
- 常见的事务失效场景
回答: Spring 事务失效的常见场景有:
- 方法不是 public 修饰的,Spring AOP 只对 public 方法进行代理。
- 自调用问题,即一个类的方法调用自身的另一个事务方法,由于没有经过代理对象,事务不会生效。
- 异常被捕获但没有重新抛出,Spring 事务是基于异常来触发回滚的,如果异常被捕获而没有重新抛出,事务不会回滚。
- 事务传播行为配置错误,不同的事务传播行为会影响事务的生效情况。
流程图:
代码示例:
java
@Service
public class UserService {
@Autowired
private UserDao userDao;
@Transactional
public void updateUser() {
try {
userDao.updateUser();
// 模拟异常
int result = 1 / 0;
} catch (Exception e) {
// 捕获异常但未重新抛出,事务失效
}
}
}
this 自调用时如何失效的
技术考查点:
- 对 Spring AOP 代理机制的理解
- 自调用导致事务失效的原理
回答: 在 Spring 中,事务是通过 AOP 代理来实现的。当一个类的方法调用自身的另一个事务方法时,由于是通过 this 关键字调用的,实际上调用的是目标对象的方法,而不是代理对象的方法,因此不会触发 AOP 代理的事务增强逻辑,导致事务失效。
流程图:
代码示例:
java
@Service
public class UserService {
@Autowired
private UserDao userDao;
@Transactional
public void method1() {
// 自调用,事务失效
this.method2();
}
@Transactional
public void method2() {
userDao.updateUser();
}
}
算法题: 有效的括号
技术考查点:
- 对栈数据结构的掌握
- 算法设计和实现能力
回答: 可以使用栈来解决有效的括号问题。遍历字符串,遇到左括号时将其压入栈中,遇到右括号时,检查栈顶元素是否为对应的左括号,如果是则弹出栈顶元素,否则返回 false。遍历结束后,如果栈为空,则说明字符串中的括号是有效的。
代码示例:
java
import java.util.Stack;
public class ValidParentheses {
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
for (char c : s.toCharArray()) {
if (c == '(' || c == '[' || c == '{') {
stack.push(c);
} else {
if (stack.isEmpty()) {
return false;
}
char top = stack.pop();
if ((c == ')' && top != '(') || (c == ']' && top != '[') || (c == '}' && top != '{')) {
return false;
}
}
}
return stack.isEmpty();
}
}