框架篇面试题

Spring

1.什么是spring

Spring是一个开源的企业级应用框架。它旨在简化Java开发,特别是企业级应用程序的开发,通过提供一系列基础功能和模块,帮助开发者应对复杂性,实现松耦合、高内聚、易于测试和可扩展的软件系统。Spring框架的核心价值在于其对控制反转(Inversion of Control, IoC)面向切面编程(Aspect-Oriented Programming, AOP)的支持,以及对众多第三方库和标准的整合能力。

2.Spring的核心框架包括哪些?

Spring框架的核心组成部分包括:

1. Spring Core:提供了IoC容器,通过依赖注入(Dependency Injection, DI)机制管理对象的创建、装配和生命周期。容器负责对象的实例化、依赖关系的注入以及对象的生命周期管理,使得代码更加模块化和可测试。

2. Spring AOP:支持面向切面编程,允许将横切关注点(如日志、事务管理、权限控制等)从业务逻辑中解耦,并以声明式的方式统一管理和织入到目标对象的特定执行点。

3. Spring JDBC、Spring ORM和Spring Data:提供对数据库访问的简化支持,包括对JDBC、JPA、Hibernate等多种数据访问技术的封装,以及Spring Data模块提供的基于Repository模式的统一数据访问API。

4. Spring MVC和Spring WebFlux:构建Web应用程序的模型-视图-控制器(Model-View-Controller, MVC)框架,支持RESTful API开发和前后端分离的架构。

5. Spring Test:提供了一套全面的测试支持工具,简化了对Spring应用程序各个层(包括控制器、服务、数据访问层等)的单元测试和集成测试。

6. Spring Security:为应用程序提供全面的安全解决方案,包括认证、授权、密码加密、会话管理等功能。

7. Spring Cloud:一套微服务架构解决方案,包含服务注册与发现、配置管理、负载均衡、熔断降级、分布式追踪等组件,助力构建云原生微服务体系。

3.你在项目中为什么要使用spring

在项目中使用Spring的原因:

1. 简化开发复杂性:Spring通过IoC和DI机制,将对象的创建、依赖管理等工作交由容器处理,极大地降低了代码之间的耦合度,提高了代码的可读性和可维护性。开发者只需关注业务逻辑的实现,而无需关心对象的生命周期管理。

2. 提高生产力:Spring提供了丰富的模块和工具,如MVC框架、模板引擎、数据访问抽象、安全框架等,极大地减少了重复工作,加快了开发速度。同时,Spring的自动装配、AOP等特性,使得开发者可以更专注于业务逻辑,而不是基础设施的搭建。

3. 易于测试:Spring框架鼓励面向接口编程和依赖注入,使得组件易于被mock对象替换,便于进行单元测试和集成测试。Spring Test模块提供了对Spring应用程序的无缝测试支持。

4. 强大的生态系统与社区支持:Spring拥有庞大的开发者社区和丰富的第三方库集成,遇到问题时容易找到解决方案。Spring Boot和Spring Cloud等项目进一步简化了应用程序的搭建和微服务架构的实施。

5. 标准化与扩展性:Spring遵循诸多业界标准(如JSR规范),并且对主流技术(如数据库访问、消息队列、NoSQL数据库、云服务等)有良好的支持和集成,使得应用程序易于与其他系统集成,具有良好的扩展性。

4.Spring的常见容器(Spring boot的常见容器)

两者都使用Spring的IoC(Inversion of Control)容器来管理应用程序中的组件(Bean)及其依赖关系。但是,Spring Boot在容器的使用和配置上进行了大量的自动化和简化。

常见容器:

Spring框架的常见容器:

1. Spring ApplicationContext:这是Spring框架的核心容器,它扩展了BeanFactory接口,不仅提供了Bean的创建、配置和管理功能,还添加了国际化支持、事件传播、资源访问等企业级服务。在Spring应用中,通常通过实现ApplicationContextAware接口或使用ClassPathXmlApplicationContext、AnnotationConfigApplicationContext等类来创建和初始化ApplicationContext。

2. WebApplicationContext:对于Web应用程序,Spring提供了WebApplicationContext,它是ApplicationContext的子接口,专为Web环境设计,能够与Servlet容器(如Tomcat、Jetty等)无缝集成,为Web组件(如Servlet、Filter、Listener等)提供Bean的访问能力。

Spring Boot的常见容器:

1. Spring Boot内置的ApplicationContext:

Spring Boot在启动过程中会自动创建并配置一个ApplicationContext,根据项目的配置和依赖,可能是AnnotationConfigServletWebServerApplicationContext(适用于Servlet环境)或AnnotationConfigApplicationContext(适用于非Web环境)。这个容器继承自Spring的ApplicationContext,包含了所有标准功能,并且Spring Boot对其进行了大量的自动化配置,如自动扫描组件、自动绑定配置属性、自动配置Spring MVC、Spring Data等模块。

2. 嵌入式Servlet容器:Spring Boot的一大特色是它能够“开箱即用”地嵌入各种Servlet容器(如Tomcat、Jetty、Undertow等),无需单独部署这些容器。这些嵌入式容器也是Spring Boot应用程序的一部分,由Spring Boot自动配置和管理。虽然它们不是Spring容器本身,但与Spring容器紧密协作,构成了Spring Boot应用的运行环境。

