Spring源码系列:Bean的加载

2023-11-08

前言

在我们前面两章,我们讲完了Spring如何加载、解析资源文件以及如何将其转化为BeanDefinition的(标签的解析)流程。那么接下来我们来看下Bean的一个加载过程。我们来从这段代码为切入口:

public static void main(String[] args) {
	ClassPathResource resource = new ClassPathResource("test.xml");
	DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
	XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
	reader.loadBeanDefinitions(resource);

	GetNameTest getNameTest = (GetNameTest) factory.getBean("getNameTest");
	getNameTest.getName();
}

一. Bean的加载

Spring中对于bean的加载功能,普遍的调用方式为factory.getBean(beanName);那我们来看下这个方法到底做了什么事情,再根据每一个步骤进行展开来细说。

GetNameTest getNameTest = (GetNameTest) factory.getBean("getNameTest");
↓↓↓↓↓↓
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
	@Override
	public Object getBean(String name) throws BeansException {
		return doGetBean(name, null, null, false);
	}
	↓↓↓↓↓↓
	protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {
		// 1.提取对应的beanName
		String beanName = transformedBeanName(name);
		Object beanInstance;

		// 2.检查缓存中或者实例工厂中是否有对应的实例
		/**
		 * 背景:在创建单例bean的时候,存在依赖注入的情况。
		 * 目的:为了避免循环依赖的产生,Spring再创建bean的时候,并不会等待bean创建完成,而是会在 bean 创建完成之前提早曝光这个 ObjectFactory。
		 * 即:将 ObjectFactory 加入到Map缓存中,下一个bean创建的时候,若需要依赖上一个bean,那么就可以直接使用这个 ObjectFactory 对象。
		 * 缓存:this.singletonObjects
		 * 提前暴露的单利工厂。this.singletonFactories。其还有另外一个熟悉的名称:三级工厂。具体的分析,在下文展开
		 */
		Object sharedInstance = getSingleton(beanName);
		if (sharedInstance != null && args == null) {
			if (logger.isTraceEnabled()) {
				if (isSingletonCurrentlyInCreation(beanName)) {
					logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
							"' that is not fully initialized yet - a consequence of a circular reference");
				}
				else {
					logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
				}
			}
			// 3.返回对应的实例,因为有时候如BeanFactory的情况,并不是直接返回实例本身。而是返回指定方法返回的实例对象。
			beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
		}

		else {
			// 4.若出现循环依赖的情况,则抛异常
			/**
			 * A类、B类必须为单例
			 * A类有B对象作为其属性。
			 * B类有A对象作为其属性。
			 */
			if (isPrototypeCurrentlyInCreation(beanName)) {
				throw new BeanCurrentlyInCreationException(beanName);
			}

			// 5.若BeanDefinitionMap中(存储已经加载好的类)不包含beanName。那么尝试从父BeanDefinition中去检测。即父工厂
			BeanFactory parentBeanFactory = getParentBeanFactory();
			if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
				String nameToLookup = originalBeanName(name);
				if (parentBeanFactory instanceof AbstractBeanFactory abf) {
					return abf.doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
				}
				// 递归到beanFactory中去寻找。
				else if (args != null) {
					return (T) parentBeanFactory.getBean(nameToLookup, args);
				}
				else if (requiredType != null) {
					return parentBeanFactory.getBean(nameToLookup, requiredType);
				}
				else {
					return (T) parentBeanFactory.getBean(nameToLookup);
				}
			}
			// 6.若不是仅仅做类型检查。那么就是创建bean。这里做一个mark(标记),做记录。
			if (!typeCheckOnly) {
				markBeanAsCreated(beanName);
			}

			StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
					.tag("beanName", name);
			try {
				if (requiredType != null) {
					beanCreation.tag("beanType", requiredType::toString);
				}
				// 7.我们从Spring解析标签的过程中可以得知。XML的一些具体配置都存储于 GenericBeanDefinition 中
				// 这里则是将 GenericBeanDefinition 转化为 RootBeanDefinition。
				// 若指定的 beanName 是子Bean的话,还会合并父子BeanDefinition。
				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				// 8.检测合并后的类型。合并后的BeanDefinition肯定不是AbstractBeanDefinition,若是,则其肯定是abstract类型的,此时抛异常
				checkMergedBeanDefinition(mbd, beanName, args);

				// 9.若存在依赖,那么开始递归实例化依赖的Bean。(属性注入(包括实例化))
				String[] dependsOn = mbd.getDependsOn();
				if (dependsOn != null) {
					for (String dep : dependsOn) {
						if (isDependent(beanName, dep)) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
						}
						registerDependentBean(dep, beanName);
						try {
							getBean(dep);
						}
						catch (NoSuchBeanDefinitionException ex) {
							throw new BeanCreationException(mbd.getResourceDescription(), beanName,
									"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
						}
					}
				}

				// 10.若依赖都注入完了。就开始实例化本身,创建单例模式,注意这里是第一次实例化(因为单例缓存中不存在,才会走到该分支)
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							destroySingleton(beanName);
							throw ex;
						}
					});
					beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
				else if (mbd.isPrototype()) {
					// 多例,创建个新的实例
					Object prototypeInstance = null;
					try {
						beforePrototypeCreation(beanName);
						prototypeInstance = createBean(beanName, mbd, args);
					}
					finally {
						afterPrototypeCreation(beanName);
					}
					beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
				}
				else {
					// 或者根据指定的scope进行实例化
					String scopeName = mbd.getScope();
					if (!StringUtils.hasLength(scopeName)) {
						throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");
					}
					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, () -> {
							beforePrototypeCreation(beanName);
							try {
								return createBean(beanName, mbd, args);
							}
							finally {
								afterPrototypeCreation(beanName);
							}
						});
						beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
					}
					catch (IllegalStateException ex) {
						throw new ScopeNotActiveException(beanName, scopeName, ex);
					}
				}
			}
			catch (BeansException ex) {
				// ...
			}
			finally {
				beanCreation.end();
			}
		}
		// 11.检查需要的类型是否符合bean的实际类型
		return adaptBeanInstance(name, beanInstance, requiredType);
	}
}

上述代码可以做个总结,其大致步骤如下:

  1. 转换对应beanName传入的参数可能是别名、FactoryBean。因此需要进行进一步的转换解析。
  2. 尝试从缓存中加载单例,若有,则可以直接返回。
  3. bean的实例化。
  4. 检测ParentBeanFactory,进行递归。
  5. 循环依赖检查。
  6. GenericBeanDefinition 转化为 RootBeanDefinition,若当前bean为子bean,则合并父子BeanDefinition
  7. 寻找依赖,对依赖项进行递归注入。
  8. 针对不同的scope进行bean的创建。
  9. 类型转换。

大胆点,我们再简化一下,Bean的一个加载三步走:

  1. Bean的实例化。
  2. Bean的相关依赖注入。
  3. Bean的初始化。

对应写出个伪代码:

Object dfs(beanName){
	// 1.实例化
	Object bean = getBeanInstance(beanName);
	// 2.递归依赖注入(若存在)
	String[] depends = getDependsOn(bean);
	for(String name:depends){
		dfs(name);
	}
	// 3.初始化
	return initBean(bean);
}

1.1 FactoryBean的使用

背景:Spring通过反射机制利用beanclass属性指定实现类来实例化bean但是传统的方式下,需要在<bean>标签里面配置大量的信息,而XML配置的这种方式是有局限性的。 若可以通过编码的方式来进行实例化,就能更加自由地实例化一些复杂的beanFactoryBean这个接口就是用来让用户定制自定义实例化的逻辑的。

public interface FactoryBean<T> {
	String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";
	// 返回由FactoryBean创建的bean实例,如果isSingleton()返回true
	// 那么该实例则会放到单例缓存池里面。
	@Nullable
	T getObject() throws Exception;
	// 返回FactoryBean创建的bean实例的类型
	@Nullable
	Class<?> getObjectType();
	// 返回由 FactoryBean 创建的bean实例的作用域,是singleton还是prototype
	default boolean isSingleton() {
		return true;
	}
}

若配置文件中的<bean>标签的class属性配置的实现类是FactoryBean的实现类的时候,那么通过getBean()返回的则是FactoryBean.getObject()方法返回的对象。相当于其代理了getBean的方法。

案例:FactoryBean的使用和定义

项目结构如下:
在这里插入图片描述
User类:

public class User {
	private String name;
	private String address;

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

UserFactoryBean类,需要实现FactoryBean类,进行自定义加载Bean。

import org.springframework.beans.factory.FactoryBean;

public class UserFactoryBean implements FactoryBean<User> {
	private String userInfo;
	@Override
	public User getObject() throws Exception {
		User user = new User();
		String[] infos = userInfo.split(",");
		user.setName(infos[0]);
		user.setAddress(infos[1]);
		return user;
	}

	@Override
	public Class<User> getObjectType() {
		return User.class;
	}

