代码地址
spring02
觉得博主还可以给个Star
Spring Bean的生命周期
- 如何判断Bean初始化了
初始化:指的是对象已经创建并且里面所有的set已经全部执行完毕
在@Bean中有着initMethod,destoryMethod属性,他们代表着bean被初始化和销毁
具体用法:
UserEntity.java
package com.entity;
public class UserEntity {
public UserEntity(){
System.out.println("UserEntity无参构造...");
}
private void initMsg() {
System.out.println("UserEntity initMsg");
}
private void destroyMsg() {
System.out.println("UserEntity destroyMsg");
}
}
MyConfig.java
@Configuration
@ComponentScan("com.entity")
public class MyConfig {
@Bean(initMethod = "initMsg",destroyMethod = "destroyMsg")
public UserEntity userEntity(){
return new UserEntity();
}
}
Application.java
import com.config.MyConfig;
import com.entity.UserEntity;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Application {
public static void main(String[] args) {
// ApplicationContext
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
UserEntity userEntity = annotationConfigApplicationContext.getBean("userEntity", UserEntity.class);
}
}
运行结果:
我们会发现"UserEntity destroyMsg"并未被打印出来,那是因为容器并未被销毁,所以我们可以自己关闭容器,清除里面的bean
Application.java
import com.config.MyConfig;
import com.entity.UserEntity;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Application {
public static void main(String[] args) {
// ApplicationContext
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
UserEntity userEntity = annotationConfigApplicationContext.getBean("userEntity", UserEntity.class);
annotationConfigApplicationContext.close();
}
}
其实判断的方法还有很多种,比如
- 实现接口InitializingBean, DisposableBean
创建BookEntity.java
package com.entity;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor;
import org.springframework.stereotype.Component;
@Component
public class BookEntity implements InitializingBean, DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("BookEntity 销毁前执行");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("BookEntity实例化完成");
}
}
2. JSR250
创建PayEntity.java
package com.entity;
import org.springframework.stereotype.Component;
@Component
public class PayEntity {
@PreDestroy
public void destroy(){
System.out.println("BookEntity 销毁前执行");
}
@PostConstruct
public void afterPropertiesSet(){
System.out.println("BookEntity实例化完成");
}
}
弄清楚了怎么判断bean的初始化,我们先来看源码
try中倒数第二个方法
可以看到上面的注释,差不多意思为初始化所有的单例
初始化所有的单例,非懒加载
获取所有的beanName,并使用RootBeanDefinition注入
上面几步为查询对象是否有初始化过,没有的话就创建到IOC容器中
创建对象,判断对象如果是单例的情况下调用该方法
创建IOC对象
通过反射实例化bean
populateBean(beanName, mbd, instanceWrapper);方法是给对象set方法属性填充
initializeBean执行初始化方法(也可以自定义初始化方法)
判断bean的类型是否Aware相关依赖,如果存在则回调方法
好了,重点来了
- 如果 Bean 实现了 BeanNameAware 接口,则 Spring 调用 Bean 的 setBeanName() 方法传入当前 Bean 的 id 值。
- 如果 Bean 实现了 BeanFactoryAware 接口,则 Spring 调用 setBeanFactory() 方法传入当前工厂实例的引用。
- 如果 Bean 实现了 ApplicationContextAware 接口,则 Spring 调用 setApplicationContext() 方法传入当前 ApplicationContext 实例的引用。
第三点就完美解决了我们在过滤器当中,不能使用注解形式获取bean的问题,我们可以直接通过上下文获取bean。
好了,现在返回到
初始化方法之前执行处理(增强)
2调用自定义init方法(使用java反射技术,此方法在无参构造函数后执行)
3在初始化方法之后调用(增强)
我们会发现1和3他们有一个单词的差别,一个前一个后,也就是作用于自定义Init方法前后执行,在他们中间2也就是自定义Init方法
之后也就是调用,销毁了。然后我们也就总结出了,bean生命周期的周期图
语言描述:
Bean 生命周期的整个执行过程描述如下。
1)根据配置情况调用 Bean 构造方法或工厂方法实例化 Bean。
2)利用依赖注入完成 Bean 中所有属性值的配置注入。
3)如果 Bean 实现了 BeanNameAware 接口,则 Spring 调用 Bean 的 setBeanName() 方法传入当前 Bean 的 id 值。
4)如果 Bean 实现了 BeanFactoryAware 接口,则 Spring 调用 setBeanFactory() 方法传入当前工厂实例的引用。
5)如果 Bean 实现了 ApplicationContextAware 接口,则 Spring 调用 setApplicationContext() 方法传入当前 ApplicationContext 实例的引用。
6)如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的预初始化方法 postProcessBeforeInitialzation() 对 Bean 进行加工操作,此处非常重要,Spring 的 AOP 就是利用它实现的。
7)如果 Bean 实现了 InitializingBean 接口,则 Spring 将调用 afterPropertiesSet() 方法。
8)如果在配置文件中通过 init-method 属性指定了初始化方法,则调用该初始化方法。
9)如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的初始化方法 postProcessAfterInitialization()。此时,Bean 已经可以被应用系统使用了。
10)如果在 中指定了该 Bean 的作用范围为 scope=“singleton”,则将该 Bean 放入 Spring IoC 的缓存池中,将触发 Spring 对该 Bean 的生命周期管理;如果在 中指定了该 Bean 的作用范围为 scope=“prototype”,则将该 Bean 交给调用者,调用者管理该 Bean 的生命周期,Spring 不再管理该 Bean。
11)如果 Bean 实现了 DisposableBean 接口,则 Spring 会调用 destory() 方法将 Spring 中的 Bean 销毁;如果在配置文件中通过 destory-method 属性指定了 Bean 的销毁方法,则 Spring 将调用该方法对 Bean 进行销毁。
直至,还有一个重要的BeanPostProcessors,其实内部的重要方法我们已经见过
两个处理器,当然,它远远没有那么简单,后续揭晓