总结来说,Spring框架和Spring Boot在容器方面的主要差异在于:

•自动化配置:Spring Boot通过@EnableAutoConfiguration注解和spring-boot-autoconfigure模块,实现了大量Spring组件和第三方库的自动配置,极大地简化了容器的配置过程。

•嵌入式Servlet容器:Spring Boot提供了嵌入式Servlet容器的支持,使得开发和部署Web应用程序更为便捷,而传统的Spring框架需要与独立部署的Servlet容器配合使用。

5.常见的Spring注解 Spring MVC注解 Mybatis注解 Spring boot注解

Spring注解:

        1. @Component:标记一个类作为Spring容器中的组件(Bean),是@Service、@Repository、@Controller等注解的基础。

        2. @Service:用于标记业务逻辑层(Service)的类,通常包含应用的核心业务逻辑。

        3. @Repository:用于标记数据访问层(DAO/Repository)的类,通常包含数据库操作或其他持久化操作。

        4. @Controller:标记一个类作为Spring MVC控制器,处理HTTP请求。

        5. @Autowired:自动装配Bean,Spring会根据类型或名称自动将Bean注入到标注了@Autowired的字段、方法或构造函数中。

        6. @Qualifier:配合@Autowired使用,用于当有多个相同类型的Bean时,通过指定Bean的名称来精确注入。

        7. @Value:用于注入配置属性值,可以从属性文件、环境变量等来源获取。

        8. @Configuration:标记一个类作为Spring配置类,类中可以包含@Bean方法来定义Bean。

        9. @Bean:在@Configuration类中声明Bean定义,相当于XML配置中的<bean>元素。

        10. @Profile:标记Bean只在特定的Spring profile激活时生效。

        11. @PostConstruct:标记在Bean初始化完成后执行的方法。

        12. @PreDestroy:标记在Bean销毁前执行的方法。

Spring MVC注解:

        1. @RequestMapping:用于映射HTTP请求到控制器的方法上,可以指定请求路径、HTTP方法、参数、 consumes/produces 类型等。

        2. @GetMapping, @PostMapping, @PutMapping, @DeleteMapping @PatchMapping:分别对应HTTP的GET、POST、PUT、DELETE、PATCH方法,是对@RequestMapping的快捷方式。

        3. @PathVariable:用于将URL路径中的占位符参数绑定到控制器方法的形参上。

        4. @RequestParam:用于将查询参数或表单字段绑定到控制器方法的形参上。

        5. @RequestBody:用于将HTTP请求体中的JSON、XML等数据绑定到控制器方法的形参上。

        6. @RequestHeader:用于将HTTP请求头的值绑定到控制器方法的形参上。

        7. @CookieValue:用于将HTTP请求中的Cookie值绑定到控制器方法的形参上。

        8. @ModelAttribute:用于将请求参数绑定到方法参数或返回值表示的模型对象上,常用于表单数据绑定和数据预处理。

        9. @SessionAttributes:标记控制器类,表示其方法中使用@ModelAttribute注解的模型对象应存储在HttpSession中。

        10. @ControllerAdvice:定义全局的异常处理器、数据绑定器、模型属性处理器等,对所有@Controller生效。

MyBatis注解:

        1. @Mapper:标记一个接口作为MyBatis的Mapper接口,用于定义SQL映射。

        2. @Select, @Insert, @Update, @Delete:分别对应SQL的SELECT、INSERT、UPDATE、DELETE语句,用于在Mapper接口方法上定义SQL查询。

        3. @Results:定义结果集映射,用于复杂类型的查询结果转换。

        4. @Result:在@Results内部使用,定义单个结果映射,包括字段名、Java属性名、类型转换器等。

        5. @Param:在Mapper接口方法的参数上使用,为参数命名,以便在SQL语句中引用。

        6. @Options:在Mapper接口方法上使用,设置SQL执行的相关选项,如fetchSize、timeout、useCache等。

Spring Boot注解:

        1. @SpringBootApplication:组合了@SpringBootConfiguration、@EnableAutoConfiguration和@ComponentScan,用于标记主配置类,启动Spring Boot应用。

        2. @EnableAutoConfiguration:启用Spring Boot的自动配置机制,根据类路径中的依赖自动配置Bean。

        3. @SpringBootConfiguration:等同于@Configuration,标记类作为Spring Boot配置类。

        4. @ComponentScan:自动扫描并注册Bean,等同于Spring的@ComponentScan,通常用于指定扫描基础包。

        5. @ConfigurationProperties:绑定外部配置(如application.properties/yml)到Bean的属性上。

        6. @EnableConfigurationProperties:启用特定@ConfigurationProperties类的自动绑定。

        7. @Entity:在JPA实体类上使用,表示这是一个持久化实体。

        8. @Table:在JPA实体类上使用,指定对应的数据库表名及其它表属性。

        9. @Id:标记实体类的主键字段。

        10. @GeneratedValue:指定主键生成策略。

        11. @DataJpaTest:用于测试JPA相关功能的Spring Boot测试注解,自动配置一个内嵌的数据库、Spring Data JPA仓库以及一个TestEntityManager。

        12. @WebMvcTest:用于测试Spring MVC控制器的Spring Boot测试注解,仅加载与Web MVC相关的上下文。

        13. @SpringBootTest:用于启动整个Spring Boot应用上下文进行集成测试。