	@Override
	public boolean isSingleton() {
		return false;
	}

	public String getUserInfo() {
		return userInfo;
	}

	public void setUserInfo(String userInfo) {
		this.userInfo = userInfo;
	}
}

user.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xsi:schemaLocation="
   	http://www.springframework.org/schema/beans
   	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
	<bean id="user" class="com.mytest.factorytest.UserFactoryBean">
		<property name="userInfo" value="你好,上海"/>
	</bean>

</beans>

Test类:

public class Test {
	public static void main(String[] args) {
		DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
		XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);

		ClassPathResource resource = new ClassPathResource("/factorytest/user.xml");
		reader.loadBeanDefinitions(resource);

		User user = (User) factory.getBean("user");
		System.out.println(user.getName());
		System.out.println(user.getAddress());
	}
}

代码运行结果如下:
在这里插入图片描述
可见确实如上文所说FactoryBean.getObject()方法代理了getBean()方法,负责Bean的加载。

1.2 缓存中获取单例Bean

Spring在获取bean的时候,会先从单例缓存中去尝试获取,若还没有,则再去singletonFactories中加载。

我们来看下这个方法:Object sharedInstance = getSingleton(beanName);

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
	public Object getSingleton(String beanName) {
		// true设置为:允许早期依赖(就是我们说的,为了避免循环依赖,不等bean创建完成就会将创建bean的ObjectFactory提早曝光)
		return getSingleton(beanName, true);
	}
	↓↓↓↓↓↓
	@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		// 1.先检查一级缓存中是否存在,若存在,则直接返回。这里的bean都是已经创建完成的。
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			// 2.尝试从二级缓存中获取,这里的bean都是完成实例化,但是没有进行属性注入和初始化的对象或者代理对象
			singletonObject = this.earlySingletonObjects.get(beanName);
			if (singletonObject == null && allowEarlyReference) {
				synchronized (this.singletonObjects) {
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
						singletonObject = this.earlySingletonObjects.get(beanName);
						if (singletonObject == null) {
							// 3.singletonFactories:提前暴露的单例工厂,二级缓存中存储的对象,就是从该工厂中获取到的对象
							ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
							if (singletonFactory != null) {
								// 4.创建bean
								singletonObject = singletonFactory.getObject();
								// 5.earlySingletonObjects和singletonFactories互斥
								this.earlySingletonObjects.put(beanName, singletonObject);
								this.singletonFactories.remove(beanName);
							}
						}
					}
				}
			}
		}
		return singletonObject;
	}
}

我们可以看出来,这里Spring有三级的缓存,用来解决循环依赖问题,具体的在下文展开。在此先解释下几种缓存代表的意义:

  • singletonObjects:保存beanNamebean实例(初始化完成的)之间的关系。
  • earlySingletonObjects:同样保存beanNamebean实例之间的关系。循环对象依赖列表,用于存储那些发生了循环依赖的对象。
  • singletonFactories:保存beanName和创建bean的工厂ObjectFactory之间的关系。注意和前两者的区别,其存储的并不是bean,而是负责创建它的工厂。

1.2.1 Spring解决循环依赖的原理☆

接下来我会用大篇幅来讲这个循环依赖的问题,也希望尽量将这一块难题啃下来,也方便日后自己复习,这里参考了这位博主的文章(第二次看了)

我们先来看下循环依赖的一个示意图:这里的类都是单例。
在这里插入图片描述
或者是更简单粗暴的:

@Component
public class A{
	@Autowired
	private A a;
}

那么在这种情况下,就是所谓的循环依赖了。


我们以AB两个类之间的依赖来讲解Spring解决循环依赖的过程。
整体过程如下:

  1. 实例化A
  2. A的属性B进行注入。
  3. B进行实例化。
  4. B进行属性注入。
  5. B完成初始化方法。
  6. A注入完成。则完成初始化方法。
(1) 以A类的角度来观察bean的加载过程。

Spring先对A进行实例化(第一次),那么最终最终会走代码中的第十步:

if (mbd.isSingleton()) {
	sharedInstance = getSingleton(beanName, () -> {
		try {
			return createBean(beanName, mbd, args);
		}
		catch (BeansException ex) {
			destroySingleton(beanName);
			throw ex;
		}
	});
	beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

该代码走的则是getSingleton的重载方法:

getSingleton(String beanName, ObjectFactory<?> singletonFactory)

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
	Assert.notNull(beanName, "Bean name must not be null");
	synchronized (this.singletonObjects) {
		// 1.同样先去单例缓存中去拿
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null) {
			// ..日志记录等
			// 2.在创建单例对象之前先做一个标记处理。将beanName放入singletonsCurrentlyInCreation集合中。
			// 代表这个bean正在被创建中,如果一个单例Bean被多次创建,那么会在这里抛出异常
			beforeSingletonCreation(beanName);
			boolean newSingleton = false;
			boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
			if (recordSuppressedExceptions) {
				this.suppressedExceptions = new LinkedHashSet<>();
			}
			try {
				// 3.这里则执行外部传入的参数,是一个lambda表达式,调用上文的createBean方法
				singletonObject = singletonFactory.getObject();
				newSingleton = true;
			}
			// ...catch
			finally {
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = null;
				}
				// 3.创建完成后,将对应的beanName从singletonsCurrentlyInCreation中删除
				afterSingletonCreation(beanName);
			}
			if (newSingleton) {
				// 4.添加到一级缓存中,注意到这一步为止,该单例bena已经创建完成了。即完成了初始化了。
				addSingleton(beanName, singletonObject);
			}
		}
		return singletonObject;
	}
}

从代码中我们可以发现,类的实例化由singletonObject = singletonFactory.getObject();来完成。我们又知道,外部传入的lambda表达式只执行了createBean方法。我们来跟进:

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
		implements AutowireCapableBeanFactory {
	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
		// ...省略
		try {
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			// ...
			return beanInstance;
		}
		// ...catch
	}
	
	protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			// 创建实例
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		Object bean = instanceWrapper.getWrappedInstance();
		Class<?> beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			// log...
			// 先将beanName->工厂方法,加入到三级缓存中,因为可能会发生循环依赖
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}
		// 三级缓存中添加完成后,在进行属性注入和初始化
		Object exposedObject = bean;
		try {
			// 属性注入
			populateBean(beanName, mbd, instanceWrapper);
			// 初始化
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		if (earlySingletonExposure) {
			// 这里再一次调用了getSingleton方法,并且禁用了三级缓存。
			// 在属性注入阶段,B的属性注入阶段中,已经将A从三级缓存工厂取出,并加入到了二级缓存。
			// 因此这里取出来的是A的一个代理对象。
			Object earlySingletonReference = getSingleton(beanName, false);
			// ...
		}
	}
}

在这里做个总结,A类的加载做了什么事情getBean(beanNameA)开始:

  1. A完成了实例化。
  2. beanNameA对应的工厂方法加入到了三级缓存。
  3. A完成属性注入populateBean(beanName, mbd, instanceWrapper);
  4. A完成初始化exposedObject = initializeBean(beanName, exposedObject, mbd);

那么对于B类的加载,则发生在A类加载阶段的第三步:属性注入阶段。

注意:属性注入阶段对于A类的属性B而言,也只不过是完成了三个步骤:实例化、B类的属性注入、初始化。

(2) 以B类的角度来观察bean的加载过程。

对于B而言,其加载同样是从getBean(beanNameB)开始的,同样的:

  1. B完成了实例化。
  2. beanNameB对应的工厂方法加入到了三级缓存。
  3. 此时发现B类下面有个A属性,那么对A进行属性注入。 开始调用getBean(beanNameA)
  4. B完成初始化。

但是,这里的getBean则会走不同的分支了,我们这里可以接上1.1节源码的第二步:Object sharedInstance = getSingleton(beanName);(与A类的加载过程进行区分,参数传的不一样,并且在A类的加载过程中,已经将相关的工厂加入到了三级缓存中了。)此时跟进代码,我们会走入该环节:
在这里插入图片描述
结合上述代码,我们可以发现注入到B中的A对象是通过addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));提前暴露出去的,我们来跟进下getEarlyBeanReference

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
		implements AutowireCapableBeanFactory {
	// 获取后置处理器,即通过@EnableAspectJAutoProxy注解导入的AnnotationAwareAspectJAutoProxyCreator对象
	protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
		Object exposedObject = bean;
		// 若有AOP的相关配置逻辑,才会走这段代码,若没有,本代码实则上并没有什么作用。也就是说三级工厂在无AOP的情况下是没有实质作用的。
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
				exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
			}
		}
		return exposedObject;
	}
}

那么在无AOP的情况下:

  • 虽然加载B的时候,给B注入了一个未完成初始化的对象A,但是A将其引用加入到了三级缓存。
  • 因此注入到B中的是A的一个引用。在B完成初始化后,会根据这个引用对A进行初始化。

