SpringBean的常见面试题

什么是springbean?

由springioc容器管理的对象就是一个bean,是由ioc容器实例化,组装,管理的对象

javabean和springbean的区别?

所谓javaBean, 是指符合如下标准的Java类:
1.类是公共的
2.有一个无参的公共的构造器
3.有属性且有对应的get. set方法

配置bean有哪几种方式?

1.xml: <bean class=“com.tuling.UserService” id=>
2.注解: @Component(@Controller 、@Service、 @Repostory)反射调用构造方法//需要配置扫描包 context:annotation-config/
3.javaConfig: @Bean @Configuration可以自己控制实例化过程
4.@lmport

实例化bean有哪几种方式?

1.构造器方式(反射)–xml,@Component
2.静态工厂
3.实例工厂(@bean)
4.bean工厂

解释Spring支持的几种bean的作用域?

singleton : bean在每个Spring ioc容器中只有一个实例。

prototype: 一个bean的定义可以有多个实例

request: 每次http请求都会创建一个bean, 该作用域仅在基于web的Spring ApplicationContext情形下有效。

session:在一个HTTP Session中,一个bean定义对应一 个实例。 该作用域仅在基于web的Spring ApplicationContext情形下有效。

global-session: 在-一个全局的HTTP Session中, - -个bean定义对应-个实例。 该作用域仅在基于web的Spring ApplicationContext情形下有效。

单例bean的优势?

由于不会每次都新创建新对象所以有一下几个性能上的优势:
1.减少了新生成实例的消耗新生成实例消耗包括两方面,第一,spring会通过反射或者cglib来生成bean实例这都是耗性能的操作,其次给对象分配内存也会涉及复杂算法。

2.减少jvm垃圾回收由于不会给每个请求都新生成bean实例,所以自然回收的对象少了。

3.可以快速获取到bean因为单例的获取bean操作除了第一次生成之外其余的都是从缓存里获取的所以很快。

单例bean是线程安全的吗?

单例bean情况如果在类中声明成员变量,并且有读写操作(有状态)线程不安全但是只要把成员变量声明到方法中(无状态)单例bean就是安全的

如何处理线程并发问题?

1.设置为多例的

2.将成员变量放在threadlocal中

3.同步锁syn(变成串行了会影响吞吐量)

Spring是如何实现单例bean的?

Spring是通过单例注册表实现单例的,Ioc容器维护了一个bean表格,当需要一个单例bean时,从表格中获取,没有获取到的,向表格注册一个新的bean。

什么是bean的自动装配/注入?

无须在Spring配置文件中描述javaBean之间的依赖关系(如配置)。IOC容器会自动建立javabean之间的关联关系。

不同方式的自动装配 ?

1no:默认的方式是不进行自动装配,通过显式设置ref 属性来进行装配。
2. byName :通过参数名自动装配,Spring 容器在配置文件中发现 bean 的 autowire 属性被设置成 byname,之后容器试图匹配、装配和该bean的属性具有相同名字的bean。
3 .byType:通过参数类型自动装配,Spring容器在配置文件中发现bean的autowire属性被设置成byType,之后容器试图匹配、装配和该bean的属性具有相同类型的bean。如果有多个bean符合条件,则抛出错误。
4 .constructor:这个方式类似于 byType, 但是要提供给构造器参数,如果没有确定的带参数的构造器参数类型,将会抛出异常。
5.autodetect:首先尝试使用constructor来自动装配,如果无法工作,则使用byType方式。

bean的四种形态?

在这里插入图片描述

概念态–刚在标签里定义还没有加载
在new Applicationtext之后进入IOC的创建 进入定义态
定义态–把id,lazy,scop等定义信息传到BeanDefinition当中
再通过BeanFactory把定义态创建成纯净态
纯净态–完成创建但是没有注入属性信息(他是存在二级缓存中用来解决循环依赖)
成熟态–属性注入完成

Spring Bean 的生命周期?

Spring Bean 元信息配置阶段,可以通过面向资源(XML 或 Properties)、面向注解、面向 API 进行配置

Spring Bean 元信息解析阶段,对上一步的配置元信息进行解析,解析成 BeanDefinition 对象,该对象包含定义 Bean 的所有信息,用于实例化一个 Spring Bean

Spring Bean 元信息注册阶段,将 BeanDefinition 配置元信息 保存至 BeanDefinitionRegistry 的 ConcurrentHashMap 集合中