6.你是如何理解Spring注解 Spring MVC注解 Mybatis注解 Spring boot注解(你认为常用的spring注解是否包括 springmvc注解 mybatis注解 spring boot注解吗)

常用的Spring注解通常是指Spring框架本身提供的那些注解,它们构成了Spring的核心IoC(Inversion of Control,控制反转)和AOP(Aspect-Oriented Programming,面向切面编程)能力,以及一些通用的Bean管理、生命周期方法、资源注入等方面的注解。这些注解适用于任何基于Spring的应用,无论是否使用了Spring MVC、MyBatis或Spring Boot。

Spring MVC注解、MyBatis注解和Spring Boot注解则是针对各自特定领域的扩展注解,分别用于构建Web应用程序、进行ORM操作和简化Spring应用的创建与配置。尽管它们都建立在Spring框架的基础上,但这些注解更具有针对性,主要用于解决各自领域内的特定问题。

因此,通常所说的“常用的Spring注解”并不直接包含Spring MVC注解、MyBatis注解或Spring Boot注解,因为它们属于不同的子框架或工具集。

但如果是在讨论一个具体使用了Spring全家桶(包括Spring MVC、MyBatis、Spring Boot等)的项目,那么在该项目的上下文中,上述所有类型的注解都可以被视为“常用的Spring相关注解”。

综上所述:

•常用的Spring注解是指Spring框架本身提供的核心注解,如@Component、@Autowired、@Configuration等。

•Spring MVC注解、MyBatis注解、Spring Boot注解分别是各自子框架或工具集特有的注解,如Spring MVC的@RequestMapping、MyBatis的@Mapper、Spring Boot的@SpringBootApplication等。

虽然它们都属于Spring生态,但在讨论时通常会根据上下文区分这些注解所属的具体子框架或工具集。如果需要了解的是一个项目中可能用到的所有Spring相关注解,那么应该将Spring注解、Spring MVC注解、MyBatis注解和Spring Boot注解综合起来考虑。

7.在 Spring 中,有几种配置 Bean 的方式?

基于XML的配置

原理:通过在XML配置文件中编写<bean>元素来定义Bean,指定Bean的类、属性、初始化方法、销毁方法、依赖关系等信息。

<beans>
    <bean id="exampleBean" class="com.example.ExampleBean">
        <property name="propertyName" value="propertyValue"/>
        <!-- 其他属性配置 -->
    </bean>
</beans>

基于注解的配置

原理:在Java类、方法、字段或参数上使用Spring提供的注解(如@Component、@Service、@Repository、@Controller、@Autowired、@Value等)来声明Bean、定义依赖关系和注入属性值。

@Service
public class ExampleService {
    @Autowired
    private ExampleRepository repository;

    @Value("${app.property}")
    private String propertyValue;

    // ...
}

基于Java的配置

原理:通过编写Java类(通常使用@Configuration注解标记)来定义Bean,并在类中使用@Bean注解的方法来声明和配置Bean。

@Configuration
public class AppConfig {
    @Bean
    public ExampleBean exampleBean() {
        ExampleBean bean = new ExampleBean();
        bean.setPropertyValue("propertyValue");
        // ... 其他配置
        return bean;
    }
}

8.什么是Bean:

在Spring框架中,Bean(也称为Spring Bean)是一个由Spring IoC(Inversion of Control,控制反转)容器管理的对象。简单来说,Bean就是被Spring容器实例化、组装、管理并最终交付给应用程序使用的对象。这些对象可以是任何类型的Java对象,如服务类、数据访问对象(DAO)、模型对象等。

9.为什么项目要使用Bean:

项目使用Bean主要有以下几个原因:

1. 降低耦合性:通过依赖注入,Bean之间解耦,不再直接依赖对方的实现细节。这使得代码更易于测试、维护和扩展,因为组件间的关系由配置文件管理,而非硬编码在代码中。

2. 简化对象管理:Spring容器负责Bean的生命周期管理,包括对象的创建、初始化、销毁等,开发者无需手动编写这些管理代码,从而专注于业务逻辑实现。

3. 增强灵活性与可配置性:Bean的配置信息与代码分离,可以在不修改源代码的情况下通过修改配置文件来改变Bean的行为或替换Bean的实现,增强了系统的灵活性和可配置性。

4. 提供企业级服务:Spring框架为Bean提供了诸如事务管理、AOP(面向切面编程)、消息服务、数据访问抽象等企业级服务,通过配置Bean即可轻松利用这些服务,无需手动编写大量基础设施代码。

10.Bean的生命周期

Spring Bean的生命周期主要包括以下几个阶段:

1. Bean定义:

        •定义方式:通过XML配置文件、JavaConfig类、注解等方式声明Bean的基本信息,如Bean的类名、作用域、初始化方法、销毁方法、依赖关系、属性值等。

2. Bean的创建:

        •实例化:Spring容器根据Bean定义信息,通过反射调用构造函数创建Bean的实例。

        •依赖注入:Spring容器按照依赖关系,将其他Bean注入到当前Bean的属性中,完成依赖关系的建立。