在开启AOP的情况下,则会走代码exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
	@Override
	public Object getEarlyBeanReference(Object bean, String beanName) {
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		this.earlyProxyReferences.put(cacheKey, bean);
		// 若需要代理,返回代理对象。
		// 若不需要代理,则返回当前这个bean。
		return wrapIfNecessary(bean, beanName, cacheKey);
	}
}

总结下就是:
在这里插入图片描述
注意:

  • 初始化的时候我们都是对类本身进行初始化,但是在上述过程中,如容器给B在这里插入代码片类的注入的属性是A的代理对象,但是不管是cglib还是jdk代理,内部都存储一个目标类的引用。而A的代理对象就是A的一个引用。因此代理对象完成了初始化,A类自然而然完成了初始化。
  • 只用二级缓存可以吗?为什么非要用三级缓存去存储一个工厂对象呢?若没有三级缓存,那么在B加载环节,就需要其相关属性完成AOP代理。而Spring希望AOP在bena初始化之后再进行。 因此,通过一个三级缓存,返回一个代理对象(没有完成AOP操作的),让bean之间完成初始化操作并解决循环依赖问题。最后再遵循Spring的原则,进行AOP代理。

1.2.2 小结

getBean有两种用途:

  1. 生成Bean,并将其工厂方法存入三级缓存。
  2. 从单例缓存中去获取bean

此外,我们可以发现,二级缓存就能够实现解决Spring循环依赖的需求,而三级缓存的存在仅仅是提供了一个能够生成代理对象的工厂方法。 那么其目的是什么?

假设我们没有三级缓存,我们的对象并且是单例的。若A对象依赖的B对象存在AOP机制,B对象需要被代理。那么在属性注入的时候,再加入二级缓存之前都需要被代理。这并不合适。 那么如果能够通过第三方的工厂方法,生成一个代理对象丢给二级缓存,就能解决这个问题。


问题来了:为何在存在AOP的情况下,我的实例再加入二级缓存之前就一定要完成代理呢?

  • Spring在创建对象的过程中,不知道对象什么时候会被代理, 因此无论当前对象是否需要被代理,总是会提前生成一个普通对象。
  • 若二级缓存中存入的是半成品对象(只完成了实例化的),那么当被引用的时候,若发现了存在AOP代理,那么Spring又需要为其创建一个代理对象并返回。此时,二级缓存中的对象和代理对象并不是一个对象。

那么请问:代理对象和二级缓存中的对象不是一个东西,引用不同。那么这种情况下完成对代理对象的初始化之后,原对象完成了吗?

没有,那么通过三级缓存,直接将代理对象(其引用和Spring想要加载的bean的引用是同一个)返回给二级缓存。那么此时即满足AOP的代理条件,又能够满足Spring的一个初始化过程。

言归正传,到此为止,在讲解bean的循环依赖的过程中,其实已经顺带把bean加载的一个过程给过了一遍。但是里面的一些方法我们还没有详细的去了解。

1.3 从bean的实例中获取对象

我们在getBean方法中可以发现,getObjectForBeanInstance这个方法调用了多次。在这两种大情况下,都会调用该方法:

  • 从缓存中加载bean
  • 根据不同的scope策略加载bean

而该方法的目的就是为了检测bean的正确性。主要用于检测当前bean是否是FactoryBean类型的bean 如果是,则会调用对应实例中的getObject()方法作为返回值(参考1.1小节的案例)。我们可以从侧面发现,无论从缓存中还是策略加载的bean都是最原始的bean。我们还需要做进一步的处理,来看下其源码:

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
	protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

		// 1.若指定的name是工厂相关的,并且&开头
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			if (beanInstance instanceof NullBean) {
				return beanInstance;
			}
			// 若不是 FactoryBean 类型,则验证不通过。前后if矛盾
			if (!(beanInstance instanceof FactoryBean)) {
				throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
			}
			if (mbd != null) {
				mbd.isFactoryBean = true;
			}
			// 若是 FactoryBean ,我们就用它创建实例。
			return beanInstance;
		}
		// 2.若是bean本身,则直接返回
		if (!(beanInstance instanceof FactoryBean)) {
			return beanInstance;
		}
		Object object = null;
		if (mbd != null) {
			mbd.isFactoryBean = true;
		}
		else {
			// 3.尝试从缓存中加载bean
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			// 4.若是BeanFactory类型的实例。且缓存中不存在
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// 5.在所有已经加载的bean中检测,是否存在相同的bean
			if (mbd == null && containsBeanDefinition(beanName)) {
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			// 6.是否是用户定义的,而非程序本身定义。
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			// 7.核心代码,获取实例对象。
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}
}

再从最后一步的核心代码出发,来看下展开的源码:

protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
	// 1.若是单例模式
	if (factory.isSingleton() && containsSingleton(beanName)) {
		// 2.锁住singletonObjects对象,一级缓存
		synchronized (getSingletonMutex()) {
			// 3.factoryBeanObjectCache存储一些已经创建好的,并且由factoryBean创建出来的bean。
			Object object = this.factoryBeanObjectCache.get(beanName);
			if (object == null) {
				object = doGetObjectFromFactoryBean(factory, beanName);
				// 发生循环引用时可能也会有提早暴露的对象(代理)
				Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
				if (alreadyThere != null) {
					object = alreadyThere;
				}
				else {
					// 若需要对bean进行后续处理
					if (shouldPostProcess) {
						// 若该bean还在创建过程中,则不做处理直接返回
						if (isSingletonCurrentlyInCreation(beanName)) {
							return object;
						}
						// 创建bean前预处理
						beforeSingletonCreation(beanName);
						try {
							object = postProcessObjectFromFactoryBean(object, beanName);
						}
						catch (Throwable ex) {
							throw new BeanCreationException(beanName,
									"Post-processing of FactoryBean's singleton object failed", ex);
						}
						finally {
							// 创建bean后处理
							afterSingletonCreation(beanName);
						}
					}
					if (containsSingleton(beanName)) {
						this.factoryBeanObjectCache.put(beanName, object);
					}
				}
			}
			return object;
		}
	}
	else {
		Object object = doGetObjectFromFactoryBean(factory, beanName);
		if (shouldPostProcess) {
			try {
				object = postProcessObjectFromFactoryBean(object, beanName);
			}
			catch (Throwable ex) {
				throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
			}
		}
		return object;
	}
}

可以发现最外层的if/else分支,都调用了doGetObjectFromFactoryBean方法:

private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
	Object object;
	try {
		// 权限验证
		if (System.getSecurityManager() != null) {
			AccessControlContext acc = getAccessControlContext();
			try {
				object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
			}
			catch (PrivilegedActionException pae) {
				throw pae.getException();
			}
		}
		else {
			object = factory.getObject();
		}
	}
	// catch..
	// ...
	return object;
}

可以发现无论怎么样,都会执行FactoryBeangetObject方法来获取实例对象。本小节实质上并不是特别复杂,通过简化也就是:

  1. 检验beanInstance对象,他是bean类型还是FactoryBean类型的实例?
  2. 若是FactoryBean类型的,并且以&为开头,说明用户希望直接获取工厂实例而非工厂方法创建出来的实例对象。
  3. 若是bean类型,直接返回。
  4. 若是FactoryBean类型,不以&开头,那么就调用其getObject()方法并返回实例。
  5. 并且根据条件(是否用户创建),来对该bean实例进行后续处理。即后处理器的调用。

Spring在获取bean的时候有这么一个规则:尽可能保证所有bean初始化完成后都会调用注册的BeanPostProcessorpostProcessAfterInitialization方法进行处理。

紧接着,我们需要将注意力几种在Bean的一个创建过程。即实例化、属性注入、初始化的这么一个过程。

1.4 Bean的创建☆

上述文章中,一大片篇幅其实都是在讲Spring如何从缓存中加载Bean(1.2节)以及如何将原始bean进行转换的(1.3节)。但是我们都没有具体的去看过Spring在第一次的时候(无缓存)是怎么创建Bean的。

一切还是该从这段代码走起,来再回忆一遍:

