spring
什么是 spring,你对 spring 的理解?
是一个轻量级的,开源的,一站式的java开发框架,为简化企业级开发而生.
spring 的优缺点
优点: 轻量级,开源的,简单, IOC 和 AOP
缺点:配置麻烦,很多都是模板化配置, 管理很多依赖
解释一下 IOC 和 AOP
IOC--控制反转: 把项目中创建对象的权利反转给spring框架,由spring框架统一管理项目中的对象,
把由spring框架生成的对象,称为一个bean对象,spring可以对对象进行功能上的增强.
AOP--面向切面编程: 使用动态代理方式,为目标对象提供代理对象,在不修改目标类中的代码时,为目标类添加额外的功能,将额外的功能横切到目标类中.
IOC 和 DI 的区别是什么
IOC--控制反转
DI--Dependency Injection 依赖注入 在IOC的基础上,把对象注入到需要的地方
spring 中管理注入对象的方式
xml配置方式,注解方式
属性注入,构造方法注入
自动注入的注解有哪些注解
声明 bean 的注解
@RestController、@Service、@Repository 都可以称为@Component
@Component:基本组件
@RestController:控制层
@Service:业务层
@Repository:数据访问层
Bean 的生命周期属性
@Scope 设置类型包括:设置 Spring 容器如何新建 Bean 实例
singleton:单例,一个 Spring 容器中只有一个 bean 实例,默认模式
protetype:每次调用新建一个 bean
request:web 项目中,给每个 http request 新建一个 bean
注入 bean 的注解
@Autowired:由 Spring 提供
@Qualifier:
当有多个同一类型的 Bean 时,可以用@Qualifier(“name”)来指定。与
@Autowired 配合使用.
@Resource:由 java 提供
Spring 中的 bean 和 new 的对象有什么区别
bean对象是由spring框架创建的,根据我们的配置(事务,日志,统一异常处理),可以进行功能上的增强
自己new的对象就是最原始的对象,没有任何功能增强
AOP 中的术语有哪些,通知有哪些
连接点: 类中可以被增强的方法
切入点: 类中实际被增强的方法
通知: 给切入点添加的功能
目标: 被增强的类
代理: 代理对象
通知类型
前置通知 :在方法执行之前执行.
后置通知: 在方法执行后执行,即使出现异常也会执行.
返回通知:在方法执行后执行,一旦出现异常就不执行了.
异常通知:在出现异常时执行.
环绕通知: 可以实现,前置,后置,返回,异常通知
Spring 实现 AOP 有哪几种方式
xml配置方式
注解方式
谈谈 Spring 事务管理,实现方式有几种,原理是什么?
事务是数据库的特性,spring事务管理,只是spring框架对事务开启,提交,回滚进行管理
编程式事务: 需要在代码中自己提交,回滚.
声明式事务: 在类,方法上声明即可 使用@Transactional(rollbackFor = Exception.class)
使用动态代理对象
声明式事务哪些场景下会失效
声明式事务失效场景: 1.@Transactional用在非public方法上 2.方法中的异常被捕获了,认为方法没有异常 3.方法中出现编译期异常,还是会提交事务 可以将rollbackFor = Exception.class这样所有的异常都会回滚 4.数据库引擎不支持事务 mysql中只有innodb引擎支持事务的.
SpringWEB(springMVC)运行流程
Servlet 的过滤器与 Spring 拦截器区别
过滤器属于servlet规范中定义的,拦截器是spring中定义的
过滤器可以拦截所有进入到java后端的请求, 拦截器只能拦截进入到处理器(Controller web层)的请求
spring 和 springboot 关系
springboot是对spring框架的搭建进行封装,简化了搭建过程,不是代替spring的,底层依然还是spring.
Spring 常用注解
参考文档
SpringBean 的生命周期
IOC java中的对象由spring框架管理的
宏观上来讲,springBean 的生命周期可以分为 5 个阶段:
实例化 Instantiation
属性赋值 Populate (依赖注入)
初始化 Initialization (最关键的 根据我们各种的注解配置,在这一步进行落地实现)
将 bean 对象放入到容器中,使用
销毁 Destruction
Spring 中的 bean 是线程安全的吗?
spring中的bean如果是单例,始终只创建了一个对象,所有请求共用同一个对象,(Spring默认是单例bean)
那么对该单例对象中的成员变量也就只有一份,所有请求共享.
在多用户访问时,可能出现问题, 还有种情况,就是想每个请求中,都用于一个属于自己的成员变量使用.
所以单例bean使用时,就有可能存在线程安全问题
@RestController @RequestMapping(value = "/testctl") @scope(value = "singleton") //范围是单例的 public class TestController { private int var = 0; //单例bean,成员变量也就只有一个,所有的请求共享 }
原型bean每次请求都会创建新的对象,不会存在线程安全问题
单例bean线程安全问题解决:
如果成员变量是共享的,多线程(请求)操作时,如++等操作,进行加锁的控制. 如果每个请求中,都需要一个属于自己的成员变量: 1.把单例bean改成原型bean.
2.使用ThreadLoacl为每次请求提供变量副本
ThreadLocal<Integer> threadLocal = new ThreadLocal<>(){ @Override protected Integer initialValue() { return 1; } };
单例bean又分为:
有状态bean, 就是有成员变量,而且成员变量可以存储数据,就有可能多线程操作出问题.
无状态bean @Autowired OrderService orderService; 注入的这种对象,不用于存储数据,只是调方法,每次请求中的参数数据都是相互隔离的
Bean 循环依赖
什么是循环依赖问题
class A{ @Autowired B b; } class B{ @Autowired A a; } public static void main(String[] args) { A a = new A(); //创建A对象时,关联对象b为null B b = new B(); //创建B对象时,关联对象a为null } 虽然A,B之间相互关联,但是创建对象时没有任何问题.
但是在spring中会存在循环依赖问题(spring已经解决了此问题)
在spring中如果使用@Autowired注解,那么在创建A对象时,需要为关联的b对象注入值, 需要去创建对象b,创建对象b时,需要为关联的a注入值,但是此时a还没创建完成, 形成死循环.
spring中如何解决循环依赖问题
spring中使用三级缓存来解决循环依赖问题
三级缓存其实就是三个map对象,来存储不同的对象.
一级缓存: singletonObjects 一级缓存对象,主要存储创建,初始化完成的bean对象.
二级缓存:earlySingletonObjects 主要存储实例化完成,单还未初始化完成的半成品对象
三级缓存:singletonFactories 主要存储创建对象的工厂对象 . 创建a时,还有一个创建a的工厂对象
过程
创建A时,需要用到B, A创建了一半,把它存放到二级缓存中,把创建A工厂放到三级缓存中,把半成品A注入到B中,B完成了创建,把B放到了一级缓存中, 把B注入到A中, A对象完成了创建.
SpringBoot 自动装配原理
从启动类说起
@SpringBootApplication 是springboot中最核心的注解 @MapperScan("com.ffyc.aiserver.dao") public class AiserverApplication { public static void main(String[] args) { //加载启动类 SpringApplication.run(AiserverApplication.class, args); } } @SpringBootApplication 注解标签,里面包含了三个注解标签 @SpringBootConfiguration @EnableAutoConfiguration 自动配置 @ComponentScan( 扫描启动类所在的包下的类 excludeFilters = {@Filter( type = FilterType.CUSTOM, classes = {TypeExcludeFilter.class} ), @Filter( type = FilterType.CUSTOM, classes = {AutoConfigurationExcludeFilter.class} )} ) @EnableAutoConfiguration 自动配置 @Import({AutoConfigurationImportSelector.class}) 根据pom.xml中配置的相关依赖,进行选择性的加载,读取相关依赖的配置类.
MyBatis-Plus
mybatis自动进行结果映射,尤其是单张表. select id,name from user where id = 1
单表操作不想写sql,让框架直接自动生成sql, 把类和表对应起来, 把类中属性和表中列对应起来
save(user) --> insert into user(id,name)value(1,'jim')
delete(id) -->delete from user where id = 1
User select(id); --->select id,name from user where id = 1
List<User> selects(条件);
update(User)-->update uset set name='tom' where id = 1
hibernate 数据量大,自动生成sql,自动数据封装, 效率低 淘汰