Spring常见问题
Spring常见问题
1.什么是Spring,对Spring的理解?
Spring是一个轻量级的,IOC和AOP的一站式框架,为简化企业级开发而生的.
Spring会管理对象,需要使用的时候直接注入即可,还可以对对象的功能进行增强,使得耦合度降低.
2.解释IOC和AOP
IOC (控制反转)将生成对象控制权反转给了Spring框架,主要用来管理对象的生命周期.
Spring bean对象:一般把Spring框架创建的对象称为bean对象.
AOP(面向切面编程) :首先是对面向对象的补充,使用动态代理的方式,为目标类中的方法进行功能上的增强,不需要修改源代码
Spring中使用xml配置和注解方式 实现.
3.Spring的不足
不足之处是诞生SpringBoot之后对比产生的.配置比较麻烦,且大多都是模板化配置,需要大量的jar依赖
SpringBoot对Spring搭建进行简化,并不是代替Spring
4.IOC和DI的区别是什么?
IOC(控制反转)—>强调Spring管理对象
DI(依赖注入)—>在创建对象的同时注入相关联的对象
5.Spring中注入对象的方式
使用xml方式配置
使用注解方式
6.自动注入有哪些注解
方式1:使用spring框架中提供@Autowired 可以添加到要注入的属性上面,或者属性的set方法上,如果直接添加到属性上,set方法可以不需要,默认情况下,要注入的属性对象不能为空(@Autowired=true) 注入时查找bean的方式有两种: 1.通过对象名查找,需要使用@qualifier(value=“admindao”)2.通过属性的类型查找
方式2:使用jdk中提供的注解@Resource 查询bean也是两种方式:1.@Resource 通过类型查询 2.@Resource(name=“admindao”) 通过对象名查询
7.spring中的bean和new的对象区别
Spring创建的对象可以进行相关对象的注入,可以进行功能的增强(事务,统一异常处理,日志)自己new的对象就是普通的一个对象,没有任何增强和注入的功能
8.AOP中的术语有哪些,通知有哪些
连接点 切入点 通知 代理 目标
前置通知 后置通知 返回通知 异常通知 环绕通知(可以事先前置,后置,返回,异常通知功能)
9.spring实现AOP有几种方式?
通过xml配置
动态代理:
jdk代理:通过反射机制实现,目标类必须要实现接口
Cglib代理:Spring中提供的代理实现方式,不要求实现接口
10.谈谈Spring事务管理,实现方式有几种,原理是什么?
事务管理属于数据库功能,spring(java)帮助我们进行事务管理(开启事务,提交事务,回滚事务)
实现方式:1.编程式事务 :通过在代码中使用事务管理对象手动提交,回滚事务
2.声明式事务:使用注解方式实现@Transactional(rollbackFor=Exception.class)
原理: aop–动态代理
11.声明式事务那些场景下会失效
1.@Transactional(rollbackFor=Exception.class)用在了非public方法上
2.异常被catch捕获,认为方法没有出现异常
3.默认出现编译期异常,可以在@Transactional(rollbackFor=Exception.class)设置回滚事务为Exception,即使出现编译期异常也会回滚
4.数据库引擎不支持事务,只有innodb支持
12.SpringWeb(SprngMVC)运行流程
当有请求时,会先访问dispatcherServelet ,拦截器会先检测是否拦截,若不拦截则在适配器中进行封装后进入处理器进行解析地址,作出响应后返回给dispatcherservelet.
13.spring和springboot的关系区别
springboot对spring搭建进行简化,并不是代替spring,为微服务架构做铺垫
14.SpringBean的生命周期
宏观上来讲,springBean的生命周期可以分为5个阶段:
- 实例化 Instantiation
- 属性赋值 Populate
- 初始化 Initialization
- 将bean对象放入到容器中,使用
- 销毁 Destruction
15.Spring常用注解
声明bean的注解
@RestController、@Service、@Repository都可以称为@Component
@Component:泛指各种组件
@RestController:控制层
@Service:业务层
@Repository:数据访问层
Bean的生命周期属性
@Scope设置类型包括:设置Spring容器如何新建Bean实例
singleton:单例,一个Spring容器中只有一个bean实例,默认模式
protetype:每次调用新建一个bean
request:web项目中,给每个http request新建一个bean
session:web项目中,给每个http session新建一个bean
globalSession:给每一个 global http session新建一个Bean实例
注入bean的注解
@Autowired:由Spring提供
@Qualifier:
当有多个同一类型的Bean时,可以用@Qualifier(“name”)来指定。与@Autowired配合使用.
@Resource:由java提供
切面(AOP)相关注解
Spring支持AspectJ的注解式切面编程
@Aspect:声明一个切面
@After:最终通知
@AfterReturning 后置通知
@Before:在方法执行之前执行
@Around:在方法执行之前与之后执行
@AfterThrowing 异常通知
SpringWEB常用注解
@RestController:该注解为一个组合注解,相当于@Controller和@ResponseBody的组合,注解在类上,意味着,该Controller的所有方法都默认加上了@ResponseBody。
@RequestMapping:用于映射web请求,包括访问路径和参数
@ResponseBody:支持将返回值放到response内,而不是一个页面,通常用户返回json数据
@RequestBody:允许request的参数在request体中,而不是在直接连接的地址后面
其他注解
@JsonFormat
此注解用于属性或者方法上(最好是属性上),可以方便的把Date类型直接转化为我们想要的模式.
@Transactional 注解放在类级别时,表示所有该类的公共方法都配置相同的事务属性信息。
SpringBoot注解
@SpringBootApplication:
包含@Configuration、@EnableAutoConfiguration、@ComponentScan通常用在主类上;
@RestControllerAdvice,@ExceptionHandler用于统一异常处理,捕获指定的异常.
配置类相关注解
@Configuration:声明当前类为配置类
@Bean:注解在方法上,声明当前方法的返回值为一个bean,替代xml中的方式
@ComponentScan:用于对Component类型注解进行扫描
Spring定时器
在启动类上添加 @EnableScheduling
在任务方法上添加 @Scheduled(cron = “*/6 * * * * ?”)
16.Spring 中的bean是线程安全的吗?
Spring容器中的Bean是否线程安全,容器本身并没有提供Bean的线程安全策略,因此可以说Spring容器中的Bean本身不具备线程安全的特性,但是具体还是要结合具体scope的Bean情况。
Spring 的 bean 作用域(scope)类型
1、singleton:单例,默认作用域。
2、prototype:原型,每次创建一个新对象。
3、request:请求,每次Http请求创建一个新对象,适用于
…
线程安全这个问题,要从单例Bean与原型Bean分别进行说明。
原型Bean:
对于原型Bean,每次创建一个新对象,也就是线程之间并不存在Bean共享,自然是不会有线程安全的问题。
单例Bean:
对于单例Bean,所有线程都共享一个单例实例Bean,因此是存在资源的竞争。
Bean又分为
有状态就是有数据存储功能(例如包含成员变量)
无状态就是不会保存数据
如果单例Bean,是一个无状态Bean,也就是线程中的操作不会对Bean的成员执行查询以外的操作,那么这个单例Bean是线程安全的。比如Spring mvc 的 Controller、Service、Dao等,这些Bean大多是无状态的,只关注于方法本身。
但是如果Bean是有状态的 那就需要开发人员自己来进行线程安全的保证,最简单的办法就是改变bean的作用域 把 "singleton"改为’‘protopyte’ 这样每次请求Bean就相当于是 new Bean() 这样就可以保证线程的安全了。
17.Bean循环依赖
Spring中相互依赖注入会产生问题
在Spring中,一个对象并不是简单new出来了,而是会经过一系列的Bean的生命周期,就是因为Bean的生命周期所以才会出现循环依赖问题。
在创建A类的bean对象时,需要经历创建对象,初始化,这时就需要给A类中B属性进行注入,但是此时B也需要注入A,这时就会陷入循环依赖问题.
产生循环依赖的问题,主要是:A创建时–>需要B----B去创建—>需要A,从而产生了循环。
Spring解决循环依赖问题:
过程解析:
1.初始化BeanA,需要注入BeanB,去查找BeanB,没有找到,把BeanA交给一个工厂对象,将BeanA工厂对象存入到三级缓存中.
2.去查找BeanB,BeanB不存在,也将BeanB交给一个工厂对象,将BeanB工厂对象也存入到三级缓存中.
3.由于BeanB需要BeanA,此时可以在第三级缓存中找到BeanA工对象,注入给BeanB,然后将BeanB放入到二级缓存,从三级缓存中删除BeanB工厂对象,注入到BeanB,完成BeanB的初始化,放入到一级缓存.
4.当BeanB完成初始化后,将完整的BeanB注入到BeanA中,完成BeanA的初始化.
spring内部有三级缓存:
在DefaultSingletonBeanRegistry类中定义了3个Map对象充当缓存.
singletonObjects: 一级缓存,用于保存实例化、注入、初始化完成的bean.实例
**earlySingletonObjects:**二级缓存,用于保存实例化完成的bean实例,提前曝露对象.
singletonFactories: 三级缓存,用于保存创建bean的工厂.
18.SpringBoot自动装配原理
.
spring内部有三级缓存:
在DefaultSingletonBeanRegistry类中定义了3个Map对象充当缓存.
singletonObjects: 一级缓存,用于保存实例化、注入、初始化完成的bean.实例
**earlySingletonObjects:**二级缓存,用于保存实例化完成的bean实例,提前曝露对象.
singletonFactories: 三级缓存,用于保存创建bean的工厂.
18.SpringBoot自动装配原理
springBoot启动时,首先对application.yml和pom.xml文件进行读取,获取到项目中使用到的第三方组件,然后读取spring.factories中的spring支持的配置类,最后加载项目中所使用到的组件配置类.