if (mbd.isSingleton()) {
	sharedInstance = getSingleton(beanName, () -> {
		try {
			return createBean(beanName, mbd, args);
		}
		catch (BeansException ex) {
			destroySingleton(beanName);
			throw ex;
		}
	});
	beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

createBean则是创建Bean的入口函数,最终的实现在AbstractAutowireCapableBeanFactory类中完成:

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
		throws BeanCreationException {
	// ...
	RootBeanDefinition mbdToUse = mbd;

	// 1.锁定class,根据设置的class属性或者根据className来解析
	Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
	if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
		mbdToUse = new RootBeanDefinition(mbd);
		mbdToUse.setBeanClass(resolvedClass);
	}

	// 2.验证和准备覆盖的方法。
	try {
		mbdToUse.prepareMethodOverrides();
	}
	// ...catch
	try {
		// 3.提供机会,用BeanPostProcessors返回的代理对象来替代实例
		Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
		if (bean != null) {
			return bean;
		}
	}
	// ...catch

	try {
		// 4.创建bean
		Object beanInstance = doCreateBean(beanName, mbdToUse, args);
		if (logger.isTraceEnabled()) {
			logger.trace("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	}
	// ...catch
}

一共有4步:

  1. 根据设置的class属性或者根据className来解析Class
  2. override属性进行标记验证。如XML配置中的lookup-methodreplaced-method标签。
  3. 应用初始化前的后处理器,解析指定的bean是否存在初始化前的短路操作。
  4. 创建bean

1.4.1 处理override属性

XML配置中的lookup-methodreplaced-method标签。经过Spring容器的读取和转换后,将其存放在BeanDefinition中的methodOverrides属性中,而下面的操作就是针对该属性来进行的。

mbdToUse.prepareMethodOverrides();
↓↓↓↓↓
public void prepareMethodOverrides() throws BeanDefinitionValidationException {
	// 判断methodOverrides是否为空
	if (hasMethodOverrides()) {
		// 遍历处理
		getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
	}
}
↓↓↓↓↓
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
	// 获取对应类中和该名称同名的方法的个数
	int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
	// 若没有,抛出异常,说明XML配置肯定出问题啦,配置了一个不存在的方法
	if (count == 0) {
		throw new BeanDefinitionValidationException(
				"Invalid method override: no method with name '" + mo.getMethodName() +
				"' on class [" + getBeanClassName() + "]");
	}
	else if (count == 1) {
		// 标记methodOverride暂时没有被覆盖,避免参数类型检查带来的开销
		mo.setOverloaded(false);
	}
}

在后续bean实例化的阶段,若检查到对应的methodOverride属性,则会动态的为当前bean生成代理,并使用拦截器为bean做增强处理(下文介绍)。

1.4.2 实例化的前置处理

Spring-AOP的功能就是基于此进行的,我们来看下这个方法的调用入口:

Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
// 为什么要加这个判断?
// 若经过前置处理的返回结果不是null,那么我们就将其替代原有的bean,直接返回。以达到逻辑增强的插拔效果。
if (bean != null) {
	return bean;
}

来看下resolveBeforeInstantiation方法的源码:

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
		implements AutowireCapableBeanFactory {

	@Nullable
	protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
		Object bean = null;
		// 没被处理过的情况下
		if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
			if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
				Class<?> targetType = determineTargetType(beanName, mbd);
				if (targetType != null) {
					// 调用 InstantiationAwareBeanPostProcessor 的 postProcessBeforeInstantiation 方法
					bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
					if (bean != null) {
						// 调用 BeanPostProcessor 的 postProcessAfterInitialization方法
						bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
					}
				}
			}
			mbd.beforeInstantiationResolved = (bean != null);
		}
		return bean;
	}
}

备注:

  1. postProcessBeforeInstantiation方法:在Bean的自定义初始化方法之执行。
  2. postProcessAfterInitialization方法:在Bean的自定义初始化方法之执行。

紧接着就是最后一个步骤了:

Object beanInstance = doCreateBean(beanName, mbdToUse, args);

代码的展开在上文已经有提及,本章只围绕着三个重点来讲:

  • createBeanInstance()创建实例。
  • populateBean()属性注入。
  • initializeBean()初始化。

1.4.3 bean实例的创建

源码如下:

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
	// 1.根据Class属性来解析Class
	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());
	}
	// 2.一个bean的回调函数,用来代替工厂方法。 若不为空,那么调用回调函数并直接将结果返回。
	Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
	if (instanceSupplier != null) {
		return obtainFromSupplier(instanceSupplier, beanName);
	}
	// 3.若工厂方法不为空,那么使用工厂方法来进行初始化。
	// 若RootBeanDefinition中配置了factoryMethodName属性,说明配置文件中配置了factory-method的方法
	if (mbd.getFactoryMethodName() != null) {
		return instantiateUsingFactoryMethod(beanName, mbd, args);
	}

	boolean resolved = false;// 构造函数是否解析过
	boolean autowireNecessary = false;// 构造函数其中的参数是否解析过
	if (args == null) {
		// 由于一个类中可能有多种构造函数,每个构造函数有着不同的参数。因此需要锁定构造函数
		synchronized (mbd.constructorArgumentLock) {
			// resolvedConstructorOrFactoryMethod :一个用于缓存 已解析的构造函数或者工厂方法。
			// 因为构造函数的多样性,定位到一个准确的构造函数并进行实例化是一个耗时的过程,因此采用缓存来标记。
			if (mbd.resolvedConstructorOrFactoryMethod != null) {
				resolved = true;
				// constructorArgumentsResolved属性:标记这个构造函数参数已经解析过了
				autowireNecessary = mbd.constructorArgumentsResolved;
			}
		}
	}
	// 若已经解析过,那么使用解析好的构造函数
	if (resolved) {
		if (autowireNecessary) {
			return autowireConstructor(beanName, mbd, null, null);
		}else {
			// 使用默认的构造函数
			return instantiateBean(beanName, mbd);
		}
	}

	// 根据参数来解析构造函数
	Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
	if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
			mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
		// 构造函数注入
		return autowireConstructor(beanName, mbd, ctors, args);
	}

	// 构造函数注入
	ctors = mbd.getPreferredConstructors();
	if (ctors != null) {
		return autowireConstructor(beanName, mbd, ctors, null);
	}

	// 若以上都不命中,则使用默认构造来创建
	return instantiateBean(beanName, mbd);
}

总结下就是:

  1. 通过反射来解析Class对象并校验。
  2. 若配置了回调函数,那么直接调用并返回。
  3. 若配置了factory-method,则调用并返回。
  4. 否则,就调用其构造函数进行初始化(带参数),同时用了缓存进行优化
  5. 若都没有,则调用默认的构造函数并返回。

同时我们可以注意到,代码中除了第二、第三点这样的特殊情况。对于实例的创建分为了两大类:

  • 构造函数注入(带构造函数参数):autowireConstructor
  • 通用实例化(无参构造):instantiateBean
(1) autowireConstructor解析

