首先借个图,说明一下spring的bean的整个生命流程。
销毁什么的这个看图就知道怎么回事,使用的话一般都是纯业务,而且我们更关心spring是怎么初始化的,初始化成我们定义的那个样子。我们就是以这个出发点来看一下spring的大概流程。
spring的创建过程主要哪些步骤:
主要是对象的创建和对象的初始化
其实有人会疑问对象创建和对象初始化有什么区别?
其实就是先后次序的问题。 首先你要是用一个对象,要创建他,这里我们常见的是直接new一个。但是spring利用的是反射。 对象有时候不是创建好了,就可以用,尤其是spring,会出现要用到A对象,A对象以来别的B,C,D对象。毕竟你atowire的这些就是要用到的,你不希望拿到的这些都是null。所以初始化,就是让这个对象按照你设计的那样可以获得对应的值这些,可以去使用,很多程序都需要你自己初始化才能使用,或者说设计的人已经替你弄了一套默认的配置来让你使用。
创建解决的是有没有的问题,初始化决定的是能不能用的问题。否则仅是在内存中站一块空间,这是没啥作用的。
spring的初始化方式 一种是最早的配置文件的方式,里面会有一个 init-method,配置的是对应的这个类的初始化方法。这种初始化方式有一个缺点,初始化函数并不固定,由用户随意定义,这就需要 Spring 通过反射,在运行时动态地调用这个初始化函数。而反射又会影响代码执行的性能。(反射确实会影响性能,像做导入导出文件时,实际上有时候直接给一个确定的要比反射的模板类要快一些)
public class DemoClass {
//...
public void initDemo() {
//...初始化..
}
}
// 配置:需要通过init-method显式地指定初始化方法
<bean id="demoBean" class="com.xzg.cd.DemoClass" init-method="initDemo"></bean>
另一种就是解决这个,Spring 提供了另外一个定义初始化函数的方法,那就是让类实现 Initializingbean 接口。
这个接口包含一个固定的初始化函数定义(afterPropertiesSet() 函数)。Spring 在初始化 Bean 的时候,可以直接通过 bean.afterPropertiesSet() 的方式,调用 Bean 对象上的这个函数,而不需要使用反射来调用了。
public class DemoClass implements InitializingBean{
@Override
public void afterPropertiesSet() throws Exception {
//...初始化...
}
}
// 配置:不需要显式地指定初始化方法
<bean id="demoBean" class="com.xzg.cd.DemoClass"></bean>
spring初始化的细分
实际上分的更细一点,将初始化分为初始化前置操作、初始化、初始化后置操作这三个步骤。
前置操作和后置操作怎么回事,虽然从字面理解就能了解到他们的作用。一个是在初始化前要做的事,一个是初始化后的要做的事。但怎么实现,毕竟spring倡导的是“约定大于配置”。
中间的部分,初始化是在 InitializingBean里面。那他前后的操作在哪里。
同样也是一个接口BeanPostProcesso,里面postProcessBeforeInitialization和postProcessAfterInitialization看到名字就知道那个是前,那个是后。
我们只需要定义一个实现了 BeanPostProcessor 接口的处理器类,并在配置文件中像配置普通 Bean 一样去配置就可以了。Spring 中的 ApplicationContext 会自动检测在配置文件中实现了 BeanPostProcessor 接口的所有 Bean,并把它们注册到 BeanPostProcessor 处理器列表中。在 Spring 容器创建 Bean 的过程中,Spring 会逐一去调用这些处理器。
spring源码的相关初始化的部分 这里很多人还拿的是老的版本代码,一摸一样的文章转载来转载去的,而且还不严谨,我这里建议还是自己去代码里看具体的实现过程。
具体的部分位置是:AbstractAutowireCapableBeanFactory这个类,这个是我们自动装载bean的一个类
很多人看别人的文档直接支到doCreateBean方法,也不能说错,但我个人建议还是从她的公共入库public修饰的createBean开始一步一步的点,直到最后的实现方法doCreateBean方法。
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = (BeanWrapper)this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = this.createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
synchronized(mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
this.applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
} catch (Throwable var17) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Post-processing of merged bean definition failed", var17);
}
mbd.postProcessed = true;
}
}
boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
if (earlySingletonExposure) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
}
this.addSingletonFactory(beanName, () -> {
return this.getEarlyBeanReference(beanName, mbd, bean);
});
}
Object exposedObject = bean;
try {
this.populateBean(beanName, mbd, instanceWrapper);
exposedObject = this.initializeBean(beanName, exposedObject, mbd);
} catch (Throwable var18) {
if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
throw (BeanCreationException)var18;
}
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", var18);
}
if (earlySingletonExposure) {
Object earlySingletonReference = this.getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
} else if (!this.allowRawInjectionDespiteWrapping && this.hasDependentBean(beanName)) {
String[] dependentBeans = this.getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet(dependentBeans.length);
String[] var12 = dependentBeans;
int var13 = dependentBeans.length;
for(int var14 = 0; var14 < var13; ++var14) {
String dependentBean = var12[var14];
if (!this.removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName, "Bean with name '" + beanName + "' has been injected into other beans [" + StringUtils.collectionToCommaDelimitedString(actualDependentBeans) + "] in its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
try {
this.registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
} catch (BeanDefinitionValidationException var16) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", var16);
}
}
当然了,这个创建bean的方法外,里面还提供了销毁bean,处理bean的前置操作和bean的后置操作的公共方法。
|