Spring Bean
热门问题
- 什么是 Spring Bean ?
- Bean 的作用域有几种?
- Bean 的生命周期?
- Bean 注入容器的方式?(非重点)
- 单例 Bean 是否有并发安全问题?
见招拆招
1、什么是 Spring Bean ?
所谓的 Bean 其实就是一个又一个放入 Spring 容器中被容器管理的 Java 对象,容器管理着它们的 **生命周期 **嘛,可以通过XML配置
、注解
以及配置类
进行 Bean 的声明,还可以指定 bean的作用域 什么的。
(这个问题就是个引子,目的还是后面那些问题,埋钩子)
2、Bean 的作用域有几种?
Spring 官方文档上是写了六
个,有singleton
、prototype
、request
、session
、application
、websocket
。平时开发中常用的就是singleton
和prototype
,singleton
是单例的,当 bean 中不进行数据共享是,singleton
无疑是最好的选择;如果 bean 中的状态需要进行读写,那么单例的Bean就有线程安全的问题,这个时候可以使用prototype
,其实我们更多时候不会选择这种方式,而是自己去new 对象
。
(这里不要没事找事儿,面试官问了,再答详细一点,这里也埋了一个线程安全的钩子)
- singleton:单例模式,容器中有且仅有一个 Bean,默认
- prototype:多实例,每次使用的时候都会创建一个新的实例,容器不管理其生命周期
- request:每一次的请求都会创建一个新的实例,仅在web应用中存在
- session:这个也是单例的,保存着与客户端的会话信息,每个会话有一个
- application:这个也是个单例的对象,仅在web应用中存在,代表当前应用的上下文对象
- websocket:一个 WebSocket 连接会话对应一个,仅在web应用中存在
3、Bean 的生命周期?
具体的过程还是比较复杂的,我这里说一下大体的一个过程吧:
首先肯定是实例化对象这个过程,然后进行属性的设置,也就是依赖注入嘛,这里需要注意的一点就是 Bean 的循环依赖 问题了。如果有写对应的初始化方法的话,还会去调用初始化方法,处理完成之后,这个 Bean 就可以被使用了。当 Bean 要被销毁的时候,就会调用destroy
方法进行一些后置处理工作。基本上就是这些了。
(上述是口语话回答)
(这幅图,理解并记忆)
实例化对象:Spring容器根据配置创建Bean实例
属性设置:Spring容器进行依赖注入,设置Bean的属性
初始化
如果Bean实现了InitializingBean接口,Spring会调用其afterPropertiesSet()方法。
如果在XML配置中指定了init-method属性,Spring会调用指定的初始化方法。
如果Bean使用了@PostConstruct注解,Spring会调用标注的方法。
使用:Bean处于就绪状态,可以被应用程序使用。
销毁
如果Bean实现了DisposableBean接口,Spring会调用其destroy()方法。
如果在XML配置中指定了destroy-method属性,Spring会调用指定的销毁方法。
如果Bean使用了@PreDestroy注解,Spring会调用标注的方法。
代码示例
@Component public class MyBean implements InitializingBean, DisposableBean { @PreDestroy public void cleanUp(){ System.out.println("谁先?"); } @Override public void destroy() throws Exception { System.out.println("销毁了嘛?"); } @PostConstruct public void init(){ System.out.println("看是我先,还是,afterPropertiesSet先"); } @Override public void afterPropertiesSet() throws Exception { System.out.println("要初始化完毕啦?"); } }
(很明显的,肯定是带注解的方法优先执行)
4、Bean 注入容器的方式?(非重点)
(送分题,被问到的概率应该不是很大,毕竟用过Spring的人都能回答出来)
- XML配置
- @Component注解及其衍生注解
- @Import,不常用,了解
5、单例 Bean 是否有并发安全问题?
从线程安全的角度来讲的话,单例对象确实是线程不安全的。但是 Spring 创建 Bean 的模式默认还是单例的,所以这个得分场景去看待这个所谓的线程安全问题。比如说被@Controller、@Service注解的Bean,它们身上的属性基本上都是本地使用,也就是给类中的方法使用,并不会去向外暴露。而一些公共的数据,比如一些常量、枚举什么的,我们也会单独的抽离出来,这些都是些只读的数据,我们不会对其进行修改嘛,所以不用考虑线程安全的问题。需要考虑线程安全问题的,是那些需要进行写操作的对象,比如说数据库表对应的实体类,当然,这些对象我们也不会交给Spring进行管理,而是自己去手动创建对象。以上就是我的一些理解。
(这才能体现自己的思考)
2025/01/03
writeBy kaiven