源码如下:

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
	protected BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd, @Nullable Constructor<?>[] ctors, @Nullable Object[] explicitArgs) {
		return new ConstructorResolver(this).autowireConstructor(beanName, mbd, ctors, explicitArgs);
	}
	↓↓↓↓↓↓
	public BeanWrapper autowireConstructor(String beanName, RootBeanDefinition mbd,
			@Nullable Constructor<?>[] chosenCtors, @Nullable Object[] explicitArgs) {

		BeanWrapperImpl bw = new BeanWrapperImpl();
		this.beanFactory.initBeanWrapper(bw);

		Constructor<?> constructorToUse = null;
		ArgumentsHolder argsHolderToUse = null;
		Object[] argsToUse = null;
		// explicitArgs由调用getBean方法的时候传入
		if (explicitArgs != null) {
			argsToUse = explicitArgs;
		}
		else {
			// 若getBean调用的时候,并没有传入相关的参数,那么会尝试去配置文件中寻找
			Object[] argsToResolve = null;
			// 同理,这里用了缓存去存放解析好的构造函数参数
			synchronized (mbd.constructorArgumentLock) {
				constructorToUse = (Constructor<?>) mbd.resolvedConstructorOrFactoryMethod;
				if (constructorToUse != null && mbd.constructorArgumentsResolved) {
					// Found a cached constructor...
					argsToUse = mbd.resolvedConstructorArguments;
					if (argsToUse == null) {
						argsToResolve = mbd.preparedConstructorArguments;
					}
				}
			}
			/**
			 * 若缓存中存在,那么对参数值进行转换。
			 * 例如构造函数A(int a,int b),而配置文件中配的是字符串("1","2")
			 * 那么该方法调用后,结果转化为(1,2)
			 */
			if (argsToResolve != null) {
				argsToUse = resolvePreparedArguments(beanName, mbd, bw, constructorToUse, argsToResolve);
			}
		}
		// 若缓存中没有
		if (constructorToUse == null || argsToUse == null) {
			// 若getBean的时候传了构造相关参数,则使用它
			Constructor<?>[] candidates = chosenCtors;
			// 若没有传入,则通过反射来获取相关的构造器
			if (candidates == null) {
				Class<?> beanClass = mbd.getBeanClass();
				try {
					candidates = (mbd.isNonPublicAccessAllowed() ?
							beanClass.getDeclaredConstructors() : beanClass.getConstructors());
				}
				// catch...
			}
			// 调用无参构造
			if (candidates.length == 1 && explicitArgs == null && !mbd.hasConstructorArgumentValues()) {
				Constructor<?> uniqueCandidate = candidates[0];
				if (uniqueCandidate.getParameterCount() == 0) {
					synchronized (mbd.constructorArgumentLock) {
						mbd.resolvedConstructorOrFactoryMethod = uniqueCandidate;
						mbd.constructorArgumentsResolved = true;
						mbd.resolvedConstructorArguments = EMPTY_ARGS;
					}
					bw.setBeanInstance(instantiate(beanName, mbd, uniqueCandidate, EMPTY_ARGS));
					return bw;
				}
			}

			// 是否需要解析构造函数
			boolean autowiring = (chosenCtors != null ||
					mbd.getResolvedAutowireMode() == AutowireCapableBeanFactory.AUTOWIRE_CONSTRUCTOR);
			ConstructorArgumentValues resolvedValues = null;

			int minNrOfArgs;
			if (explicitArgs != null) {
				minNrOfArgs = explicitArgs.length;
			}
			else {
				// 提取配置文件中配置的构造函数参数
				ConstructorArgumentValues cargs = mbd.getConstructorArgumentValues();
				// 创建一个用于装在 cargs 的一个对象
				resolvedValues = new ConstructorArgumentValues();
				// 能够解析到的参数个数
				minNrOfArgs = resolveConstructorArguments(beanName, mbd, bw, cargs, resolvedValues);
			}
			// 对给定的构造函数进行排序,public类型的构造函数优先。非public的构造则根据参数个数降序排序
			AutowireUtils.sortConstructors(candidates);
			int minTypeDiffWeight = Integer.MAX_VALUE;
			Set<Constructor<?>> ambiguousConstructors = null;
			Deque<UnsatisfiedDependencyException> causes = null;

			for (Constructor<?> candidate : candidates) {
				// 每个构造函数对应的参数个数
				int parameterCount = candidate.getParameterCount();
				// 若缓存中存在已经解析好的构造函数,同时 解析好的参数的个数(不重复) >当前构造函数所需的参数个数
				// 说明当前构造函数无需继续解析,跳出循环即可
				if (constructorToUse != null && argsToUse != null && argsToUse.length > parameterCount) {
					break;
				}
				// 个数不相等,跳过本次循环
				if (parameterCount < minNrOfArgs) {
					continue;
				}

				ArgumentsHolder argsHolder;
				Class<?>[] paramTypes = candidate.getParameterTypes();
				// resolvedValues存储了上文读取XML配置的一些参数配置
				if (resolvedValues != null) {
					try {
						// 注释上获取参数名称
						String[] paramNames = ConstructorPropertiesChecker.evaluate(candidate, parameterCount);
						if (paramNames == null) {
							// 获取参数名称处理器。
							ParameterNameDiscoverer pnd = this.beanFactory.getParameterNameDiscoverer();
							if (pnd != null) {
								// 获取指定构造函数的参数名称
								paramNames = pnd.getParameterNames(candidate);
							}
						}
						// 根据名称和数据类型创建参数的持有者。
						argsHolder = createArgumentArray(beanName, mbd, resolvedValues, bw, paramTypes, paramNames,
								getUserDeclaredConstructor(candidate), autowiring, candidates.length == 1);
					}
					// catch...
				}
				else {
					// Explicit arguments given -> arguments length must match exactly.
					if (parameterCount != explicitArgs.length) {
						continue;
					}
					// 若构造函数没有参数
					argsHolder = new ArgumentsHolder(explicitArgs);
				}
				// 检验是否存在具有不确定性的构造函数。例如不同构造函数的参数为父子关系。
				int typeDiffWeight = (mbd.isLenientConstructorResolution() ?
						argsHolder.getTypeDifferenceWeight(paramTypes) : argsHolder.getAssignabilityWeight(paramTypes));
				// 若满足,说明当前的构造函数是最匹配的一个,那么它将作为最终的构造函数来调用。
				if (typeDiffWeight < minTypeDiffWeight) {
					constructorToUse = candidate;
					argsHolderToUse = argsHolder;
					argsToUse = argsHolder.arguments;
					minTypeDiffWeight = typeDiffWeight;
					ambiguousConstructors = null;
				}
				else if (constructorToUse != null && typeDiffWeight == minTypeDiffWeight) {
					if (ambiguousConstructors == null) {
						ambiguousConstructors = new LinkedHashSet<>();
						ambiguousConstructors.add(constructorToUse);
					}
					ambiguousConstructors.add(candidate);
				}
			}

			if (constructorToUse == null) {
				if (causes != null) {
					UnsatisfiedDependencyException ex = causes.removeLast();
					for (Exception cause : causes) {
						this.beanFactory.onSuppressedException(cause);
					}
					throw ex;
				}
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Could not resolve matching constructor on bean class [" + mbd.getBeanClassName() + "] " +
						"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)");
			}
			else if (ambiguousConstructors != null && !mbd.isLenientConstructorResolution()) {
				throw new BeanCreationException(mbd.getResourceDescription(), beanName,
						"Ambiguous constructor matches found on bean class [" + mbd.getBeanClassName() + "] " +
						"(hint: specify index/type/name arguments for simple parameters to avoid type ambiguities): " +
						ambiguousConstructors);
			}
			// 到这里,构造函数已经解析完成了,同时将其加入到缓存中。
			if (explicitArgs == null && argsHolderToUse != null) {
				argsHolderToUse.storeCache(mbd, constructorToUse);
			}
		}

		Assert.state(argsToUse != null, "Unresolved constructor arguments");
		// 将构建的实例加入到BeanWrapper中
		bw.setBeanInstance(instantiate(beanName, mbd, constructorToUse, argsToUse));
		return bw;
	}
}

代码有点长,让我们来做个概括:

1.确定构造函数参数explicitArgs

  • 先看调用getBean()的时候是否传了参数,传了则使用它。
  • 若未传参数,看缓存中是否存在已经解析好的,若有,则使用它。
  • 若前两者都没有,则去XML配置文件中读取。

2.确定构造函数。根据构造函数的参数来匹配对应的构造函数。匹配的过程中会对构造函数进行排序:

  • public修饰的在前。
  • 其余的根据参数个数进行排序。

3.转换对应的参数类型,确保类型正确。

4.检验构造函数的不确定性。

5.根据实例化的策略和最终确定的构造函数(包括参数)进行实例化Bean

(2) instantiateBean解析
protected BeanWrapper instantiateBean(String beanName, RootBeanDefinition mbd) {
	try {
		Object beanInstance;
		if (System.getSecurityManager() != null) {
			// 根据实例化策略直接进行实例化
			beanInstance = AccessController.doPrivileged(
					(PrivilegedAction<Object>) () -> getInstantiationStrategy().instantiate(mbd, beanName, this),
					getAccessControlContext());
		}
		else {
			beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, this);
		}
		// 将实例化完成的对象封装为BeanWrapper
		BeanWrapper bw = new BeanWrapperImpl(beanInstance);
		// 初始化wrapper
		initBeanWrapper(bw);
		return bw;
	}
	// ..catch
}

我们可以发现,两种构造解析,最终对实例进行实例化的时候,都会调用instantiate()方法。我们来看下这个方法做了什么事情:

public class SimpleInstantiationStrategy implements InstantiationStrategy {
	@Override
	public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
		// 如果有 需要覆盖 或者 动态替换的方法 。即lookup和replaced方法
		// 那么需要使用cglib进行动态代理,因为其可以再创建代理的同时将动态方法插入类中。
		// 若没有,则通过 反射 进行实例化就可以。
		if (!bd.hasMethodOverrides()) {
			Constructor<?> constructorToUse;
			synchronized (bd.constructorArgumentLock) {
				constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
				if (constructorToUse == null) {
					final Class<?> clazz = bd.getBeanClass();
					if (clazz.isInterface()) {
						throw new BeanInstantiationException(clazz, "Specified class is an interface");
					}
					try {
						if (System.getSecurityManager() != null) {
							constructorToUse = AccessController.doPrivileged(
									(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
						}
						else {
							constructorToUse = clazz.getDeclaredConstructor();
						}
						bd.resolvedConstructorOrFactoryMethod = constructorToUse;
					}
					// ..catch
				}
			}
			return BeanUtils.instantiateClass(constructorToUse);
		}
		else {
			// cglib动态代理
			return instantiateWithMethodInjection(bd, beanName, owner);
		}
	}
}

总结下就是实例化分为两种情况:

