用友项目管理部门后端一面2023.9.11"/>
【2024秋招】用友项目管理部门后端一面2023.9.11
1 实习
1.1 架构实例反向同步
1.2 你使用策略模式,不同的策略之间有没有干扰
策略模式(Strategy Pattern)是一种行为设计模式,它定义了一系列算法,并将每一个算法封装起来,使它们可以相互替换。策略模式的核心思想是定义一系列的算法,并将每一个算法封装到具有共同接口的独立的类中,从而使它们可以相互替换。
关于策略模式中不同策略之间的干扰,以下是几点考虑:
-
独立性:在理想的策略模式实现中,每个策略都应该是独立的,不同的策略之间不应该有任何干扰或依赖。这是策略模式的基本原则,确保每个策略可以独立地工作和替换。
-
状态共享:如果策略需要访问或修改某些共享资源或状态,可能会导致策略之间的干扰。在这种情况下,需要确保对共享资源的访问是线程安全的,并且策略使用的状态不会被其他策略意外地修改。
-
上下文传递:在某些实现中,策略可能需要从上下文中获取信息。如果上下文在策略之间共享,那么策略可能会受到上下文状态的影响。为了避免这种干扰,可以考虑为每个策略提供一个独立的上下文或确保上下文状态在策略执行之间是不变的。
-
策略选择:策略的选择和应用通常是由一个称为“上下文”的外部实体控制的。确保在运行时选择和应用正确的策略是很重要的,以避免不必要的干扰或错误。
总的来说,策略模式的目的是提供一种机制,使得算法或策略可以独立于使用它们的客户端代码进行变化。为了确保不同的策略之间没有干扰,需要确保每个策略都是独立的,并且在设计和实现时考虑到可能的共享状态和资源访问问题。
1.3 中弘的同步任务,你如何处理线程的并发问题
答:一个表一个线程,这是同步的粒度,各个表之间互相不影响
2 spring框架
2.1 讲一讲bean的生命周期
在Spring框架中,Bean的生命周期描述了从创建到销毁的过程。Spring容器管理Bean的整个生命周期。以下是Bean在Spring容器中的生命周期的详细步骤:
-
实例化Bean:Spring容器首先创建Bean的实例。
-
设置Bean属性:根据配置,Spring容器注入Bean的属性,这也被称为依赖注入。
-
调用
BeanNameAware
的setBeanName
方法:如果Bean实现了BeanNameAware
接口,Spring将传递Bean的ID到setBeanName
方法。 -
调用
BeanFactoryAware
的setBeanFactory
方法:如果Bean实现了BeanFactoryAware
接口,Spring容器将调用setBeanFactory
方法并传递自身实例。 -
调用
ApplicationContextAware
的setApplicationContext
方法:如果Bean实现了ApplicationContextAware
接口,它的setApplicationContext
方法将被调用,传递当前应用上下文作为参数。 -
BeanPostProcessor
的postProcessBeforeInitialization
方法:如果Bean实现了BeanPostProcessor
接口,postProcessBeforeInitialization
方法将被调用。 -
调用
InitializingBean
的afterPropertiesSet
方法:如果Bean实现了InitializingBean
接口,afterPropertiesSet
方法将被调用。 -
调用自定义初始化方法:如果在Bean配置中使用
init-method
属性定义了初始化方法,该方法将被调用。 -
BeanPostProcessor
的postProcessAfterInitialization
方法:如果Bean实现了BeanPostProcessor
接口,postProcessAfterInitialization
方法将被调用。 -
Bean现在已经准备好使用:此时,Bean已经初始化完成并可以被应用程序使用。
-
调用
DisposableBean
的destroy
方法:如果Bean实现了DisposableBean
接口,当容器关闭时,destroy
方法将被调用。 -
调用自定义销毁方法:如果在Bean配置中使用
destroy-method
属性定义了销毁方法,当容器关闭时,该方法将被调用。
这就是Spring Bean的生命周期。在这个过程中,开发者可以通过实现特定的接口或使用特定的配置属性,介入Bean的生命周期,执行自定义的逻辑。
2.1.1 为什么需要BeanNameAware,BeanFactoryAware,ApplicationContextAware这三个扩展点,讲讲三个扩展点的作用
在Spring框架中,BeanNameAware
、BeanFactoryAware
和 ApplicationContextAware
是三个常用的Aware接口,它们允许一个Bean在被初始化或装配到容器时获得关于容器的信息。这些接口提供了Bean与Spring容器之间的回调机制。
-
BeanNameAware:
- 作用:允许一个Bean获取其在Spring容器中的名称。
- 方法:
void setBeanName(String name)
- 使用场景:当Bean需要知道其在容器中的名称(或ID)时,可以实现此接口。这在某些场景中可能很有用,例如,当一个Bean需要根据其名称进行某些特定的配置或行为时。
-
BeanFactoryAware:
- 作用:允许一个Bean引用到它所在的BeanFactory。
- 方法:
void setBeanFactory(BeanFactory beanFactory)
- 使用场景:当Bean需要与其所在的BeanFactory交互,例如查询其他Bean、访问容器的配置或生命周期操作时,可以实现此接口。这为Bean提供了更大的灵活性,使其能够与容器进行更深入的交互。
-
ApplicationContextAware:
- 作用:允许一个Bean引用到整个ApplicationContext。
- 方法:
void setApplicationContext(ApplicationContext applicationContext)
- 使用场景:当Bean需要访问应用上下文,例如获取其他Bean、发布事件、访问资源等,可以实现此接口。与
BeanFactoryAware
相比,ApplicationContextAware
提供了更丰富的上下文信息和功能。
这些Aware接口为Bean提供了一种机制,使其能够在初始化时获得关于容器的信息和功能。这增加了Bean的灵活性,使其能够更好地与Spring容器集成。然而,过度使用这些接口可能导致Bean与Spring容器过于紧密地耦合,从而降低了代码的可移植性和可测试性。因此,建议在确实需要时才使用这些接口,并尽量减少对它们的依赖。
2.2 如何解决bean循环依赖
2.3 bean的初始化为什么需要有这么多种方式
- 不同的需求(加入一些自定义的逻辑):不同的应用和场景可能需要不同的初始化逻辑。
- 向后兼容性:随着Spring的发展,新的初始化方法被引入,但旧的方法仍然被支持以确保向后兼容性。
- 选择权:提供多种初始化方式使开发者可以选择最适合他们需求的方法。
- 细粒度控制:某些初始化方法,如
@PostConstruct
注解,允许开发者在特定的生命周期阶段执行逻辑。
2.4 spring事务失效的情况
- 非public方法上使用
@Transactional
:如果在一个类的非public方法上使用@Transactional
注解,事务可能不会被正确地应用。 - 自调用问题:如果一个事务方法被同一个类中的另一个非事务方法调用,事务可能不会生效。
- 异常处理:默认情况下,只有在运行时异常(unchecked exceptions)发生时,事务才会回滚。对于已检查的异常(checked exceptions),事务不会回滚,除非明确配置。
- 不正确的事务传播行为:如果事务的传播行为(propagation behavior)配置不正确,可能会导致事务不按预期工作。
- 事务只读设置:如果事务被标记为只读,但方法试图执行写操作,事务可能不会按预期工作。
2.5 spring的事务是如何传播的
- REQUIRED:如果当前存在事务,就使用当前事务,否则创建一个新的事务。
- SUPPORTS:如果当前存在事务,就使用当前事务,否则执行非事务性的。
- MANDATORY:如果当前存在事务,就使用当前事务,否则抛出异常。
- REQUIRES_NEW:总是创建一个新的事务,并暂停当前事务(如果存在)。
- NOT_SUPPORTED:总是执行非事务性的,暂停当前事务(如果存在)。
- NEVER:总是执行非事务性的,如果存在当前事务则抛出异常。
- NESTED:如果当前存在事务,则嵌套执行事务,否则创建一个新的事务。
2.5.1 NESTED和REQUIRED有什么区别
NESTED 和 REQUIRED 是Spring事务管理中的两种传播行为,它们在事务处理上有所不同。以下是它们的区别和详细解释:
NESTED:
-
行为:当一个事务方法(称为内部事务)被另一个事务方法(称为外部事务)调用时,内部事务会运行在一个嵌套的事务中。这是一个子事务。
-
保存点:嵌套事务使用了保存点(savepoint)的概念。当嵌套事务开始时,会创建一个保存点。如果嵌套事务失败,它会回滚到这个保存点,而不是回滚整个外部事务。但如果外部事务失败并回滚,那么整个事务(包括内部事务)都会回滚。
-
共享与否:嵌套事务并不是真正地共享外部事务,但它是外部事务的一部分。它有自己的独立的提交和回滚设置,但仍然受到外部事务的影响。
REQUIRED:
-
行为:如果当前存在事务,方法会加入到这个事务中,共享同一个事务上下文。如果没有事务,它会启动一个新的事务。
-
共享:在REQUIRED模式下,所有参与的方法都共享同一个事务上下文。这意味着,如果其中一个方法导致事务回滚,整个事务都会回滚。
-
没有保存点:与NESTED不同,REQUIRED不使用保存点的概念。所有操作都在同一个事务上下文中执行,任何部分的失败都会导致整个事务的回滚。
总结:NESTED和REQUIRED的主要区别在于如何处理事务的回滚和提交。在NESTED中,内部事务可以独立于外部事务进行回滚或提交,但仍然受到外部事务的影响。而在REQUIRED中,所有方法都共享同一个事务上下文,整个事务是一个单一的单位。
2.5.2 spring事务的默认传播级别
在Spring中,事务的默认传播行为(Propagation Level)是 REQUIRED
。
REQUIRED:
- 当当前存在事务时,加入到这个事务中。如果当前没有事务,就新建一个事务。这是大多数情况下的常见选择,因为它支持当前的事务,并在没有事务的情况下创建一个新的事务。
这意味着,如果你在一个方法上使用 @Transactional
注解而没有明确指定传播行为,那么它将默认使用 REQUIRED
传播行为。
2.5.3 REQUIRES_NEW的两个事务是独立的吗还是相互影响的,他们是嵌套关系吗
REQUIRES_NEW的两个事务关系:
使用REQUIRES_NEW
传播行为时,每次都会启动一个新的事务。如果当前已经存在一个事务,那么这个存在的事务会被挂起,直到新的事务完成。
-
独立性:
REQUIRES_NEW
启动的事务是独立的。这意味着,新事务的提交或回滚不会影响到外部的事务。同样,外部事务的提交或回滚也不会影响到REQUIRES_NEW
启动的事务。 -
嵌套关系:尽管
REQUIRES_NEW
启动的事务是在外部事务的上下文中启动的,但它们并不是嵌套事务。它们是两个完全独立的事务,只是一个在另一个的上下文中启动。
2.5.4 嵌套事务如何实现:
嵌套事务是通过NESTED
传播行为来实现的。在NESTED
模式下,如果当前存在一个事务,那么会启动一个嵌套事务。这个嵌套事务是外部事务的子事务。
-
保存点:嵌套事务使用了保存点(savepoint)的概念。当嵌套事务开始时,会创建一个保存点。如果嵌套事务失败,它会回滚到这个保存点,而不是回滚整个外部事务。但如果外部事务失败并回滚,那么整个事务(包括嵌套事务)都会回滚。
-
实现细节:嵌套事务的实现依赖于底层数据库是否支持保存点。如果数据库支持保存点,那么Spring可以使用这个特性来实现嵌套事务。如果数据库不支持保存点,那么
NESTED
传播行为可能无法正常工作。
总结:REQUIRES_NEW
和NESTED
都允许在一个事务的上下文中启动另一个事务,但它们的行为和实现方式是不同的。REQUIRES_NEW
启动的是一个完全独立的事务,而NESTED
启动的是一个嵌套事务,它是外部事务的子事务。
3 mysql
3.1 mysql的隔离级别
3.2 描述一下B+树木
3.3 一条查询sql的解析过程
3.4 解释一下索引合并和下推
4 redis
4.1 为什么redis这么快呢
4.2 怎么理解redis的单线程
4.3 为什么redis要用单线程,而不是多线程呢
答:redis的性能瓶颈在于网络IO而不是cpu
4 反问
4.1 你们是什么部门呢
答:项目管理,项目进度,成本,人力等
更多推荐
【2024秋招】用友项目管理部门后端一面2023.9.11
发布评论