Springbean的生命周期一直是面试高频题,想答好,还得看源码
bean的生命周期,从源码角度来说,值得我们关注的主要有四个大点,穿插在bean的创建过程中,所以显得散乱:
实例化对应构造方法,
属性赋值对应setter方法的注入,
初始化和销毁是用户能自定义扩展的两个阶段,如我们可以指定初始化方法和销毁方法,这部分之前的文章有分析过。
对应的执行顺序为:
实例化->属性赋值->初始化->销毁
我们先来看实例化:
这里简单的提下注入bean的几种方式:
XML配置的方式:
1.构造器的方式:通过默认构造器创建 空构造方法必须存在 否则创建失败
<!--通过默认的无参构造函数创建-->
<bean id="car1" class="com.cjian.bean.Car"/>
2.静态工厂方式:我们指定Spring使用静态工厂方法来创建Bean实例时,Spring将先解析配置文件,并根据配置文件指定的信息,**通过反射调用静态工厂类的静态工厂方法,并将该静态工厂方法的返回值作为Bean实例,在这个过程中,Spring不再负责创建Bean实例,Bean实例是由用户提供的静态工厂方法提供的
<!--通过静态工厂创建-->
<bean id="car2" class="com.cjian.beanfactory.BeanFactory" factory-method="getCar1"/>
public class BeanFactory {
//静态工厂
public static Car getCar1(){
return new Car();
}
}
3.实例化工厂方式:
<!--通过工厂实例创建-->
<bean id="carBeanFactory" class="com.cjian.beanfactory.BeanFactory"/>
<bean id="car3" factory-bean="carBeanFactory" factory-method="getCar2"/>
public class BeanFactory {
public Car getCar2(){
return new Car();
}
}
4.通过FactoryBean:需要将该实例注入到容器中
<!--通过FactoryBean-->
<bean id="car4" class="com.cjian.beanfactory.CarFactoryBean"/>
package com.cjian.beanfactory;
import com.cjian.bean.Car;
import org.springframework.beans.factory.FactoryBean;
/**
* @description:
* @author: CJ
* @time: 2021/1/7 15:19
*/
public class CarFactoryBean implements FactoryBean<Car> {
@Override
public Car getObject() throws Exception {
return new Car();
}
@Override
public Class<?> getObjectType() {
return null;
}
@Override
public boolean isSingleton() {
return true;
}
}
2.通过注解的方式:
注解的方式也有很多种:
如@Bean @Import (直接导入bean,实现ImportSelector接口,并通过@Import导入 实现ImportBeanDefinitionRegistrar接口,并通过@Import导入)
接下来我们来看下实例化的具体过程:
不管是注解方式还是xml配置方式,ioc容器的初始化都是从调用refresh()方法开始:
abstractApplicationContext.refresh():
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
this();
this.register(componentClasses);
this.refresh();
}
beanFactory.preInstantiateSingletons();
public void refresh() throws BeansException, IllegalStateException {
synchronized(this.startupShutdownMonitor) {
this.prepareRefresh();
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
this.postProcessBeanFactory(beanFactory);
this.invokeBeanFactoryPostProcessors(beanFactory);
this.registerBeanPostProcessors(beanFactory);
this.initMessageSource();
this.initApplicationEventMulticaster();
this.onRefresh();
this.registerListeners();
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
} catch (BeansException var9) {
if (this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}
this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}
}
}
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
if (beanFactory.containsBean("conversionService") && beanFactory.isTypeMatch("conversionService", ConversionService.class)) {
beanFactory.setConversionService((ConversionService)beanFactory.getBean("conversionService", ConversionService.class));
}
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver((strVal) -> {
return this.getEnvironment().resolvePlaceholders(strVal);
});
}
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
String[] var3 = weaverAwareNames;
int var4 = weaverAwareNames.length;
for(int var5 = 0; var5 < var4; ++var5) {
String weaverAwareName = var3[var5];
this.getBean(weaverAwareName);
}
beanFactory.setTempClassLoader((ClassLoader)null);
beanFactory.freezeConfiguration();
beanFactory.preInstantiateSingletons();
}
在这里面会调用到beanFactory的getBean()方法->doGetBean():
这里也开始了bean的创建:
请看源码:
protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
//对 name 进行转换,获取真正的 beanName
String beanName = this.transformedBeanName(name);
//从缓存中获取 bean 的实例(已经注册过的单例bean 都保存在 singletonObjects 中)
//这里还有循环依赖的知识点,以后再说
Object sharedInstance = this.getSingleton(beanName);
Object bean;
if (sharedInstance != null && args == null) {
//...
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, (RootBeanDefinition)null);
} else {
//如果是多实例的且bean正在创建,直接抛异常,这也是循环依赖无法解决的问题
if (this.isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 1. 在 parentBeanFactory 中如果存在 beanName,则直接返回父容器里面的 bean
BeanFactory parentBeanFactory = this.getParentBeanFactory();
if (parentBeanFactory != null && !this.containsBeanDefinition(beanName)) {
String nameToLookup = this.originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory)parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
}
if (args != null) {
return parentBeanFactory.getBean(nameToLookup, args);
}
if (requiredType != null) {
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
return parentBeanFactory.getBean(nameToLookup);
}
if (!typeCheckOnly) {
this.markBeanAsCreated(beanName);
}
try {
RootBeanDefinition mbd = this.getMergedLocalBeanDefinition(beanName);
this.checkMergedBeanDefinition(mbd, beanName, args);
// 2. 初始化当前 bean 依赖的 bean
String[] dependsOn = mbd.getDependsOn();
String[] var11;
if (dependsOn != null) {
var11 = dependsOn;
int var12 = dependsOn.length;
for(int var13 = 0; var13 < var12; ++var13) {
String dep = var11[var13];
if (this.isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
this.registerDependentBean(dep, beanName);
try {
// getBean() 会再递归调用 doGetBean(),以确保所依赖的 bean 全部初始化
this.getBean(dep);
} catch (NoSuchBeanDefinitionException var24) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "'" + beanName + "' depends on missing bean '" + dep + "'", var24);
}
}
}
if (mbd.isSingleton()) {
// 3. 创建 单实例bean
sharedInstance = this.getSingleton(beanName, () -> {
try {
return this.createBean(beanName, mbd, args);
} catch (BeansException var5) {
this.destroySingleton(beanName);
throw var5;
}
});
//如果bean为 FactoryBean的话,则调用FactoryBean.getObject() 来创建 bean 实例
bean = this.getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
//多实例bean
var11 = null;
Object prototypeInstance;
try {
this.beforePrototypeCreation(beanName);
prototypeInstance = this.createBean(beanName, mbd, args);
} finally {
this.afterPrototypeCreation(beanName);
}
bean = this.getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} else {
// 其他 scope 类型的 bean
String scopeName = mbd.getScope();
if (!StringUtils.hasLength(scopeName)) {
throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
}
Scope scope = (Scope)this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, () -> {
this.beforePrototypeCreation(beanName);
Object var4;
try {
var4 = this.createBean(beanName, mbd, args);
} finally {
this.afterPrototypeCreation(beanName);
}
return var4;
});
bean = this.getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
} catch (IllegalStateException var23) {
throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton", var23);
}
}
} catch (BeansException var26) {
this.cleanupAfterBeanCreationFailure(beanName);
throw var26;
}
}
//...
}
再来看 createBean()
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
RootBeanDefinition mbdToUse = mbd;
......
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
// 在实例化之前返回一个代理对象,BeanPostProcessor 可以创建一个代理 bean 返回(AOP的功能)
// 执行 InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation -- bean 实例化前置处理
// 执行 InstantiationAwareBeanPostProcessor.postProcessAfterInitialization -- bean 初始化后置处理
//重点--这里以后单独分析
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
// 创建 bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
doCreateBean():
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (instanceWrapper == null) {
// 创建 bean 的实例:通过默认构造函数反射生成、通过配置的构造函数生成(构造方法注入)、通过 factoryMethod 生成
// 最终会生成一个 BeanWrapper
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
// Allow post-processors to modify the merged bean definition.
// 允许 post-processors 修改 bean 的定义
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
// 执行 MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
// 解决循环依赖相关
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 填充 bean 属性,处理属性注入:@Value, @Autowired, @Resource 等
populateBean(beanName, mbd, instanceWrapper);
// 初始化 bean:执行 aware 方法 --> BeanPostProcessor.before --> afterPropertiesSet()-->初始化方法 --> BeanPostProcessor.after
exposedObject = initializeBean(beanName, exposedObject, mbd);
} catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
......
return exposedObject;
}
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd) throws Throwable {
boolean isInitializingBean = bean instanceof InitializingBean;
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged(() -> {
((InitializingBean)bean).afterPropertiesSet();
return null;
}, this.getAccessControlContext());
} catch (PrivilegedActionException var6) {
throw var6.getException();
}
} else {
((InitializingBean)bean).afterPropertiesSet();
}
}
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) && (!isInitializingBean || !"afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) {
this.invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
接着属性赋值
populateBean:处理属性注入:@Value, @Autowired, @Resource 等,具体的代码就不贴了
然后初始化
initializeBean:执行 aware 方法 --> BeanPostProcessor.applyBeanPostProcessorsBeforeInitialization--> afterPropertiesSet()-->初始化方法(init-method)-->BeanPostProcessor.applyBeanPostProcessorsAfterInitialization
Aware ,英文翻译是意识到的,感知的,Spring 提供了诸多 **Aware 接口用于辅助 Spring Bean 以编程的方式调用 Spring 容器,通过实现这些接口,可以增强 Spring Bean 的功能。
Spring 提供了如下系列的 Aware 接口:
- LoadTimeWeaverAware:加载Spring Bean时织入第三方模块,如AspectJ
- BeanClassLoaderAware:加载Spring Bean的类加载器
- BootstrapContextAware:资源适配器BootstrapContext,如JCA,CCI
- ResourceLoaderAware:底层访问资源的加载器
- BeanFactoryAware:声明BeanFactory
- PortletConfigAware:PortletConfig
- PortletContextAware:PortletContext
- ServletConfigAware:ServletConfig
- ServletContextAware:ServletContext
- MessageSourceAware:国际化
- ApplicationEventPublisherAware:应用事件
- NotificationPublisherAware:JMX通知
- BeanNameAware:声明Spring Bean的名字
比如BeanNameAware:
如果一个类实现了该接口,则可以获取自己的实例在ioc容器中的id(beanName),点击查看示例
BeanPostProcessor 的作用是:如果我们想要在 Spring 容器完成 Bean 的实例化,配置和其他的初始化后添加一些自己的逻辑处理,那么请使用该接口,这个接口给与了用户充足的权限去更改或者扩展 Spring,是我们对 Spring 进行扩展和增强处理一个必不可少的接口。
通过方法名称可知是在初始化之前和之后执行,再看下源码展现:
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(() -> {
this.invokeAwareMethods(beanName, bean);
return null;
}, this.getAccessControlContext());
} else {
//执行aware接口方法
this.invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//执行bean的后置处理的before方法
wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
}
try {
//执行自定义的初始化方法,如init-method,afterPropertiesSet等
this.invokeInitMethods(beanName, wrappedBean, mbd);
} catch (Throwable var6) {
throw new BeanCreationException(mbd != null ? mbd.getResourceDescription() : null, beanName, "Invocation of init method failed", var6);
}
if (mbd == null || !mbd.isSynthetic()) {
// //执行bean的后置处理的after方法
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
初始化方法:初始化方法有一下几种:
1.指定init-method
2.实现InitializingBean
3.使用@PostConstruct注解(底层原理为BeanPostProcessor)
或者使用上面的BeanPostProcessor
最后销毁
销毁一般在容器关闭的时候执行,销毁方法有以下几种:
1.指定destroyMethod
2.让Bean实现DisposableBean接口
3.使用@PreDestory注解(底层原理为BeanPostProcessor)
来看下流程图:
Spring Bean对象的作用域(给某人看):
在Spring容器中管理的Bean对象,可以在声明时通过scope属性或者相关注解指定其作用域
在Spring容器中,Bean对象的作用域一共有5种:singleton(单例)、prototype(多实例)、request(HTTP请求)、session(会话)、global-session(全局会话)。
Bean的五种作用域
singlteon | 在ioc容器中仅存在一个Bean实例,容器一加载(初始化)就会去创建,也是默认值 |
prototype | ioc容器加载的时候不创建,获取的时候才会创建,且每次都返回一个新的bean |
request | 每次http请求都会创建一个新的bean |
session | 同一个http session共享一个bean,不同session使用不同的bean |
globalSession | 一般用于全局会话 |
其中最常用的是singleton和prototype两种:
1)singleton(单例模式)
singleton是默认的作用域,当我们定义Bean时,如果没有给scope指定属性值,Spring会默认Bean的作用域为singleton。singleton属于单例模式,被singleton标识的对象具备全局唯一性,也就是在整个spring的容器中有且仅有一个该Bean的实例。
singleton的 配置文件如下:
<!-- 通过指定scope属性的值,来确定Bean的作用域 -->
<bean id="user" class="com.beans.User"
scope="singleton">
</bean>
2)prototype:这个作用域标识的对象每次获取调用都会创建新的对象
<!-- 通过指定scope属性的值,来确定Bean的作用域 -->
<bean id="user" class="com.beans.User"
scope="prototype">
</bean>
至于request(HTTP请求)、session(会话)、global-session(全局会话)三种作用域,用的话一般会配合SpringMVC框架进行使用,在这里不做深入了解。