  1. 正常通过反射进行实例创建。
  2. 若有 需要覆盖 或者 动态替换的方法 。即lookupreplaced方法。则进行cglib动态代理。

1.4.4 属性注入

接下来我们来讲下创建Bean过程中的第二个重要环节,属性注入。其入口为populateBean()函数:

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
		implements AutowireCapableBeanFactory {
	protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
		// 若beanWrapper为null,都不需要属性注入了。若XML配置了相关属性,则需要抛异常。因为不能给一个null对象进行属性注入。
		if (bw == null) {
			if (mbd.hasPropertyValues()) {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
			} else {
				return;
			}
		}
		// 给InstantiationAwareBeanPostProcessor最后一次机会,在设置属性之前来改变bean
		if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
			for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
				if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
					return;
				}
			}
		}

		PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

		int resolvedAutowireMode = mbd.getResolvedAutowireMode();
		// Spring的自动注入有两种方式,根据type。根据name
		if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
			MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
			// 根据名称自动注入
			if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
				autowireByName(beanName, mbd, bw, newPvs);
			}
			// 根据type自动注入
			if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
				autowireByType(beanName, mbd, bw, newPvs);
			}
			pvs = newPvs;
		}
		// 后处理器是否已经初始化
		boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
		// 是否需要依赖检查
		boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

		PropertyDescriptor[] filteredPds = null;
		if (hasInstAwareBpps) {
			if (pvs == null) {
				pvs = mbd.getPropertyValues();
			}
			for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
				PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
				if (pvsToUse == null) {
					if (filteredPds == null) {
						filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
					}
					// 对所有属性进行后处理
					pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
					if (pvsToUse == null) {
						return;
					}
				}
				pvs = pvsToUse;
			}
		}
		// 依赖检查
		if (needsDepCheck) {
			if (filteredPds == null) {
				filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
			}
			checkDependencies(beanName, mbd, filteredPds, pvs);
		}

		if (pvs != null) {
			// 将解析得到的属性封装到bean中
			applyPropertyValues(beanName, mbd, bw, pvs);
		}
	}
}

对上述流程总结下就是:

  1. 判断是否需要对Bean进行相关的填充。
  2. 根据Name/Type提取依赖的bean,并存储于PropertyValues实例中。
  3. 在填充属性前,通过InstantiationAwareBeanPostProcessor处理器对各个属性再进行处理。
  4. 将最终填充好的属性放到BeanWrapper中。

我们需要关注的是依赖的提取和处理操作,使用过@Autowired@Resource注解的人我们都知道,一个是根据类型来属性注入,一个是根据名称来属性注入。那么碰巧的是,正好可以在这里对其原理做一个大概的了解。

(1) 根据Name自动注入
autowireByName(beanName, mbd, bw, newPvs);
↓↓↓↓↓↓
protected void autowireByName(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
	// 寻找bw中存储的 需要依赖注入的属性
	String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
	for (String propertyName : propertyNames) {
		if (containsBean(propertyName)) {
			// 递归初始化bean,根据bean的名称
			Object bean = getBean(propertyName);
			pvs.add(propertyName, bean);
			// 注册依赖
			registerDependentBean(propertyName, beanName);
			if (logger.isTraceEnabled()) {
				logger.trace("Added autowiring by name from bean name '" + beanName +
						"' via property '" + propertyName + "' to bean named '" + propertyName + "'");
			}
		}
		else {
			// log..
		}
	}
}

共三步:

  1. 找到需要依赖的属性。
  2. 递归根据名称来调用getBean(name)方法进行初始化。
  3. 注册依赖(实际就是将对应的依赖名称保存到Set集合中)。

由于getBean方法又是我们整篇文章要讲述的,因此我们只需要知道根据名称自动注入的过程中,存在getBean方法的递归调用即可。

(2) 根据Type自动注入
autowireByType(beanName, mbd, bw, newPvs);
↓↓↓↓↓↓
protected void autowireByType(String beanName, AbstractBeanDefinition mbd, BeanWrapper bw, MutablePropertyValues pvs) {
	TypeConverter converter = getCustomTypeConverter();
	if (converter == null) {
		converter = bw;
	}

	Set<String> autowiredBeanNames = new LinkedHashSet<>(4);
	// 1.同样,寻找bw需要依赖注入的属性
	String[] propertyNames = unsatisfiedNonSimpleProperties(mbd, bw);
	for (String propertyName : propertyNames) {
		try {
			PropertyDescriptor pd = bw.getPropertyDescriptor(propertyName);
			if (Object.class != pd.getPropertyType()) {
				// 探测指定属性的set方法
				MethodParameter methodParam = BeanUtils.getWriteMethodParameter(pd);
				boolean eager = !(bw.getWrappedInstance() instanceof PriorityOrdered);
				DependencyDescriptor desc = new AutowireByTypeDependencyDescriptor(methodParam, eager);
				/**
				 * 解析beanName匹配的值,并存储在 autowiredBeanNames 集合中。当属性存在多个bean的时候。例如
				 *        @Autowired
				 *        private List<A> list;
				 * 那么此时会将所有匹配A类的bean注入进来
				 */
				Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
				if (autowiredArgument != null) {
					pvs.add(propertyName, autowiredArgument);
				}
				// 递归注册依赖
				for (String autowiredBeanName : autowiredBeanNames) {
					registerDependentBean(autowiredBeanName, beanName);
					// log..
				}
				autowiredBeanNames.clear();
			}
		} catch (BeansException ex) {
			throw new UnsatisfiedDependencyException(mbd.getResourceDescription(), beanName, propertyName, ex);
		}
	}
}

概括下就是:

  1. 寻找bw中需要依赖注入的属性。
  2. 遍历这些属性,寻找匹配的bean
  3. 递归注册依赖。

和通过Name注入的方式不同的是第二步,我们来看下寻找类型匹配的方法做了什么操作:

Object autowiredArgument = resolveDependency(desc, beanName, autowiredBeanNames, converter);
↓↓↓↓↓↓
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
		implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
	public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

		descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
		// 若依赖的bean是Optional类型的
		if (Optional.class == descriptor.getDependencyType()) {
			return createOptionalDependency(descriptor, requestingBeanName);
		}
		// 若依赖的bean是ObjectFactory类型的
		else if (ObjectFactory.class == descriptor.getDependencyType() ||
				ObjectProvider.class == descriptor.getDependencyType()) {
			return new DependencyObjectProvider(descriptor, requestingBeanName);
		}
		else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
			return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
		}
		// 通用处理逻辑
		else {
			Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
					descriptor, requestingBeanName);
			if (result == null) {
				result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
			}
			return result;
		}
	}
}

我们来看下通用的处理逻辑doResolveDependency

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
		implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
	public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
			@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
		// 设置当前的 descriptor,其中存储了方法参数等信息。作为当前的切入点。
		InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
		try {
			Object shortcut = descriptor.resolveShortcut(this);
			if (shortcut != null) {
				return shortcut;
			}
			// 从 descriptor 中获取属性类型
			Class<?> type = descriptor.getDependencyType();
			// 支持注解@Value
			Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
			if (value != null) {
				if (value instanceof String) {
					String strVal = resolveEmbeddedValue((String) value);
					BeanDefinition bd = (beanName != null && containsBean(beanName) ?
							getMergedBeanDefinition(beanName) : null);
					value = evaluateBeanDefinitionString(strVal, bd);
				}
				TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
				try {
					return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
				}
				catch (UnsupportedOperationException ex) {
					// A custom TypeConverter which does not support TypeDescriptor resolution...
					return (descriptor.getField() != null ?
							converter.convertIfNecessary(value, type, descriptor.getField()) :
							converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
				}
			}
			// 处理一些集合的注入
			Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
			if (multipleBeans != null) {
				return multipleBeans;
			}
			// 查找符合注入类型的bean
			Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
			if (matchingBeans.isEmpty()) {
				// 当符合条件的bean是空的,但是注入的属性又是存在的,那么此时抛异常
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				return null;
			}

			String autowiredBeanName;
			Object instanceCandidate;
			// 若查找到多个符合注入类型的bean
			if (matchingBeans.size() > 1) {
				// 过滤,找到最优的beanName
				autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
				if (autowiredBeanName == null) {
					// 同样,找不到最优的beanName,但是注入的属性又是必须的,同样抛异常
					// 或者注入的属性非必须,未过滤前就有多个注入类型的bean。但是注入的属性不是集合,那么同样抛异常。
					// 毕竟除集合外,怎么会有一个属性对应多个注入的bean呢?
					if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
						return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
					}
					else {
						return null;
					}
				}
				// 根据beanName获取的最优解,来创建属性实例的一个候选者instanceCandidate
				instanceCandidate = matchingBeans.get(autowiredBeanName);
			}
			else {
				// 若存在了一对一的情况,那么也不需要去寻找匹配了,直接就用当前的就可以了。
				Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
				autowiredBeanName = entry.getKey();
				instanceCandidate = entry.getValue();
			}

			if (autowiredBeanNames != null) {
				autowiredBeanNames.add(autowiredBeanName);
			}
			if (instanceCandidate instanceof Class) {
				// 调用了getBean,进行初始化
				instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
			}
			Object result = instanceCandidate;
			if (result instanceof NullBean) {
				if (isRequired(descriptor)) {
					raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
				}
				result = null;
			}
			if (!ClassUtils.isAssignableValue(type, result)) {
				throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
			}
			return result;
		}
		finally {
			ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
		}
	}
}

概括下:

  1. @Value注解、集合等类型的bean做特殊处理。
  2. findAutowireCandidates查找符合注入类型的bean
  3. 通过determineAutowireCandidate过滤, 找到最优的bean的候选者。
  4. 对候选者进行初始化。

