1. **Spring框架中的单例bean线程安全问题**:
- 单例bean本身不是线程安全的,当多线程并发执行对单例状态有修改的业务逻辑时,需要考虑线程同步问题。
- Spring框架未对单例bean进行多线程封装处理,若bean为不可变状态(如Service类和DAO类),在某种程度上是线程安全的;
若bean有多种状态(如View Model对象),则需要自行保证线程安全,可将其作用由“singleton”变更为“prototype”。
2. **AOP(面向切面编程)**:
- 定义:将与业务无关但对多个对象产生影响的公共行为和逻辑抽取出来复用,降低耦合,可用于公共日志保存、事务处理等。
- 项目应用:在后台管理系统中使用AOP记录系统操作日志,通过环绕通知+切点表达式找到要记录日志的方法,获取请求方法的参数(类信息、方法信息、注解、请求方式等)并保存到数据库。
3. **Spring中的事务实现**:
- 本质:通过AOP对方法前后进行拦截,在执行方法之前开启事务,执行完后根据情况提交或回滚事务。
4. **Spring中事务失效的场景**:
- 方法上异常捕获处理后自行处理异常且未抛出,会导致事务失效,处理异常后应抛出。
- 方法抛出检查异常且在@Transactional注解上未配置rollbackFor属性为Exception时,事务失效,应配置该属性使无论何种异常都回滚事务。
- 方法上不是public修饰时,事务失效。
5. **Spring的bean的生命周期**:
- 通过BeanDefinition获取bean的定义信息,包括类的全路径、是否延迟加载、是否单例等。
- 创建bean时,步骤如下:
- 调用构造函数实例化bean。
- 进行bean的依赖注入(如@Autowire)。
- 处理Aware接口(若bean实现了该接口则重写方法执行)。
- 执行bean的前置处理器BeanPostProcessor。
- 执行初始化方法(如实现InitializingBean接口或自定义init - method标签或@PostContruct)。
- 执行bean的后置处理器BeanPostProcessor(可能产生代理对象)。
- 销毁bean。
6. **Spring中的循环引用**:
- 定义:循环依赖即循环引用,指两个或以上的bean互相持有对方,形成闭环,如A依赖于B,B依赖于A。
- Spring框架依据三级缓存解决大部分循环依赖:
- 一级缓存:单例池,缓存已完成生命周期、初始化完成的bean对象。
- 二级缓存:缓存早期的bean对象(生命周期未走完)。
- 三级缓存:缓存ObjectFactory,用于创建某个对象。
- 具体解决流程:
- 先实例化A对象,同时创建ObjectFactory对象存入三级缓存singletonFactories。
- A初始化时需要B对象,走B的创建逻辑。
- B实例化完成,也创建ObjectFactory对象存入三级缓存singletonFactories。
- B需要注入A时,通过三级缓存中获取ObjectFactory来生成A的对象并存入二级缓存,可能是A的普通对象或代理对象,由ObjectFactory生产。
- B从二级缓存earlySingletonObjects获取到A的对象后正常注入,B创建成功存入一级缓存singletonObjects。
- A初始化时因B对象已创建完成可直接注入,A创建成功存入一级缓存singletonObjects。
- 二级缓存中的临时对象A清除。
7. **构造方法出现循环依赖的解决方法**:
- Spring框架不能解决构造函数的依赖注入,可使用@Lazy懒加载,在需要对象时再创建bean对象。
8. **SpringMVC的执行流程**:
- 用户发送请求到前端控制器DispatcherServlet。
- DispatcherServlet收到请求调用HandlerMapping(处理器映射器)。
- HandlerMapping找到具体的处理器(可查找xml配置或注解配置),生成处理器对象及处理器拦截器(如果有),返回给DispatcherServlet。 - DispatcherServlet调用HandlerAdapter(处理器适配器)。
- HandlerAdapter经过适配调用具体的处理器(Handler/Controller)。
- Controller执行完成返回ModelAndView对象。
- HandlerAdapter将Controller执行结果ModelAndView返回给DispatcherServlet。
- DispatcherServlet将ModelAndView传给ViewReslover(视图解析器)。
- ViewReslover解析后返回具体View(视图)。
- DispatcherServlet根据View进行渲染视图(将模型数据填充至视图中)。
- DispatcherServlet响应用户。
- 前后端分离开发中,一般在handler中使用Response直接返回结果,无视图相关操作。
9. **Springboot自动配置原理**:
- Spring Boot项目引导类上的@SpringBootApplication注解封装了@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan三个注解。
- @EnableAutoConfiguration注解通过@Import注解导入对应的配置选择器,关键是读取项目和引用Jar包的classpath路径下META-INF/spring.factories文件中配置类的全类名。
- 配置类中定义的Bean根据条件注解(如@ConditionalOnClass)指定的条件决定是否导入到Spring容器中。
10. **Spring的常见注解**:
- 声明bean:@Component、@Service、@Repository、@Controller。
- 依赖注入相关:@Autowired、@Qualifier、@Resourse。
- 设置作用域:@Scope。
- spring配置相关:@Configuration、@ComponentScan、@Bean。
- 跟aop相关做增强:@Aspect、@Before、@After、@Around、@Pointcut。
11. **SpringMVC常见的注解**:
- @RequestMapping:用于映射请求路径。
- @RequestBody:注解实现接收http请求的json数据,将json转换为java对象。
- @RequestParam:指定请求参数的名称。
- @PathViriable:从请求路径下中获取请求参数(/user/{id}),传递给方法的形式参数。
- @ResponseBody:注解实现将controller方法返回对象转化为json对象响应给客户端。
- @RequestHeader:获取指定的请求头数据。 - @PostMapping、@GetMapping等。
12. **Springboot常见注解**:
- @SpringBootApplication:由@SpringBootConfiguration(组合了@Configuration注解,实现配置文件功能)、@EnableAutoConfiguration(打开自动配置功能,可关闭某个自动配置选项)、@ComponentScan(Spring组件扫描)组成。
13. **MyBatis执行流程**:
- 读取MyBatis配置文件(mybatis - config.xml)加载运行环境和映射文件。
- 构造会话工厂SqlSessionFactory(一个项目只需要一个,单例的,一般由spring进行管理)。
- 会话工厂创建SqlSession对象,包含执行SQL语句的所有方法。
- 操作数据库的接口Executor执行器,同时负责查询缓存的维护。
- Executor接口的执行方法中有一个MappedStatement类型的参数,封装了映射信息。
- 输入参数映射。
- 输出结果映射。
14. **Mybatis是否支持延迟加载**:
- 支持,延迟加载是在需要用到数据时才进行加载,不需要时不加载数据,Mybatis支持一对一关联对象和一对多关联集合对象的延迟加载。
- 在Mybatis配置文件中,可配置是否启用延迟加载(lazyLoadingEnabled = true | false,默认关闭)。
15. **延迟加载的底层原理**:
- 主要使用CGLIB动态代理完成。
- 使用CGLIB创建目标对象(开启了延迟加载的mapper)的代理对象。
- 当调用目标方法时,进入拦截器invoke方法,发现目标方法是null值,再执行sql查询。
- 获取数据以后,调用set方法设置属性值,再继续查询目标方法,就有值了。
16. **Mybatis的一级、二级缓存**:
- 一级缓存:基于PerpetualCache的HashMap本地缓存,存储作用域为Session,当Session进行flush或close之后,该Session中的所有Cache将清空,默认打开一级缓存。
- 二级缓存:需要单独开启,基于namespace和mapper的作用域起作用,不依赖于SQL session,默认采用PerpetualCache,HashMap存储。若要开启二级缓存,需要在全局配置文件和映射文件中进行配置。
17. **Mybatis的二级缓存什么时候会清理缓存中的数据**:
- 当某一个作用域(一级缓存Session/二级缓存Namespaces)进行了新增、修改、删除操作后,默认该作用域下所有select中的缓存将被clear。