Spring BeanDefinition 合并阶段,定义的 Bean 可能存在层次性关系,则需要将它们进行合并,存在相同配置则覆盖父属性,最终生成一个 RootBeanDefinition 对象

Spring Bean 的实例化阶段,首先的通过类加载器加载出一个 Class 对象,通过这个 Class 对象的构造器创建一个实例对象,构造器注入在此处会完成。在实例化阶段 Spring 提供了实例化前后两个扩展点(InstantiationAwareBeanPostProcessor 的 postProcessBeforeInstantiation、postProcessAfterInstantiation 方法)

Spring Bean 属性赋值阶段,在 Spring 实例化后,需要对其相关属性进行赋值,注入依赖的对象。首先获取该对象所有属性与属性值的映射,可能已定义,也可能需要注入,在这里都会进行赋值(反射机制)。提示一下,依赖注入的实现通过 CommonAnnotationBeanPostProcessor(@Resource、@PostConstruct、@PreDestroy)和 AutowiredAnnotationBeanPostProcessor(@Autowired、@Value)两个处理器实现的。

Aware 接口回调阶段,如果 Spring Bean 是 Spring 提供的 Aware 接口类型(例如 BeanNameAware、ApplicationContextAware),这里会进行接口的回调,注入相关对象(例如 beanName、ApplicationContext)

Spring Bean 初始化阶段,这里会调用 Spring Bean 配置的初始化方法,执行顺序:@PostConstruct 标注方法、实现 InitializingBean 接口的 afterPropertiesSet() 方法、自定义初始化方法。在初始化阶段 Spring 提供了初始化前后两个扩展点(BeanPostProcessor 的 postProcessBeforeInitialization、postProcessAfterInitialization 方法)

Spring Bean 初始化完成阶段,在所有的 Bean(不是抽象、单例模式、不是懒加载方式)初始化后,Spring 会再次遍历所有初始化好的单例 Bean 对象,如果是 SmartInitializingSingleton 类型则调用其 afterSingletonsInstantiated() 方法,这里也属于 Spring 提供的一个扩展点

Spring Bean 销毁阶段,当 Spring 应用上下文关闭或者你主动销毁某个 Bean 时则进入 Spring Bean 的销毁阶段,执行顺序:@PreDestroy 注解的销毁动作、实现了 DisposableBean 接口的 Bean 的回调、destroy-method 自定义的销毁方法。这里也有一个销毁前阶段,也属于 Spring 提供的一个扩展点,@PreDestroy 就是基于这个实现的

Spring 垃圾收集(GC)

如何解决bean的循环依赖?

三级缓存
A首先完成了初始化的第一步,并且将自己提前曝光到singletonFactories中,此时进行初始化的第二步,发现自己依赖对象B,此时就尝试去get(B),发现B还没有被create,所以走create流程,B在初始化第一步的时候发现自己依赖了对象A,于是尝试get(A),尝试一级缓存singletonObjects(肯定没有,因为A还没初始化完全),尝试二级缓存earlySingletonObjects(也没有),尝试三级缓存singletonFactories,由于A通过ObjectFactory将自己提前曝光了,所以B能够通过
ObjectFactory.getObject拿到A对象(虽然A还没有初始化完全,但是总比没有好呀),B拿到A对象后顺利完成了初始化阶段1、2、3,完全初始化之后将自己放入到一级缓存singletonObjects中。此时返回A中,A此时能拿到B的对象顺利完成自己的初始化阶段2、3,最终A也完成了初始化,进去了一级缓存singletonObjects中,而且更加幸运的是,由于B拿到了A的对象引用,所以B现在hold住的A对象完成了初始化。
请添加图片描述

夺命连环问:

1.二级缓存能不能解决循环依赖?
a.如果只是死循环的问题: 一级缓存就可以解决:无法避免在并发下获取不完整的Bean?
b.二级缓存也可以解决循环依赖:只不过如果出现重复循环依赖 会多次创建aop的动态代理
2. Spring有没有解决多例Bean的循环依赖?
a.多例不会使用缓存进行存储(多例Bean每次使用都需要重新创建)
b.不缓存早期对象就无法解决循环
3. Spring有没有解决构造函数参数Bean的循环依赖?
a.构造函数的循环依赖也是会报错
b.可以通过@Lazy
i.就不会立即创建依赖的bean了
ii.而是等到用到才通过动态代理进行创建

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值