我们来大概了解下上述的两个方法:

protected Map<String, Object> findAutowireCandidates(
			@Nullable String beanName, Class<?> requiredType, DependencyDescriptor descriptor) {
	// 获取给定类型的所有beanName,包括在父工厂中定义的beanName
	String[] candidateNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
			this, requiredType, true, descriptor.isEager());
	Map<String, Object> result = CollectionUtils.newLinkedHashMap(candidateNames.length);
	// 先尝试从缓存中寻找。这里的 resolvableDependencies 是已经解析过的缓存,
	for (Map.Entry<Class<?>, Object> classObjectEntry : this.resolvableDependencies.entrySet()) {
		Class<?> autowiringType = classObjectEntry.getKey();
		if (autowiringType.isAssignableFrom(requiredType)) {
			Object autowiringValue = classObjectEntry.getValue();
			autowiringValue = AutowireUtils.resolveAutowiringValue(autowiringValue, requiredType);
			if (requiredType.isInstance(autowiringValue)) {
				result.put(ObjectUtils.identityToString(autowiringValue), autowiringValue);
				break;
			}
		}
	}
	/**
	 * isSelfReference:判断是否是自引用。即注入的属性是类本身
	 * isAutowireCandidate:判断是否有资格作为依赖注入的候选者
	 * @Bean(autowireCandidate = false)注解的bean就没有资格
	 */
	for (String candidate : candidateNames) {
		if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, descriptor)) {
			addCandidateEntry(result, candidate, descriptor, requiredType);
		}
	}
	// 没有符合注入属性类型的beanName
	if (result.isEmpty()) {
		// 注入的属性是否是bean的集合类型
		boolean multiple = indicatesMultipleBeans(requiredType);
		// 使用 备用的依赖描述器 再去获取一遍符合注入属性类型的beanName
		DependencyDescriptor fallbackDescriptor = descriptor.forFallbackMatch();
		for (String candidate : candidateNames) {
			if (!isSelfReference(beanName, candidate) && isAutowireCandidate(candidate, fallbackDescriptor) &&
					(!multiple || getAutowireCandidateResolver().hasQualifier(descriptor))) {
				addCandidateEntry(result, candidate, descriptor, requiredType);
			}
		}
		// 若此时发现还是没有找到符合类型的beanName并且不是集合类型,考虑到自引用的存在
		if (result.isEmpty() && !multiple) {
			for (String candidate : candidateNames) {
				if (isSelfReference(beanName, candidate) &&
						(!(descriptor instanceof MultiElementDescriptor) || !beanName.equals(candidate)) &&
						isAutowireCandidate(candidate, fallbackDescriptor)) {
					addCandidateEntry(result, candidate, descriptor, requiredType);
				}
			}
		}
	}
	return result;
}

以及determineAutowireCandidate过滤:

protected String determineAutowireCandidate(Map<String, Object> candidates, DependencyDescriptor descriptor) {
	// 1.获取代注入的属性类型
	Class<?> requiredType = descriptor.getDependencyType();
	// 2.匹配候选bean中是否存在@Primary
	String primaryCandidate = determinePrimaryCandidate(candidates, requiredType);
	// 3.若匹配成功直接返回
	if (primaryCandidate != null) {
		return primaryCandidate;
	}
	// 4.匹配失败,则通过@Priority进行优先级匹配,值越小,优先级越高
	String priorityCandidate = determineHighestPriorityCandidate(candidates, requiredType);
	if (priorityCandidate != null) {
		return priorityCandidate;
	}
	// 5.若前两者都匹配失败,则匹配beanName是否一致
	for (Map.Entry<String, Object> entry : candidates.entrySet()) {
		String candidateName = entry.getKey();
		Object beanInstance = entry.getValue();
		if ((beanInstance != null && this.resolvableDependencies.containsValue(beanInstance)) ||
				matchesBeanName(candidateName, descriptor.getDependencyName())) {
			return candidateName;
		}
	}
	// 6.否则匹配失败,返回null
	return null;
}

总结下就是:
第一点:如何查找符合注入条件的bean

  1. 先从已经解析好的缓存中寻找是否存在。
  2. 否则检查自引用和排除不符合的bean。过滤@Qualifier。以及过滤@Bean(autowireCandidate = false)注解的bean
  3. 将符合条件的封装起来,放到集合matchingBeans中。

第二点:如何在集合matchingBeans中匹配到最优解?

  1. 匹配@Primary
  2. 匹配@Priority进行优先级匹配,值越小,优先级越高
  3. 匹配beanName是否一致。

那么这些最优解得到后,完成初始化的工作,那么属性注入的工作也就完成了。最后一步,我们来看下初始化的过程。

1.4.5 初始化

配置bean的时候,有一个init-method属性,这个属性的作用是bean在实例化前调用其指定的方法来完成初始化工作。

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
	if (System.getSecurityManager() != null) {
		AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
			// 1.1执行aware方法
			invokeAwareMethods(beanName, bean);
			return null;
		}, getAccessControlContext());
	} else {
		// 1.2对特殊的bean进行处理,例如:Aware、BeanClassLoaderAware、BeanFactoryAware
		invokeAwareMethods(beanName, bean);
	}

	Object wrappedBean = bean;
	if (mbd == null || !mbd.isSynthetic()) {
		// 2.应用后处理
		wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
	}

	try {
		// 3.执行用户自定义的init方法
		invokeInitMethods(beanName, wrappedBean, mbd);
	} 
	// ..catch
	if (mbd == null || !mbd.isSynthetic()) {
		// 应用后处理
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}

	return wrappedBean;
}
(1) Aware的使用

案例如下:
在这里插入图片描述
User类:

public class User {
	void getName(){
		System.out.println("User");
	}
}

UserAware类:需要实现接口BeanFactoryAware

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;

public class UserAware implements BeanFactoryAware {
	private BeanFactory beanFactory;
	@Override
	public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
		this.beanFactory=beanFactory;
	}

	void testAware(){
		User user = (User) beanFactory.getBean("user");
		user.getName();
	}
}

Test类:

public class Test {
	public static void main(String[] args) {
		BeanFactory factory = new DefaultListableBeanFactory();
		XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader((BeanDefinitionRegistry) factory);

		ClassPathResource resource = new ClassPathResource("/aware/test.xml");
		reader.loadBeanDefinitions(resource);

		UserAware user = (UserAware) factory.getBean("userAware");
		user.testAware();
	}
}

test.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	   xsi:schemaLocation="
   	http://www.springframework.org/schema/beans
   	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
	<bean id="userAware" class="com.mytest.aware.UserAware">
	</bean>

	<bean id="user" class="com.mytest.aware.User">
	</bean>
</beans>

结果如下:
在这里插入图片描述
什么意思呢?就是说:

  1. Spring加载了一些 实现了Aware接口的bean 后,可以取得一些相对应的资源。
  2. 例如实现BeanFactoryAware接口,那么在初始化后,Spring容器会注入BeanFactory的实例。
  3. 因此testAware方法中,通过beanFactory实例调用getBean是可行的。
(2) 处理器的使用

初始化源码中,我们可以发现wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);这段代码执行了两遍,我们来看下他干了什么事情:

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException {
	// 代码很简单,递归地调用BeanPostProcessor实现类的postProcessBeforeInitialization方法而已。
	// 并将其返回结果作为替代来返回。	
	Object result = existingBean;
	for (BeanPostProcessor processor : getBeanPostProcessors()) {
		Object current = processor.postProcessBeforeInitialization(result, beanName);
		if (current == null) {
			return result;
		}
		result = current;
	}
	return result;
}

而至于BeanPostProcessor处理器,本文就不多展开啦,无非就是在Spring调用自定义的初始化方法的前后时机允许通过处理器来调用指定的逻辑,实现插拔。

  • 调用自定义初始化方法前:BeanPostProcessor.postProcessBeforeInitialization()
  • 调用自定义初始化方法后:BeanPostProcessor.postProcessAfterInitialization()
(3) 自定义init方法调用

调用入口为

invokeInitMethods(beanName, wrappedBean, mbd);
↓↓↓↓↓↓
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable {
	// 1.检查是否为InitializingBean,是则调用afterPropertiesSet方法
	// 因为Bean可能实现了InitializingBean接口,并且重写了afterPropertiesSet方法。
	boolean isInitializingBean = (bean instanceof InitializingBean);
	if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
		if (logger.isTraceEnabled()) {
			logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
		}
		if (System.getSecurityManager() != null) {
			try {
				AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
					((InitializingBean) bean).afterPropertiesSet();
					return null;
				}, getAccessControlContext());
			} 
			// ..catch
		} 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)) {
			// 2.调用用户指定的自定义初始化方法。
			invokeCustomInitMethod(beanName, bean, mbd);
		}
	}
}

