在spring获取一个bean时,如果是非懒加载的bean,会先在单例池中获取,如果没有获取到,则需要进行bean的创建。那么bean的创建需要经过哪些步骤呢?具体步骤查看下一文了解Spring底层整体脉络-CSDN博客 bean的创建过程这一章节。本文会对bean创建过程中的类加载、实例化前、实例化后的源码进行解读;
读此文章前,最好先了解一下bean的创建的主体源码,参考Spring源码解读之创建bean-CSDN博客。
bean创建的主线代码:
AbstractAutowireCapableBeanFactory.java 的createBean这个方法。
/** * Central method of this class: creates a bean instance, * populates the bean instance, applies post-processors, etc. * @see #doCreateBean */ @Override protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException { if (logger.isTraceEnabled()) { logger.trace("Creating instance of bean '" + beanName + "'"); } RootBeanDefinition mbdToUse = mbd; // Make sure bean class is actually resolved at this point, and // clone the bean definition in case of a dynamically resolved Class // which cannot be stored in the shared merged bean definition. // 马上就要实例化Bean了,确保beanClass被加载了,进行类加载 Class resolvedClass = resolveBeanClass(mbd, beanName); if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) { mbdToUse = new RootBeanDefinition(mbd); mbdToUse.setBeanClass(resolvedClass); } // Prepare method overrides. try {//和@lookUp这个注解相关 就是要做一些属性覆盖的操作 mbdToUse.prepareMethodOverrides(); } catch (BeanDefinitionValidationException ex) { throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(), beanName, "Validation of method overrides failed", ex); } try { // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance. // 实例化前 Object bean = resolveBeforeInstantiation(beanName, mbdToUse); if (bean != null) { return bean; } } catch (Throwable ex) { throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", ex); } try { //创建bean Object beanInstance = doCreateBean(beanName, mbdToUse, args); if (logger.isTraceEnabled()) { logger.trace("Finished creating instance of bean '" + beanName + "'"); } return beanInstance; } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) { // A previously detected exception with proper bean creation context already, // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry. throw ex; } catch (Throwable ex) { throw new BeanCreationException( mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex); } }
当spring要创建一个bean时,先要进行类加载
1. 在bean创建的主线代码createBean方法中会调用
Class resolvedClass = resolveBeanClass(mbd, beanName);
该方法主线逻辑就是判断类有没有被加载,如果已经加载了,则直接返回类;如果没有被加载,则进行类加载。
点击进入该方法。源码解读如下:
/** * Resolve the bean class for the specified bean definition, * resolving a bean class name into a Class reference (if necessary) * and storing the resolved Class in the bean definition for further use. * @param mbd the merged bean definition to determine the class for * @param beanName the name of the bean (for error handling purposes) * @param typesToMatch the types to match in case of internal type matching purposes * (also signals that the returned {@code Class} will never be exposed to application code) * @return the resolved bean class (or {@code null} if none) * @throws CannotLoadBeanClassException if we failed to load the class */ @Nullable protected Class resolveBeanClass(RootBeanDefinition mbd, String beanName, Class... typesToMatch) throws CannotLoadBeanClassException { try { // 如果beanClass被加载了 直接返回该类 if (mbd.hasBeanClass()) { return mbd.getBeanClass(); } // 如果beanClass没有被加载 if (System.getSecurityManager() != null) {//查看是否开启了安全管理器 return AccessController.doPrivileged((PrivilegedExceptionAction
>) () -> doResolveBeanClass(mbd, typesToMatch), getAccessControlContext()); } else {//没有开启安全管理器 加载类 return doResolveBeanClass(mbd, typesToMatch); } } catch (PrivilegedActionException pae) { ClassNotFoundException ex = (ClassNotFoundException) pae.getException(); throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex); } catch (ClassNotFoundException ex) { throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), ex); } catch (LinkageError err) { throw new CannotLoadBeanClassException(mbd.getResourceDescription(), beanName, mbd.getBeanClassName(), err); } } 2. 如果类没有被加载,resolveBeanClass这个方法则会调用
doResolveBeanClass(mbd, typesToMatch);
这个方法,这个方法主要逻辑就是获取类加载器,然后进行加载类;
其源码解读如下:
@Nullable private Class doResolveBeanClass(RootBeanDefinition mbd, Class... typesToMatch) throws ClassNotFoundException { //1. 获取对应的类加载器 ClassLoader beanClassLoader = getBeanClassLoader(); ClassLoader dynamicLoader = beanClassLoader; boolean freshResolve = false; if (!ObjectUtils.isEmpty(typesToMatch)) { // When just doing type checks (i.e. not creating an actual instance yet), // use the specified temporary class loader (e.g. in a weaving scenario). ClassLoader tempClassLoader = getTempClassLoader(); if (tempClassLoader != null) { dynamicLoader = tempClassLoader; freshResolve = true; if (tempClassLoader instanceof DecoratingClassLoader) { DecoratingClassLoader dcl = (DecoratingClassLoader) tempClassLoader; for (Class typeToMatch : typesToMatch) { dcl.excludeClass(typeToMatch.getName()); } } } } String className = mbd.getBeanClassName(); if (className != null) { // 解析Spring表达式,有可能直接返回了一个Class对象 Object evaluated = evaluateBeanDefinitionString(className, mbd); if (!className.equals(evaluated)) {//可以暂时忽略不看 是我们定义bean时可能会用spring的表达式定义bean,很少用这种形式 // A dynamically resolved expression, supported as of 4.2... if (evaluated instanceof Class) {//解析得到的对象已经是一个class对象 说明已经被加载 直接返回 return (Class) evaluated; } else if (evaluated instanceof String) {//解析得到的值还是一个字符串 说明类还没有被加载 需要被加载 className = (String) evaluated; freshResolve = true; } else { throw new IllegalStateException("Invalid class name expression result: " + evaluated); } } if (freshResolve) {//2. 加载类 // When resolving against a temporary class loader, exit early in order // to avoid storing the resolved Class in the bean definition. if (dynamicLoader != null) { try { //加载类 return dynamicLoader.loadClass(className); } catch (ClassNotFoundException ex) { if (logger.isTraceEnabled()) { logger.trace("Could not load class [" + className + "] from " + dynamicLoader + ": " + ex); } } } return ClassUtils.forName(className, dynamicLoader); } } // Resolve regularly, caching the result in the BeanDefinition... return mbd.resolveBeanClass(beanClassLoader); }
2.1 那么我们看一下,类加载器是如何获取的:我们根据上述代码中
ClassLoader beanClassLoader = getBeanClassLoader();
一路点入,找到获取类加载器的源码;ClassUtils.java中的
public static ClassLoader getDefaultClassLoader()
具体源码解读如下:
/** * Return the default ClassLoader to use: typically the thread context * ClassLoader, if available; the ClassLoader that loaded the ClassUtils * class will be used as fallback. *
Call this method if you intend to use the thread context ClassLoader * in a scenario where you clearly prefer a non-null ClassLoader reference: * for example, for class path resource loading (but not necessarily for * {@code Class.forName}, which accepts a {@code null} ClassLoader * reference as well). * @return the default ClassLoader (only {@code null} if even the system * ClassLoader isn't accessible) * @see Thread#getContextClassLoader() * @see ClassLoader#getSystemClassLoader() */ @Nullable public static ClassLoader getDefaultClassLoader() { ClassLoader cl = null; // 1. 优先获取线程中的类加载器 try { cl = Thread.currentThread().getContextClassLoader(); } catch (Throwable ex) { // Cannot access thread context ClassLoader - falling back... } // 2. 线程中类加载器为null的情况下,获取加载ClassUtils类的类加载器 if (cl == null) { // No thread context class loader -> use class loader of this class. cl = ClassUtils.class.getClassLoader(); if (cl == null) { // getClassLoader() returning null indicates the bootstrap ClassLoader // 加入ClassUtils是被Bootstrap类加载器加载的,则获取系统类加载器 try { cl = ClassLoader.getSystemClassLoader(); } catch (Throwable ex) { // Cannot access system ClassLoader - oh well, maybe the caller can live with null... } } } return cl; }
2.2 获取到了类加载器后,上述中doResolveBeanClass这个方法中
dynamicLoader.loadClass(className);
进行加载类;
在spring加载完要创建的bean的类后,在对象实例化前会有一些操作,源码注释中写到:给bean的后置处理器一个产生代理对象代替将要创建的实例的机会。
bean创建的主线代码:AbstractAutowireCapableBeanFactory.java 的createBean这个方法会调用以下代码;
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
// 实例化前
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
点击进入resolveBeforeInstantiation这个方法
具体源码解读如下:
/**
* Apply before-instantiation post-processors, resolving whether there is a
* before-instantiation shortcut for the specified bean.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @return the shortcut-determined bean instance, or {@code null} if none
*/
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
// synthetic表示合成,如果某些Bean是合成的,那么则不会经过BeanPostProcessor的处理
//hasInstantiationAwareBeanPostProcessors() 判断类有没有继承BeanPostProcessors相关的子类
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
//执行具体实例化前的操作
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
在spring给bean的后置处理器一个产生代理对象代替将要创建的实例的机会,也就是实例化前的操作完成后,spring会创建出一个普通对象,即bean的实例化。
bean创建的主线代码:AbstractAutowireCapableBeanFactory.java 的createBean这个方法会调用以下代码;
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
doCreateBean这个方法就是创建一个bean的详细过程,比如bean的实例化、bean的实例化后、bean的依赖注入等。该方法源码解读如下:
/**
* Actually create the specified bean. Pre-creation processing has already happened
* at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.
* Differentiates between default bean instantiation, use of a
* factory method, and autowiring a constructor.
* @param beanName the name of the bean
* @param mbd the merged bean definition for the bean
* @param args explicit arguments to use for constructor or factory method invocation
* @return a new instance of the bean
* @throws BeanCreationException if the bean could not be created
* @see #instantiateBean
* @see #instantiateUsingFactoryMethod
* @see #autowireConstructor
*/
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// 实例化bean
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
// 有可能在本Bean创建之前,就有其他Bean把当前Bean给创建出来了(比如依赖注入过程中)
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 创建Bean实例
// createBeanInstance(beanName, mbd, args) 包含推断构造方法
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object bean = instanceWrapper.getWrappedInstance();
Class beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// 后置处理合并后的BeanDefinition
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
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) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 循环依赖-添加到三级缓存
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
// 属性填充
populateBean(beanName, mbd, instanceWrapper);
// 初始化
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);
}
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
// beanName被哪些bean依赖了,现在发现beanName所对应的bean对象发生了改变,那么则会报错
String[] dependentBeans = getDependentBeans(beanName);
Set actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!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 " +
"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
此处,我们着重看一下bean是如何被实例化的。
点击上述方法中
instanceWrapper = createBeanInstance(beanName, mbd, args);
进入该方法,该方法主要包含了bean实例化的几种方式以及推断构造方法的实现,具体源码解读如下:
/**
* Create a new instance for the specified bean, using an appropriate instantiation strategy:
* factory method, constructor autowiring, or simple instantiation.
* @param beanName the name of the bean
* @param mbd the bean definition for the bean
* @param args explicit arguments to use for constructor or factory method invocation
* @return a BeanWrapper for the new instance
* @see #obtainFromSupplier
* @see #instantiateUsingFactoryMethod
* @see #autowireConstructor
* @see #instantiateBean
*/
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
Class beanClass = resolveBeanClass(mbd, beanName);
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
// BeanDefinition中添加了Supplier,则调用Supplier来得到对象
Supplier instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// @Bean对应的BeanDefinition
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
// 一个原型BeanDefinition,会多次来创建Bean,那么就可以把该BeanDefinition所要使用的构造方法缓存起来,避免每次都进行构造方法推断
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
// autowireNecessary表示有没有必要要进行注入,比如当前BeanDefinition用的是无参构造方法,那么autowireNecessary为false,否则为true,表示需要给构造方法参数注入值
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
// 如果确定了当前BeanDefinition的构造方法,那么看是否需要进行对构造方法进行参数的依赖注入(构造方法注入)
if (autowireNecessary) {
// 方法内会拿到缓存好的构造方法的入参
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 构造方法已经找到了,但是没有参数,那就表示是无参,直接进行实例化
return instantiateBean(beanName, mbd);
}
}
// 如果没有找过构造方法,那么就开始找了
// Candidate constructors for autowiring?
// 提供一个扩展点,可以利用SmartInstantiationAwareBeanPostProcessor来控制用beanClass中的哪些构造方法
// 比如AutowiredAnnotationBeanPostProcessor会把加了@Autowired注解的构造方法找出来,具体看代码实现会更复杂一点
Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// 如果推断出来了构造方法,则需要给构造方法赋值,也就是给构造方法参数赋值,也就是构造方法注入
// 如果没有推断出来构造方法,但是autowiremode为AUTOWIRE_CONSTRUCTOR,则也可能需要给构造方法赋值,因为不确定是用无参的还是有参的构造方法
// 如果通过BeanDefinition指定了构造方法参数值,那肯定就是要进行构造方法注入了
// 如果调用getBean的时候传入了构造方法参数值,那肯定就是要进行构造方法注入了
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}
// No special handling: simply use no-arg constructor.
// 不匹配以上情况,则直接使用无参构造方法
return instantiateBean(beanName, mbd);
}