3. Bean的初始化:

        •默认初始化:如果Bean实现了InitializingBean接口,Spring会调用其afterPropertiesSet()方法进行初始化。

        •自定义初始化:如果在Bean定义中指定了初始化方法(如XML中的init-method属性或@PostConstruct注解),Spring会在Bean实例化和依赖注入完成后调用该方法。

        •工厂方法初始化:对于通过工厂方法创建的Bean,Spring可以调用工厂方法返回的初始化回调接口(如BeanFactoryPostProcessor或BeanPostProcessor)对Bean进行进一步的初始化。

4. Bean的使用:

        •依赖查找:应用程序通过Spring容器的getBean()方法或其他方式查找并获取Bean的实例,进行业务操作。

        •作用域管理:根据Bean定义的作用域(如singleton、prototype等),Spring容器可能创建单例Bean供全局共享,或每次请求都创建新的实例。

5. Bean的销毁:

        •默认销毁:如果Bean实现了DisposableBean接口,Spring会在销毁Bean之前调用其destroy()方法。

        •自定义销毁:如果在Bean定义中指定了销毁方法(如XML中的destroy-method属性或@PreDestroy注解),Spring会在关闭容器或Bean不再需要时调用该方法。

        •资源释放:在销毁阶段,Bean通常会释放持有的资源,如关闭数据库连接、清理缓存等。

概括来说,Spring Bean的生命周期包括定义、创建、初始化、使用和销毁五个阶段。

11.Spring Bean 有哪些作用域,它们之间有什么区别?

singleton :这种 bean 范围是默认的,这种范围确保不管接受到多少个请求,每个容器中只有一个 bean 的实例,单例的模式由 bean factory 自身来维护 。

prototype :原形范围与单例范围相反,为每一个 bean 请求提供一个实例 。

request :在请求 bean 范围内会每一个来自客户端的网络请求创建一个实例,在请求完成以后, bean 会失效并被垃圾回收器回收 。

Session :与请求范围类似,确保每个 session 中有一个 bean 的实例,在 session 过期后, bean 会 随之失效 。

global-session : global-session 和 Portlet 应用相关 。 当你的应用部署在 Portlet 容器中工作时,它 包含很多 portlet。 如果你想要声明让所有的 portlet 共用全局的存储变量的话,那么这全局变量需要存 储在 global-session 中 。

12.Spring如何处理线程并发问题?

Spring框架在处理并发线程问题时,主要通过以下几个方面来提供支持和解决方案:

1. 线程安全的Bean:

•Spring默认创建的Bean通常是单例的(除非声明为prototype作用域),这意味着所有请求共享同一个Bean实例。对于有状态的Bean,Spring鼓励使用无状态设计或线程安全的类,以避免并发问题。如果Bean需要持有状态,应确保状态的访问和更新操作是线程安全的,例如使用Atomic类、synchronized关键字或Lock实现。

2. 并发管理工具:

•Spring提供了对Java并发库(如java.util.concurrent包)的集成,包括ThreadPoolTaskExecutor、ThreadPoolTaskScheduler等线程池组件,用于管理并发任务的执行。通过配置这些组件,可以控制线程池大小、队列长度、拒绝策略等,以适应不同场景下的并发需求。

3. 事务管理:

•Spring的事务管理支持声明式事务,通过@Transactional注解或XML配置,可以轻松地在方法级别管理事务。Spring会确保在多线程环境下,同一事务内的操作在并发时保持原子性和一致性。通过事务隔离级别、锁机制等,Spring可以帮助避免脏读、不可重复读、幻读等问题。

4. 异步方法执行:

•Spring支持异步方法执行,通过@Async注解标记方法,Spring会使用TaskExecutor将方法调用放入后台线程执行,从而释放主线程继续处理其他请求。异步方法执行能够有效提升系统并发处理能力,避免阻塞等待耗时操作。

5. 并发数据结构:

•Spring提供了对Java并发数据结构(如ConcurrentHashMap、CopyOnWriteArrayList等)的支持和推荐使用,这些数据结构在多线程环境下能保证线程安全的读写操作。

6. AOP(面向切面编程)支持:

•Spring的AOP机制可以用来实现诸如事务管理、缓存、日志记录、权限控制等横切关注点,这些关注点往往涉及到多线程环境下的并发控制。通过AOP,可以在不侵入业务代码的前提下,集中管理这些并发相关的逻辑。

7. 消息驱动(如Spring Integration、Spring Cloud Stream):

•对于复杂的并发场景,如分布式系统中的消息处理,Spring提供了消息驱动框架(如Spring Integration、Spring Cloud Stream),这些框架支持消息队列、消息路由、消息转换等,能够在多线程、多进程甚至跨网络的环境中,保证消息的可靠传递和并发处理。

13.Spring的事务

spring支持编程式事务管理和声明式事务管理两种方式

Spring框架提供了强大的事务管理功能,使得开发者能够以声明式的方式轻松管理事务,确保数据的一致性和完整性。Spring事务管理的关键组件和特性包括:

1. 事务管理器(Transaction Manager):

