目录
Spring中的Bean的作用域
- singleton:唯一bean实例,Spring中的bean默认都是单例的。
- prototype:每次请求都会创建一个新的bean实例。
- request:每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP request内有效。
- session:每一次HTTP请求都会产生一个新的bean,该bean仅在当前HTTP session内有效。
Spring中 单例Bean的线程安全问题
大部分时候我们并没有在系统中使用多线程,所以很少有人会关注这个问题。单例bean存在线程问题,主要是因为当多个线程操作同一个对象的时候,对这个对象的非静态成员变量的写操作会存在线程安全问题。
有两种常见的解决方案:
- 1.在bean对象中尽量避免定义可变的成员变量(不太现实)。
- 2.在类中定义一个ThreadLocal成员变量,将需要的可变成员变量保存在ThreadLocal中(推荐的一种方式)。
Spring中的Bean生命周期
实例化–>属性赋值–>初始化–>销毁
- 实例化Bean。从Bean工厂中获取Bean,容器调用方法通过反射的方式创建出一个Bean对象进行实例化。
- 属性赋值。Bean创建好后对Bean进行属性填充,注入这个Bean依赖的其他bean对象。
- 初始化。首先判断是否执行Aware接口的方法,然后执行前置处理方法,判断是否实现了InitializingBean接口而调用afterPropertiesSet()方法,判断是否存在用户自定义的初始化方法,最后执行后置处理方法。
- 初始化完成。如果为singleon则Bean的对象会放入IOC的缓存池中,由Spring对Bean的生命周期管理,如果为prototype则将该Bean对象的生命周期交给调用者管理。
- 销毁,调用destroy()方法。
依赖注入
依赖注入(Dependency Injection,简称DI)是一种软件设计模式,用于实现对象之间的依赖关系。 在依赖注入中,一个对象的依赖关系不是在对象内部实现的,而是在容器外部实现的。换句话说,当一个对象需要其他对象的某些服务时,它不会自己创建所需要的对象,而是通过容器来注入所需要的对象。Spring Boot框架提供了依赖注入的实现,并且通过使用注解,可以非常方便地实现依赖注入。你可以通过使用@Autowired注解,来实现对象间的依赖关系,也可以通过配置文件,实现依赖关系。
循环依赖问题
循环依赖是指两个或多个Bean之间存在相互依赖的关系,导致容器无法初始化这些Bean。比如说,如果一个Bean A依赖于Bean B,同时Bean B也依赖于Bean A,那么就存在一个循环依赖的关系。 循环依赖是一个严重的问题,因为它会导致容器无法初始化,并且会抛出一个异常,因为。因此,在设计应用程序时,需要注意避免循环依赖。在实际开发中,一般通过设计模式、依赖注入等手段,来避免循环依赖的出现。
Spring中的设计模式
- 工厂模式:Spring使用工厂模式通过BeanFactory和ApplicationContext创建bean对象。
- 代理模式:Spring AOP功能的实现。
- 单例模式:Spring中Bean对象默认都是单例的。
- 包装器模式:项目需要连接多个数据库,不同的客户在每次访问中根据需要去访问不同的数据库。这种模式可以根据客户的需求能够动态切换不同的数据库。
- 观察者模式:Spring事件驱动模型就是观察者模式。
- 适配器模式:SpringAOP的增强或通知使用了适配器模式、SpringMVC中也使用适配器进行适配Controller。
@Component和@Bean的区别
- 作用对象不同。@Component注解作用于类,而@Bean注解作用于方法。
- @Component注解通常是通过类路径扫描来自动侦测以及自动装配到Spring容器中。@Bean注解通常是在标有该注解的方法中定义产生这个bean,告诉Spring这是某个类的实例。
- @Bean注解比@Component注解的自定义性更强,而且很多地方只能通过@Bean注解来注册bean。
Spring的事务管理
1.编程式事务:在代码中硬编码(不推荐使用)。
2.声明式事务:在配置文件中配置(推荐使用),分为基于XML的声明式事务和基于注解的声明式事务。
隔离级别:
ISOLATION_DEFAULT:使用后端数据库默认的隔离级别
ISOLATION_READ_UNCOMMITTED:最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
ISOLATION_READ_COMMITTED:允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生
ISOLATION_REPEATABLE_READ:对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
ISOLATION_SERIALIZABLE:最高的隔离级别,完全服从ACID的隔离级别。
Spring事务中的事务传播行为
- PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
- PROPAGATION_SUPPORTS: 如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
- PROPAGATION_MANDATORY: 如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。(mandatory:强制性)。
- PROPAGATION_REQUIRES_NEW: 创建一个新的事务,如果当前存在事务,则把当前事务挂起。
- PROPAGATION_NOT_SUPPORTED: 以非事务方式运行,如果当前存在事务,则把当前事务挂起。
- PROPAGATION_NEVER: 以非事务方式运行,如果当前存在事务,则抛出异常。
- PROPAGATION_NESTED: 如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于PROPAGATION_REQUIRED
SpringMVC
MVC是一种设计模式,SpringMVC是一款优秀的MVC框架,可以帮助我们进行方便的Web层的开发,并且与Spring集成。
Spring的工作原理
- 客户端发送请求后直接请求到DispatcherServlet
- DispatcherServlet根据请求信息调用HandlerMapping,解析请求对应的Handler(Controller处理器)
- 解析到对应的处理器后,HandlerAdapter会根据Handler来调用真正的处理器来处理请求和相关业务逻辑
- 处理完成后悔返回一个ModelAndView对象
- ViewResolver进行view的解析
- DispatcherServlet把返回的Mode进行视图渲染,并返回给客户端
Spring、SpringMVC、SpringBoot的区别
- Spring
- Spring最重要的特征就是依赖注入,所有的SpringModules不是依赖注入就是IOC控制反转,使用DI和IOC可以开发低耦合的应用。 针对于开发的WEB层(springMvc)、业务层(Ioc)、持久层(jdbcTemplate)等都提供了多种配置解决方案;
- SpringMVC
- springMvc是spring基础之上的一个MVC框架,主要处理web开发的路径映射和视图渲染,属于spring框架中WEB层开发的一部分;
- SpringBoot
- 更专注于开发微服务后台接口,不开发前端视图,同时遵循默认优于配置,简化了插件配置流程,不需要配置xml,相对springmvc,大大简化了配置流程;
SpringBoot自动配置的原理
在Spring程序main方法中,添加@SpringBootApplication或者@EnableAutoConfiguration会自动去maven中读取每个starter中的spring.factories文件,该文件里配置了所有需要被创建的Spring容器中的bean,然后将这些bean注册到IOC容器中进行管理。
SpringBoot的启动流程
- 加载配置文件: Spring Boot支持多种配置文件的方式,包括application.properties、application.yml、以及其他配置文件,例如通过命令行参数指定的配置文件。Spring Boot会读取配置文件中的内容,并将其加载到应用程序的环境变量中,以便在整个应用程序的生命周期内使用。
- 创建上下文: 创建上下文是整个应用程序的核心。在创建上下文的过程中,Spring Boot会初始化所有的Bean,并且按照它们的依赖关系进行实例化。上下文还负责管理整个应用程序的生命周期,并且提供了管理Bean的能力。
- 扫描包:在创建上下文之后,Spring Boot会扫描配置文件中指定的包,并且根据配置文件的信息加载相应的组件。例如,如果配置文件中指定了某个包是一个Spring组件扫描的起点,那么Spring Boot会扫描这个包以及这个包下的所有子包,并且加载所有的组件。
- 初始化Bean:在扫描包之后,Spring Boot会初始化所有的Bean。这一步骤包括解析Bean的依赖关系,并且按照依赖关系进行实例化。在初始化Bean的过程中,Spring Boot会调用每个Bean的生命周期回调方法,例如@PostConstruct或者InitializingBean接口的afterPropertiesSet()方法,这些方法可以用于完成Bean的初始化工作。
- 启动Tomcat:在初始化Bean的过程中,如果应用程序需要启动一个Web服务器,那么Spring Boot会自动启动一个内嵌的Tomcat服务器。在启动Tomcat的过程中,Spring Boot会加载所有的Servlet、Filter和Listener组件,并且启动Tomcat的HttpConnector,以便接受客户端的请求。
- 启动应用程序:在启动Tomcat的过程中,如果没有任何错误,那么Spring Boot就会启动应用程序,并且接受客户端的请求。在这个阶段,应用程序已经准备好提供服务了,并且可以开始处理客户端的请求。
SpringBoot的核心注解
启动类上面的注解是@SpringBootApplication,他也是SpringBoot的核心注解,主要组合包含了以下3个注解:
- @SpringBootConfiguration:组合了@Configuration注解,实现配置文件的功能;
- @EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项,如关闭数据源自动配置的功能:
- @SpringBootApplication(exclude={DataSourceAutoConfiguration.class});
- @ComponentScan:Spring组件扫描。
SpringBoot stater
SpringBoot中的starter是一种非常重要的机制(自动化配置),能够抛弃以前繁杂的配置,将其统一集成进starter,应用者只需要在maven中引入starter依赖,SpringBoot就能自动扫描到要加载的信息并启动相应的默认配置。starter让我们摆脱了各种依赖库的处理,需要配置各种信息的困扰。SpringBoot会自动通过classpath路径下的类发现需要的Bean,并注册进IOC容器。
SpringBoot实现异常处理
Spring提供了一种使用ControllerAdvice处理异常的非常有用的方法。通过实现一个ControlerAdvice类,来处理控制类抛出的所有异常。
Myabtis中#和$的区别是什么
$ {}是 Properties 文件中的变量占位符,它可以用于标签属性值和 sql 内部,属于静态文本替换,比如${driver}会被静态替换为com.mysql.jdbc. Driver。
#{}是 sql 的参数占位符,MyBatis 会将 sql 中的#{}替换为? 号,在 sql 执行前会使用 PreparedStatement 的参数设置方法,按序给 sql 的? 号占位符设置参数值,比如 ps.setInt(0, parameterValue),#{item.name} 的取值方式为使用反射从参数对象中获取 item 对象的 name 属性值,相当于 param.getItem().getName()。
DAO接口的方法重载
Mybatis 的 Dao 接口可以有多个重载方法,但是多个接口对应的映射必须只有一个,Mybatis 的 xml 里面的 ID 不允许重复,否则启动会报错。
Mybatis分页原理
(1) MyBatis 使用 RowBounds 对象进行分页,它是针对 ResultSet 结果集执行的内存分页,而非物理分页;
(2) 可以在 sql 内直接书写带有物理分页的参数来完成物理分页功能;
(3) 也可以使用分页插件来完成物理分页;
分页插件的基本原理是使用 MyBatis 提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的 sql,然后重写 sql,根据 dialect 方言,添加对应的物理分页语句和物理分页参数。