总结:

  1. 初始化方法中我们可以发现,主要调用了两个方法(注意顺序)
  2. Bean实现了InitializingBean接口,那么调用其afterPropertiesSet方法。
  3. 最后调用自定义的init-method方法。

二. 大总结(带流程图)☆

Bean的加载的流程如下getBean()开始:

1.根据beanName尝试去缓存中加载。

  • 三级缓存的目的:在AOP调用的时候解决循环依赖问题。存放的是可以生成代理对象或者本身的工厂方法。

2.调用getObjectForBeanInstance方法检测bean的正确性。主要用于检测当前bean是否是FactoryBean类型的bean 。若是FactoryBean类型,则需要调用其getObject方法来返回对象。


3.开始创建Bean,调用createBean方法分为三大步骤:

创建实例:
createBeanInstance(),返回BeanWrapper对象。实例化的方式:

  1. 若配置了回调函数,那么直接调用并返回。
  2. 若配置了factory-method,则调用并返回。
  3. 否则,就调用其构造函数进行初始化(带参数)

而构造函数初始化的过程:

  1. 确定构造函数参数explicitArgs
  2. 确定构造函数。
  3. 转换对应的参数类型,确保类型正确。以及检验构造函数的不确定性。
  4. 根据实例化的策略和最终确定的构造函数(包括参数)进行实例化Bean
  5. 若是无参构造,则通过反射来实例化对象。若有覆盖方法(lookupreplaced),则通过cglib动态代理。

属性注入:

1.根据Name自动注入:

  1. 找到需要依赖的属性。
  2. 递归根据名称来调用getBean(name)方法进行初始化。
  3. 注册依赖(实际就是将对应的依赖名称保存到Set集合中)。

2.根据Type自动注入:

  1. 寻找bw中需要依赖注入的属性。
  2. 遍历这些属性,寻找匹配的bean,其中的过程包括:查找、过滤

1.先从已经解析好的缓存中寻找是否存在。

2.否则检查自引用和排除不符合的bean。过滤@Qualifier。以及过滤@Bean(autowireCandidate = false)注解的bean
3.将符合条件的封装起来,放到集合matchingBeans中。
4.过滤操作则看是否配置了@Primary以及@Priority的大小。

  1. 递归注册依赖。

初始化:

  1. 若实现了xxxAware接口,则调用对应的方法。
  2. 若配置了BeanPostProcessor处理器,则在执行自定义初始化方法的前后执行对应的逻辑。
  3. 调用自定义的init方法(对应init-method属性)。

最后,我自己整理了下流程图:也希望大家能借此流程图加强对本文的理解。谢谢大家~
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring源码系列:Bean的加载 的相关文章

随机推荐

  • 使用 Builder 构建对象

    遇到多个构造器参数时 要考虑使用构建器 当遇到成员变量较多的类时 使用构造方法初始化对象会使得代码的可读性以及规范性变差 比如想知道某个参数的含义时必须要查看构造方法的定义源码 而且如果不消息颠倒了参数的顺序 编译器可能也不会报错 可以使用
  • 【Java集合 4】java character

    Java学习路线 搬砖工逆袭Java架构师 简介 Java领域优质创作者 CSDN哪吒公众号作者 Java架构师奋斗者 扫描主页左侧二维码 加入群聊 一起学习 一起进步 欢迎点赞 收藏 留言 目录 一 前言 二 ASCII控制字符 三 AS
  • Oracle数据库的启动

    lsnrctl start 启动监听 sqlplus nolog SQL gt conn as sysdba SQL gt startup 启动数据
  • 提高性能 MSSQL百万数据量 值得注意的30条优化技巧

    1 对查询进行优化 应尽量避免全表扫描 首先应考虑在 where 及 order by 涉及的列上建立索引 2 应尽量避免在 where 子句中对字段进行 null 值判断 否则将导致引擎放弃使用索引而进行全表扫描 如 select id
  • JSP动态网页开发技术

    一 学习目标 1 JSP概述 2 JSP指令 3 JSP 隐式对象 二 重点知识 1 JSP概述 JSP是什么 1 JSP全称Java Server Pages 是一种动态网页开发技术 它使用JSP标签在HTML网页中插入Java代码 标签
  • android控制电脑,安卓手机远程控制电脑教程详解

    当我们出门在外 没有电脑在身边 但又急需远程处理电脑上的事务时 怎么办呢 自从锤子出了手机远程协助后 没有锤子的人就急了 这里有个可以让所有Android手机和ios手机实现远程协助功能的小技巧 能 远程控制 远程控制 远程控制 windo
  • 初始gensim

    1 import jieba 2 import gensim 3 from gensim import corpora 4 from gensim import models 5 from gensim import similaritie
  • 复制CSDN文章,去掉代码前面行号的方法(及一些正则表达式小技巧)

    分享一些平时工作中常用的正则表达式小技巧 一 去掉代码前面行号的方法 idongchen modify 2018 12 5 csdn的markdown解析器蛮恶心的文章整体复制下来总有行号在前面 可以用正则找到这些行号给去掉就好 带点的 s
  • sqli-labs(29-31)

    序 这三关都是双服务器问题 网上很多教程都只考虑了apache 其实是php apache jsp tomcat 环境的搭建已经写在了另外一篇博客中 这里再推荐一下一个大牛写得很好的博客 里面把每关的原理都讲得很清晰 但是他里面关于本关的原
  • CV-对比学习-模型:MoCo/SimCLR/BYOL/SimSiam

    很多大佬认为 深度学习的本质就是做两件事情 Representation Learning 表示学习 和 Inductive Bias Learning 归纳偏好学习 在表示学习方面 如果直接对语义进行监督学习 虽然表现很好 但是它需要很多
  • lvs负载均衡、LVS集群部署

    四 LVS集群部署 lvs给nginx做负载均衡项目 218lvs DR 负载均衡器 yum y install ipvsadm 安装这个工具来管理lvs 设置VIP192 168 142 120 创建ipvsadm的文件用来存放lvs的规
  • c语言 如何创建txt文件,C++文本文件读写操作详解

    前面章节中 已经给大家介绍了文件流对象如何调用 open 方法打开文件 并且在读写 又称 I O 文件操作结束后 应调用 close 方法关闭先前打开的文件 那么 如何实现对文件内容的读写呢 接下来就对此问题做详细的讲解 在讲解具体读写文件
  • MySQL基础---连接查询(等值连接与非等值连接)

    多个表格查询 笛卡尔乘积现象 表1有m行 表2 有n行 结果有m n行 发生原因在于没有有效的连接条件 如何避免 添加有效的连接条件 方法 分类方法 按照年代分类 sql192标准和sql199标准 功能 内链接 等值连接 非等值连接 自连
  • 学习日记——物联网云平台(乐鑫云平台)

    物联网云平台了解 1 物联网云平台 接收设备上报的数据 向设备下发数据 对数据进行转发 分析 计算 显示 管理设备等 2 常见的物联网云平台一般有 私有物联网云平台 假设某瓜农 为瓜棚装上了物联网温湿计 温湿度数据通过网络发送某台主机 这台
  • redis--11.1--操作--对列表类型,集合类型,有序集合类型进行键排序

    redis 11 1 操作 对列表类型 集合类型 有序集合类型进行键排序 1 命令 sort key alpha BY pattern LIMIT offset count GET pattern GET pattern asc desc
  • javax.validation.constraints注解

    文章目录 概要 常用的注解 其他注解 小结 概要 javax validation constraints是Java Validation API中的一个包 它提供了一组注解 用于在Java代码中进行数据校验和验证 该包中定义了多个注解 用
  • LR(1)分析表-语法树-四元式

    这学期的编译原理终于学完了 不愧是号称最难的科目 要用C 从头到尾实现一下小型编译器 还真不容易啊 不过总算是做完了 首先上文法 这个文法是根据上一篇博客简化的 但还是有一点问题的 暂时发现有一个地方不符合LR1的规则 函数的返回类型如果是
  • 【ACOUG】Oracle技术爱好者的乐园

    ACOUG 的含义为 All China Oracle User Group http www acoug org 该组织是为了更好的提供一个Oracle用户的交流和活动平台 组织和发起一些公益性质的活动 这个组织是Eygle和Kamus发
  • 简单文件数据库-模拟图书馆管理系统-西安电子科技大学大一程序基础设计课程设计作业

    命令行参数如下 Libsim a u xxxx 第一个参数为可执行程序名称 第二个参数为用户身份 a表示管理员 u表示读者 第三个参数为用户名 问题分析 由于无法直接在文件中插入数据 不是简单覆盖 固采用将文件数据提取为链表的方法 对链表进
  • Spring源码系列:Bean的加载

    Spring源码系列 Bean的加载 前言 一 Bean的加载 1 1 FactoryBean的使用 案例 FactoryBean的使用和定义 1 2 缓存中获取单例Bean 1 2 1 Spring解决循环依赖的原理 1 以A类的角度来观