•Spring事务管理器是事务管理的核心组件,它负责实际的事务操作,如开启事务、提交事务、回滚事务等。Spring支持多种事务管理器实现,包括:

        •DataSourceTransactionManager:用于JDBC事务管理,与DataSource(如HikariCP、Tomcat JDBC Pool等)配合使用。

        •HibernateTransactionManager / JpaTransactionManager:用于JPA(如Hibernate、EclipseLink等)或Hibernate的事务管理。

        •JtaTransactionManager:用于Java Transaction API (JTA)事务管理,适用于分布式事务场景。

2. 事务传播行为(Transaction Propagation):

•当事务方法被另一个事务方法调用时,如何处理事务边界成为需要考虑的问题。

Spring定义了七种事务传播行为,通过@Transactional注解的propagation属性指定:

        •REQUIRED(默认):如果当前存在事务,则加入当前事务;若不存在事务,则新建一个事务。

        •SUPPORTS:如果当前存在事务,则加入当前事务;若不存在事务,则以非事务方式执行。

        •MANDATORY:必须在一个已存在的事务中执行,否则抛出异常。

        •REQUIRES_NEW:总是新建一个事务,当前事务挂起。

        •NOT_SUPPORTED:以非事务方式执行,如果当前存在事务,则将其挂起。

        •NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。

        •NESTED:如果当前存在事务,则在嵌套事务内执行;若不存在事务,则新建一个事务。

3. 隔离级别(Isolation Level):

•事务隔离级别决定了事务之间读写数据的可见性和并发控制程度。

Spring支持四种标准的隔离级别,通过@Transactional注解的isolation属性指定:

        •DEFAULT(默认):使用数据库的默认隔离级别(通常是READ_COMMITTED)。

        •READ_UNCOMMITTED:最低隔离级别,允许脏读、不可重复读、幻读。

        •READ_COMMITTED:仅允许不可重复读和幻读,大多数数据库的默认级别。

        •REPEATABLE_READ:仅允许幻读,MySQL的默认级别(InnoDB引擎)。

        •SERIALIZABLE:最高隔离级别,完全避免并发问题,但可能导致严重的锁竞争和性能下降。

4. 回滚规则(Rollback Rules):

        •Spring事务管理允许定义在何种异常发生时回滚事务。通过@Transactional注解的rollbackFor和noRollbackFor属性,可以指定触发回滚的异常类型和不应触发回滚的异常类型。

5. 声明式事务管理:

        •使用@Transactional注解标记服务类的方法,即可实现声明式事务管理。Spring AOP会拦截这些方法的调用,根据注解的属性自动管理事务的边界和行为。

示例:

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    @Transactional(rollbackFor = Exception.class)
    public User createUser(User user) {
        userRepository.save(user);
        // 其他业务逻辑...
        if (someCondition) {
            throw new CustomException("Failed to create user");
        }
        return user;
    }
}

14.Spring事务失效

Spring事务失效通常是指在预期应该进行事务管理的方法中,事务并未按照预期进行回滚或提交。以下是可能导致Spring事务失效的一些常见原因:

1. @Transactional注解位置不正确:

•@Transactional注解需要放置在实际执行事务操作的方法上,或者包含这些方法的类上。如果注解放置在不恰当的位置(如私有方法、接口方法等),Spring可能无法识别并应用事务管理。

2. Spring AOP代理未生效:

•Spring事务管理依赖于AOP代理机制。如果事务管理的方法未通过Spring容器创建的代理对象调用(如内部方法调用、new关键字直接创建对象调用等),事务注解可能失效。确保总是通过Spring容器获取并使用Bean,以确保AOP代理的介入。

3. 事务传播设置不当:

•事务传播行为决定了当前方法在已有事务环境下如何参与事务。如果传播行为设置不当(如PROPAGATION_NEVER、PROPAGATION_NOT_SUPPORTED等),可能会导致事务无法启动或被意外中断。

4. 异常未被正确捕获或抛出:

•Spring事务默认在遇到运行时异常(RuntimeException及其子类)或已检查异常(通过rollbackFor属性指定)时进行回滚。如果事务方法内部的异常被捕获但未重新抛出,或者抛出了未配置为触发回滚的异常,事务可能不会回滚。

5. 配置问题:

•确保配置了正确的事务管理器(如DataSourceTransactionManager、JpaTransactionManager等),并与实际使用的数据源或持久化技术匹配。同时,检查事务相关的Bean是否被正确注入和配置。

6. 数据库引擎不支持事务:

•如果使用的是不支持事务的数据库引擎(如MyISAM引擎的MySQL表),事务管理将无法生效。

7. 并发控制导致的问题:

•如果在多线程环境下,对同一个数据源或JPA实体管理器进行并发事务操作,可能会导致事务管理失效。确保在并发场景下正确管理事务边界和锁策略。

8. 事务超时或死锁:

•如果事务执行时间过长或陷入死锁,可能会因超时而被数据库自动回滚,或者在尝试获取锁时失败,导致事务无法正常完成。

9. Spring Boot配置禁用事务管理:

•检查application.properties或application.yml中是否存在spring.jpa.open-in-view=false或类似禁用事务的配置。

15.Spring如何管理事务的。

