java面试题(持续更新)
Spring
1.spring的Bean是否线程安全?
答案:spring的Bean是否线程安全,跟spring容器本身无关。
spring容器只提供线程安全的策略
一般在手动定义bean的时候,会定义三项,bean的ID,作用域Scope(单例,多例),和是否延时加载(lazy-init)
而作用域中的多例是每次new新的bean出来,不会有线程安全问题
单例中的bean分文有状态的Bean和无状态的Bean,有状态的就是不能被修改的,无状态的就是可以被修改的。
以上分析,Bean在单例的有状态下被修改,会产生线程安全问题。
处理方案三种:1.把scope的singleton改成prototype;2.把避免定义可变的Bean 3.在类中定义threadLocal的变量,把Bean做线程隔离,即每个线程有一个线程副本。
2.spring中的Bean的Id是否可以重复?
答案:在spring的XML同一个配置文件中,Bean的Id是不能重复的,重复会报错。程序在启动中解析spring的xml文件,并根据bean的id生成BeanDefinition会报错。
但是在不同的XML配置文件中有重复bean,后一个会覆盖前一个,不会报错。
但是在spring3.x以后用@Configiration和@Bean注解代替了XML以后,如果发生BeanId相同的情况,会取第一个加载的Bean,并且在AutoWaird和Resource只能取到第一个加载的Bean对象。
3.Spring如何解决循环依赖问题?
答案:首先循环依赖有三种情况,互相依赖,间接依赖,自我依赖(如图),
Spring解决循环依赖使用三级缓存,一级:存储完整的Bean实例,并且可以直接使用,二级:创建当前bean,但是没创建属性值的Bean 三级:存放bean工厂,Function的lanmda表达式,生成原始Bean对象放到二级缓存。
核心:Bean的实例化和Bean的依赖注入分离开,一级缓存存放完整Bean,二级缓存存放不完整的Bean,通过不完整的Bean做突破口,解决循环依赖问题。三级缓存,解决代理对象的循环注入问题