Spring框架相关问题
- 一、Spring容器中的Bean是线程安全的吗?
- 二、如何保证Spring容器中的Bean是线程安全的呢?
- 三、什么情况下会触发Spring事务回滚?
- 四、如果事务方法抛出IOException,是否会触发Spring事务回滚?
- 五、什么情况下Spring事务会失效呢?
- 六、对Spring框架Bean的生命周期有了解过吗?
一、Spring容器中的Bean是线程安全的吗?
答案:不是线程安全的;
- Spring容器中的
Bean
默认是singleton
单例的,所有线程都共享一个单例Bean,因此是存在资源竞争的; - 但在实际开发中,单例 Bean 一般都以无状态的方式来使用,即线程之间的操作不会对 Bean 的成员执行除查询以外的操作,所以这个单例 Bean 又可以说是线程安全的。比如:Controller、Service、Dao等这些Bean大多数是无状态的,我们不会对这些Bean中的属性
进行修改操作,只需要关注方法本身即可;
二、如何保证Spring容器中的Bean是线程安全的呢?
1、把默认的 singleton
单例的 Bean 的改为 prototype
多例的Bean; 添加注解:@Scope("prototype")
2、在 Bean 对象中避免定义可变的成员变量;
3、如果 Bean 对象中需要定义可变成员变量,将可变成员变量保存在 ThreadLocal
中;
private ThreadLocal<Integer> numberThreadLocal = ThreadLocal.withInitial(() -> {
return 0;
});
三、什么情况下会触发Spring事务回滚?
当执行发生异常的时候,触发Spring事务回滚。
@Transactional(rollbackFor = Exception.class)
四、如果事务方法抛出IOException,是否会触发Spring事务回滚?
如果采用Spring默认的事务回滚规则,它默认是发生RuntimeException
异常时触发事务回滚,而现在是发抛出IOException
异常,那不会触发Spring事务回滚;
如果想触发IOException
异常事务回滚,需要指定回滚的规则;
@Transactional(rollbackFor = IOException.class)
五、什么情况下Spring事务会失效呢?
- 考察对Spring的事务管理理解是否深刻;
- 先举几个示例,进行分析,然后再总结答案;
1、同一个Service中,方法A 标注事务注解,则方法B 没有标注事务注解;
2、同一个Service中,没有标注事务注解的B方法调用标注了事务注解的A方法;事务失效
3、不同的Service中,没有标注事务注解的B方法调用标注了事务注解的A方法;事务不失效
4、标注了事务注解的public方法、protected方法、默认无修饰方法、private方法,final方法,static方法;只有Public方法事务生效;
5、多线程中的事务;事务失效
事务失效情况:
1、异常类型错误;IOException类型
2、方法或类上没有标注@Transactional注解;
3、同一类中,方法内部自调用;
4、事务方法不是public的;
5、多线程调用;
6、异常被try … catch
7、手动抛了别的异常 IOException
8、事务方法所在的Bean未被 Spring 容器管理
9、方法的事务传播类型不支持事务
10、表的数据库引擎不支持事务,比如MyISAM存储引擎不支持事务;
六、对Spring框架Bean的生命周期有了解过吗?
1、解析 xml 配置或者注解的类,得到 BeanDefinition
;
2、通过 BeanDefinition
反射创建 Bean
对象(实例化 Bean 对象)。
3、对 Bean
对象进行属性填充
4、回调实现 Aware 接口的方法,比如 BeanNameAware
5、调用BeanPostProcessor
的初始化前方法;
6、调用init
初始化方法(如果有的话);
7、调用BeanPostProcessor
的初始化后方法,此处会进行 AOP;
8、将创建好的 Bean 对象放入一个 Map 中;
9、业务中使用 Bean 对象就从 Map 中获取;
10、Spring 容器关闭时调用 DisposableBean
的 destory
方法销毁 Bean 对象;