Spring事务管理主要包括3个接口,Spring事务主要由以下三个共同完成的:

1、PlatformTransactionManager:事务管理器,主要用于平台相关事务的管理。主要包括三个方 法:

        ①、commit:事务提交。

        ②、rollback:事务回滚。

        ③、getTransaction:获取事务状态。

2、TransacitonDefinition:事务定义信息,用来定义事务相关属性,给事务管理器 PlatformTransactionManager使用这个接口有下面四个主要方法:

        ①、getIsolationLevel:获取隔离级别。

        ②、getPropagationBehavior:获取传播行为。

        ③、getTimeout:获取超时时间。

        ④、 isReadOnly:是否只读(保存、更新、删除时属性变为false--可读写,查询时为true--只读)事务管理 器能够根据这个返回值进行优化,这些事务的配置信息,都可以通过配置文件进行配置。

3、TransationStatus:事务具体运行状态,事务管理过程中,每个时间点事务的状态信息。例如:

        ①、hasSavepoint():返回这个事务内部是否包含一个保存点。

        ②、isCompleted():返回该事务是否已 完成,也就是说,是否已经提交或回滚。

        ③、isNewTransaction():判断当前事务是否是一个新事务。

15.什么是IOC DI AOP?(你了解 IOC DI AOP吗)

当然,我很熟悉IOC(Inversion of Control,控制反转)、DI(Dependency Injection,依赖注入)和AOP(Aspect-Oriented Programming,面向切面编程)这三个概念,它们都是Spring框架的核心特性,极大地影响了现代Java企业级应用的设计和开发方式。

IOC(Inversion of Control,控制反转):

•概念:控制反转是一种设计原则,指的是将对象的创建、管理和依赖关系的控制权从应用程序代码中移交给一个专门的容器(如Spring IoC容器),由容器负责对象的生命周期管理。应用程序不再直接创建和管理对象,而是通过容器获取所需的对象。

•目的:通过控制反转,可以降低代码之间的耦合度,使应用程序各组件之间解耦,更易于测试、维护和扩展。同时,容器能够提供诸如依赖注入、生命周期管理、资源绑定等服务,简化对象的配置和使用。

DI(Dependency Injection,依赖注入):

•概念:依赖注入是实现控制反转的一种具体技术,它指的是容器负责将依赖对象(即某个类所需要的其他对象)通过构造函数、setter方法或字段注入到需要它们的对象中。依赖关系在配置文件或注解中声明,而不是在代码中硬编码。

•目的:依赖注入使得组件间的依赖关系变得透明和可配置,避免了硬编码的依赖导致的紧耦合。通过依赖注入,可以很容易地替换组件的实现、调整依赖关系,有利于代码复用、测试驱动开发和模块化设计。

AOP(Aspect-Oriented Programming,面向切面编程):

•概念:面向切面编程是一种编程范式,它允许将跨越多个对象或模块的横切关注点(如日志记录、事务管理、权限检查、性能监控等)抽取为“切面”(Aspect),并以声明式的方式将切面织入到应用程序的特定执行点(如方法调用、异常抛出等)。AOP通过预编译或运行时动态代理技术实现切面的织入。

•目的:AOP旨在分离关注点,将业务逻辑与横切关注点解耦,使得业务代码更纯净,关注点的修改不影响业务逻辑。通过AOP,可以集中管理、复用和修改横切关注点,提高代码的可维护性和可扩展性,降低模块间的耦合度。

总结来说,IOC是设计原则,强调将对象的控制权交给容器;DI是实现IOC的具体技术,通过注入依赖关系来解耦组件;AOP则是编程范式,通过切面来分离和管理横切关注点。这三者共同构成了Spring框架的核心理念和技术基础,极大地提升了Java企业级应用的开发效率和软件质量。

17.解释一下Spring AOP里面的几个名词:

1、切面(Aspect):被抽取的公共模块,可能会横切多个对象。 在Spring AOP中,切面可以使用通用 类(基于模式的风格) 或者在普通类中以 @AspectJ 注解来实现。

2、连接点(Join point):指方法,在Spring AOP中,一个连接点 总是 代表一个方法的执行。

3、通知(Advice):在切面的某个特定的连接点(Join point)上执行的动作。通知有各种类型,其中 包括“around”、“before”和“after”等通知。许多AOP框架,包括Spring,都是以拦截器做通知模型, 并 维护一个以连接点为中心的拦截器链。

4、切入点(Pointcut):切入点是指 我们要对哪些Join point进行拦截的定义。通过切入点表达式,指 定拦截的方法,比如指定拦截add、search。

5、引入(Introduction):(也被称为内部类型声明(inter-type declaration))。声明额外的方法 或者某个类型的字段。Spring允许引入新的接口(以及一个对应的实现)到任何被代理的对象。例如, 你可以使用一个引入来使bean实现 IsModified 接口,以便简化缓存机制。

6、目标对象(Target Object): 被一个或者多个切面(aspect)所通知(advise)的对象。也有人把 它叫做 被通知(adviced) 对象。 既然Spring AOP是通过运行时代理实现的,这个对象永远是一个 被 代理(proxied) 对象。

7、织入(Weaving):指把增强应用到目标对象来创建新的代理对象的过程。Spring是在运行时完成 织入。

