Java的各种各样的生命周期——思考历程
问题:
1.我需要了解到常见的生命周期,有Spring的Bean的生命周期,类的生命周期,对象的生命周期,线程的生命周期。
2.知道这些常见的生命周期有什么作用呢?
回答:
1类加载:
- 加载:通过类加载器(如
BootstrapClassLoader
)读取.class
文件到方法区,生成Class
对象。 - 连接
- 验证:检查字节码合法性(如文件格式、符号引用)。
- 准备:为静态变量分配内存并赋默认值(如
int
初始化为0
)。 - 解析:将符号引用转为直接引用(指向内存地址)。
- 初始化:执行静态代码块和静态变量赋值(生成
<clinit>()
方法)。 - 使用:实例化对象、调用方法等。
- 卸载:当类无实例、无
ClassLoader
引用且无Class
对象引用时,从方法区移除。
关键机制:双亲委派模型(避免重复加载核心类)
2.对象的生命周期
- 创建:通过
new
、反射或反序列化分配内存,初始化成员变量,执行构造函数。 - 使用:被强引用持有,程序可操作其字段和方法。
- 不可见:对象超出作用域(如局部变量失效),但可能仍被隐藏引用持有。
- 不可达:无任何 GC Roots 引用(如线程栈、静态变量),可被回收。
- 回收
- 标记:垃圾收集器(GC)识别不可达对象。
- 终结:若重写
finalize()
,则执行(不推荐,可能“复活”对象)。 - 内存释放:空间被回收或重用。
优化策略:分代回收(年轻代 Eden→Survivor→老年代)
3. 线程的生命周期
线程从创建到终止的状态流转:
- 新建:
new Thread()
后未调用start()
。 - 可运行:调用
start()
后,等待或占用 CPU 执行(包含就绪/运行中)。 - 阻塞:等待监视器锁(如
synchronized
竞争失败)。 - 等待:主动调用
Object.wait()
或Thread.join()
,需其他线程唤醒。 - 计时等待:带超时的等待(如
Thread.sleep(1000)
)。 - 终止:
run()
执行完毕或抛出未捕获异常。
4.Bean生命周期详细流程:(牛客给的)
-
实例化 Bean(Instantiation)
- Spring通过反射调用构造函数创建Bean实例。
- 如果是FactoryBean,则调用getObject()方法获取实际对象。
-
设置属性值(Population of Properties)
- 容器根据配置文件或注解将依赖注入到Bean中。
- 包括setter注入、构造器注入等。
-
设置Bean名称(BeanNameAware)
- 如果Bean实现了
BeanNameAware
接口,会调用setBeanName(String name)
方法,传入Bean的ID。
- 如果Bean实现了
-
设置Bean工厂(BeanFactoryAware)
- 如果Bean实现了
BeanFactoryAware
接口,会调用setBeanFactory(BeanFactory beanFactory)
方法。
- 如果Bean实现了
-
前置处理(BeanPostProcessor beforeInitialization)
- 所有BeanPostProcessor的
postProcessBeforeInitialization()
方法会被调用。
- 所有BeanPostProcessor的
-
初始化方法(Initialization)
- 如果Bean实现了
InitializingBean
接口,会调用afterPropertiesSet()
方法。 - 或者配置了
init-method
属性,会调用指定的方法。
- 如果Bean实现了
-
后置处理(BeanPostProcessor afterInitialization)
- 所有BeanPostProcessor的
postProcessAfterInitialization()
方法会被调用。
- 所有BeanPostProcessor的
-
使用 Bean
- Bean可以被应用程序正常使用。
-
销毁 Bean(Destruction)
- 容器关闭时:
- 如果Bean实现了
DisposableBean
接口,会调用destroy()
方法。 - 或者配置了
destroy-method
属性,会调用指定的方法。
- 如果Bean实现了
- 容器关闭时:
知道这些常见的生命周期有什么作用呢?
从我的角度而言,这有着普通八股一样的作用:1.增加理解,2.提高改BUG的能力,但这几个生命周期还有其他的一些作用,例如Spring 的bean的生命周期,这是框架的生命周期,对于我们去AOP增强,还有懒加载提速都有帮助
补充:
1.不同作用域的生命周期差异:
- Singleton:默认作用域,整个Spring上下文中唯一实例,容器启动时创建,容器关闭时销毁。
- Prototype:每次请求都会创建一个新的Bean实例,Spring不负责销毁该Bean。
- Request / Session / Application:适用于Web环境,生命周期分别绑定于HTTP请求、会话和ServletContext。
2.前置和后置处理是在干什么?
前置处理:
- 修改 Bean 属性:动态调整已注入的属性值(例如解密加密字段、填充默认值)
- 预校验或拦截:检查 Bean 的合法性(如必填字段非空校验),若校验失败可抛出异常阻止初始化。
- 注册监听器或事件:为 Bean 动态添加事件监听器(如
ApplicationListener
)。
后置处理:
生成动态代理
- AOP 的核心实现:通过后置处理将原始 Bean 替换为代理对象(如 JDK 动态代理或 CGLIB 代理),实现方法拦截。
- 包装或增强 Bean:为 Bean 添加额外功能(如缓存、监控、日志)。
if (bean instanceof ProductService) {
return new CachedProductService((ProductService) bean);
}