18. Spring中AOP的底层是怎么实现的?

Spring中AOP底层的实现其实是基于JDK的动态代理和cglib动态创建类进行动态代理来实现的:

1、第一种基于JDK的动态代理的原理是:

基于接口:JDK动态代理通过java.lang.reflect.Proxy类和InvocationHandler接口实现。它要求目标对象必须实现了至少一个接口。代理对象同样会实现这些接口,并在方法调用时转发给InvocationHandler的invoke()方法。在invoke()方法中,可以实现前置通知(方法调用前执行)、后置通知(方法调用后执行)、环绕通知(包裹方法调用前后)、异常通知(方法抛出异常时执行)等

// 创建代理对象
MyInterface proxy = (MyInterface) Proxy.newProxyInstance(
    getClass().getClassLoader(),
    new Class[] { MyInterface.class },
    new InvocationHandler() {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // 前置通知(如记录开始时间、日志等)
            Object result;
            try {
                // 目标方法调用
                result = method.invoke(targetObject, args);
                // 后置通知(如记录结束时间、日志等)
            } catch (Exception e) {
                // 异常通知(如记录异常信息、回滚事务等)
                throw e;
            }
            return result;
        }
    }
);

2.基于CGLIB动态代理的原理:

•基于子类:CGLIB库(Code Generation Library)通过生成目标类的子类来实现代理,因此不需要目标对象实现任何接口。它通过字节码技术(如ASM库)在运行时生成一个继承自目标类的新类,并在新类的方法中插入切面逻辑。由于是基于继承,CGLIB代理可以代理非接口方法。// 使用CGLIB增强器创建代理对象

// 使用CGLIB增强器创建代理对象
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(MyClass.class);
enhancer.setCallback(new MethodInterceptor() {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        // 前置通知
        Object result;
        try {
            // 目标方法调用
            result = proxy.invokeSuper(obj, args);
            // 后置通知
        } catch (Exception e) {
            // 异常通知
            throw e;
        }
        return result;
    }
});
MyClass proxy = (MyClass) enhancer.create();

19.Spring的循环依赖

循环依赖在spring中是允许存在,spring框架依据三级缓存已经解决了大部分的循环依赖

一级缓存:单例池,缓存已经经历了完整的生命周期,已经初始化完成的bean对象

二级缓存:缓存早期的bean对象(生命周期还没走完)

三级缓存:缓存的是ObjectFactory,表示对象工厂,用来创建某个对象的

Spring boot

1.什么是Spring boot ?

        用来简化spring应用的初始搭建以及开发过程

        使用特定的方式来进行配置(properties或yml文件)

        创建独立的spring引用程序 main方法运行

        嵌入的Tomcat 无需部署war文件

        简化maven配置

        自动配置spring添加对应功能starter自动化配置

2.Springboot 有哪些优点?(你为什么开发要使用Spring boot)

        减少开发,测试时间和努力。

        使用JavaConfig有助于避免使用XML。

        避免大量的Maven导入和各种版本冲突。

        提供意见发展方法。

        通过提供默认值快速开始开发。

        没有单独的Web服务器需要。这意味着你不再需要启动Tomcat,Glassfish或其他任何东西。 需要更少的配置 因为没有web.xml文件。只需添加用@ Configuration注释的类,然后添加用 @Bean注释的方法,Spring将自动加载对象并像以前一样对其进行管理。您甚至可以将 @Autowired添加到bean方法中,以使Spring自动装入需要的依赖关系中。

        基于环境的配置 使用这些属性,您可以将您正在使用的环境传递到应用程序:- Dspring.profiles.active = {enviornment}。在加载主应用程序属性文件后,Spring将在 (application{environment} .properties)中加载后续的应用程序属性文件。

3.properties和yml 有什么区别 ?采用哪个更好?

properties yaml(.yml 或 .yaml)都是Spring Boot 应用中常用的配置文件格式,前者简单直观,后者结构化且表达力强。根据项目的具体需求和团队偏好,可以选择适合的格式进行配置。Spring Boot 完全支持这两种格式。

properties 文件:

•格式:.properties 文件采用简单的键值对形式,键与值之间用等号(=)分隔,每行表示一个配置项。值可以使用双引号包裹,以支持包含空格和特殊字符的字符串。

YAML 文件(.yml 或 .yaml):

•格式:YAML(YAML Ain't Markup Language)是一种人类可读的数据序列化格式,比 .properties 更加结构化和灵活。YAML 支持嵌套的数据结构,如列表、映射(键值对)等。键值对之间使用冒号(:)分隔,缩进表示层级关系。注释使用井号(#)开头。

对于大多数现代Spring Boot应用,尤其是配置较为复杂的情况,推荐使用yml文件,因其具有更好的可读性、结构化表达能力和工具支持。但对于简单应用或团队有特定偏好的情况下,properties文件也是一个可行的选择。

4.Spring boot 的配置过程

        1. 启动Spring Boot应用:

        2. 加载Spring Boot环境:

        3. 加载配置源:

        4. 应用默认配置与用户自定义配置的合并:

        5. 初始化Spring Application Context:

        6. 自动配置:

        7. 用户自定义的配置类加载:

        8. Bean的初始化:

        9. 启动完成:

4.如何使用Spring boot管理日志?

1. 日志框架的选择与集成

Spring Boot默认使用Logback作为日志实现,同时也支持Java Util Logging、Log4j2等其他日志框架。默认情况下,如果你使用Spring Boot的spring-boot-starter或spring-boot-starter-web等 starters,Logback 和相关依赖已经被包含在内。若要切换至其他日志框架,例如Log4j2,需要排除默认的Logback依赖,并添加对应的starter或直接引入Log4j2相关库。

2. 日志配置

通过application.properties或application.yml配置Spring Boot允许在application.properties或application.yml文件中进行基本的日志配置。

通过XML配置文件

对于更复杂的日志配置,如自定义日志处理器、过滤规则、多文件输出等,通常需要使用日志框架本身的配置文件。对于Logback,应创建名为logback-spring.xml的配置文件放在src/main/resources目录下,Spring Boot会自动识别并使用此文件。

3. 使用日志API记录日志

在代码中,使用日志框架提供的API记录日志。由于Spring Boot通过SLF4J作为日志门面,建议始终使用SLF4J的API,以保持日志系统的可插拔性。

4. 多环境日志配置

对于不同的部署环境(如开发、测试、生产),可以通过Spring Boot的多环境配置特性来区分日志设置。在application-{profile}.properties或application-{profile}.yml中编写特定环境的日志配置,然后启动应用时指定对应的profile。

5. 实时日志查看与管理

对于生产环境中的Spring Boot应用,可以结合如Spring Boot Actuator的/logfile端点或外部日志管理服务(如ELK Stack、Graylog等)来远程查看和管理实时日志。

5.Spring boot的自动装配原理

Mybatis

1.什么是Mybatis?

1、Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,开发时只需要关注SQL语句本 身,不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。程序员直接编写原生 态sql,可以严格控制sql执行性能,灵活度高。

2、MyBatis 可以使用 XML 或注解来配置和映射原生信息,将 POJO映射成数据库中的记录,避免了几 乎所有的 JDBC 代码和手动设置参数以及获取结果集。

3、通过xml 文件或注解的方式将要执行的各种 statement 配置起来,并通过java对象和 statement中 sql的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象并 返回。(从执行sql到返回result的过程)。

2.. Mybaits的优点(为什么要使用mybatis):

1、基于SQL语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL写在XML 里,解除sql与程序代码的耦合,便于统一管理;提供XML标签,支持编写动态SQL语句,并可重用。

2、与JDBC相比,减少了50%以上的代码量,消除了JDBC大量冗余的代码,不需要手动开关连接;

3、很好的与各种数据库兼容(因为MyBatis使用JDBC来连接数据库,所以只要JDBC支持的数据库 MyBatis都支持)。

4、能够与Spring很好的集成;

5、提供映射标签,支持对象与数据库的ORM字段关系映射;提供对象关系映射标签,支持对象关系组 件维护。

3.Mybatis的执行流程

4.#{}和${}的区别是什么?

        #{} 是预编译处理

        ${} 是字符串替换。

Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值; Mybatis在处理${}时,就是把${}替换成变量的值。 使用#{}可以有效的防止SQL注入,提高系统安全性。

5.Mybatis是如何进行分页的?分页插件的原理是什么?

1、Mybatis 使用 RowBounds 对象进行分页,也可以直接编写 sql 实现分页,也可以使用 Mybatis 的分页插件(MyBatis-PageHelper、MyBatis-Paginator、MyBatis-Plus等。)。

2、分页插件的原理:实现 Mybatis 提供的接口,实现自定义插件,在插件的拦截方法内拦 截待执行的 sql,然后重写 sql。

6. Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?

Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对 一,collection指的就是一对多查询。

在Mybatis配置文件中,可以配置是否启用延迟加载 lazyLoadingEnabled=true|false。 它的原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用 a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关 联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成 a.getB().getName()方法的调用。这就是延迟加载的基本原理。 当然了,不光是Mybatis,几乎所有的包括Hibernate,支持延迟加载的原理都是一样的。

7. Mybatis的一级、二级缓存:

1)一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认打开一级缓存。

2)二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于其存 储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启 二级缓存,使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),可在它的映射 文件中配置 ;

3)对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear。

8.MyBatis如何进行事务管理?

•MyBatis提供了两种事务管理方式:

•自动提交(AutoCommit):默认情况下,每个SQL语句执行完毕后都会自动提交事务。可以通过SqlSession的setAutoCommit(boolean autoCommit)方法改变此行为。

•手动管理:在业务代码中显式调用SqlSession的commit()和rollback()方法来控制事务的提交和回滚。

9.MyBatis动态SQL有什么应用场景?

•动态SQL主要用于处理条件查询时,SQL语句的动态生成。常见的应用场景包括:

        •if:根据条件包含或排除某部分SQL。

        •choose (when/otherwise):类似Java的switch-case结构,根据条件执行某一段SQL。

        •where:动态拼接WHERE子句,避免出现多余的AND或OR。

        •set:动态拼接UPDATE语句的SET子句。

        •foreach:遍历集合,生成IN查询或批量更新、删除语句。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值