springboot 版本: 2.x
spring 版本 5.x
本篇文章主要分析下 Bean 属性的自动注入过程,并且会概要的分析下 Bean的实例化过程。
在上一篇文章中(https://www.jianshu.com/p/5d75c9bdf0c6)介绍了 springboot启动过程,其中也介绍了 bean的创建时机。其创建代码为 AbstractApplicationContext类refresh()方法中的如下代码:
Java bean 的初始化以及 field 的注入,都是通过这个方法完成的。
在这之前我们首先要熟悉几个类:
DefaultListableBeanFactory :默认的 bean工厂,看下这个类的继承结构:
AbstractAutowireCapableBeanFactory:负责创建 bean。
DefaultSingletonBeanRegistry:负责存储已经创建出来的 bean。
AutowiredAnnotationBeanPostProcessor: BeanPostProcessor的派生类, 会被 AbstractAutowireCapableBeanFactory调用并负责注入 bean 的属性。(BeanPostProcessor 的注册时机可以参考上一篇文章https://www.jianshu.com/p/5d75c9bdf0c6)
OK,一些必要的概念已经介绍完了,总结下DefaultListableBeanFactory本质上是一个容器,它会负责创建bean,存储 bean, 还会负责给 bean 注入属性。
接下来 , It's show time.
AbstractApplicationContext finishBeanFactoryInitialization() 方法:
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// 忽略代码。。。
// Instantiate all remaining (non-lazy-init) singletons.
//负责创建非懒加载的单例的bean
beanFactory.preInstantiateSingletons();
}
DefaultListableBeanFactory preInstantiateSingletons() 方法:
public void preInstantiateSingletons() throws BeansException {
// 忽略代码。。。
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
// 获取所有需要通过工程实例化的 bean 定义。
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//非抽象类, 并且是单例的, 并且是非懒加载的,才会创建
if (isFactoryBean(beanName)) {
//如果是 FactoryBean
//忽略代码。。。
}
else {
//非 FactoryBean, 也就是我们的 controller、service、dao 等等。。
//创建 bean
getBean(beanName);
}
}
}
// Trigger post-initialization callback for all applicable
// 忽略代码
}
进入 getBean 方法,一路跟踪下去
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
进入 AbstractBeanFactory doGetBean()方法
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
// 去缓存中获取 bean, 判断 bean 是否已经被创建
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
//忽略代码。。。。。
//如果已经创建了,则直接将sharedInstance转为 bean, 一般情况下(service, controller...)这里的 bean 和sharedInstance指向的是同一个对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
//如果此 bean 没有被创建,则执行下面常见 bean 的逻辑
// 忽略代码。。。
try {
// 忽略代码。。。 话说 spring 的设计很精妙,但是代码实现确实不算优雅,一个方法太长了。。。。
// Create bean instance.
if (mbd.isSingleton()) {
// 创建 bean, 这里用了 lamda表达式的匿名内部类的实现方式
// 这个匿名内部类是ObjectFactory, 只有一个方法,getObject(), 其实先就是下面的代码
// getSingleton()方法里面会调用 objectFactory.getObject()方法,实际执行的也就是createBean()方法。
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// 忽略代码。。。。
}
catch (BeansException ex) {
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
}
//忽略代码。。。
return (T) bean;
}
进入 createBean方法,即AbstractAutowireCapableBeanFactory类的 createBean() 方法
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
// 忽略一切。。。。
try {
//重点部分, 创建 bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("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);
}
}
进入 doCreateBean()方法,也在AbstractAutowireCapableBeanFactory中。
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
//创建bean, 也就是会调用 bean 的构造方法。 注意,这个方法虽然实例化了 bean,但是并没有给 bean 注入属性
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
//忽略代码。。。
// Allow post-processors to modify the merged bean definition.
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// 这里会缓存每个 bean的定义,也就是会初始化 bean 的元数据,其中包括 bean 有哪些需要注入的属性,
// 跟踪下去会发现其实调用的是AutowiredAnnotationBeanPostProcessor postProcessMergedBeanDefinition()方法
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
//忽略代码。。。
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 将实例化好的 bean,添加至缓存,也就是DefaultSingletonBeanRegistry singletonFactories属性中,
// singletonFactories是一个 map, key 是 beanName, value 是这个 bean 对应的工厂。
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
//此方法才是真正为 bean 注入属性的方法, 并且是递归注入,
//依赖的是AutowiredAnnotationBeanPostProcessor ,这个类也是 BeanPostProcessor 的派生类。但是经过适配的,主要功能就是执行 autowired。
//再注入属性实例的过程中,首先会去 DefaultSingletonBeanRegistry 缓存中判断实例是否初始化,如果已经初始化则直接赋值,否则执行上面一些列的 createBean, doCreateBean 方法实例化对象
//因为实例化和注入是互相不依赖的, 所以即使出现循环依赖的情况: A 依赖 B, B 也依赖 A, 也不会出现问题。
//循环依赖的初始化过程如下,1. 初始化 A ; 2. 将 A 加入缓存; 3. 给 A 注入 B 对象; 4. 发现 B 没有初始化, 初始化 B.
//5. 给 B 注入 A 对象,获取 A 时,发现A 再缓存中, 直接将 A 的实例赋值给B,支持 B 初始化且注入完成。 6. 将 B 的实例注入给 A。
//至此 完成 A B 的初始化和注入。
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);
}
}
// 忽略 忽略。。。。
return exposedObject;
}
最后我们来看下是如何找到需要注入的 Autowired 属性的,也就是
AutowiredAnnotationBeanPostProcessor postProcessMergedBeanDefinition()方法
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
InjectionMetadata metadata = findAutowiringMetadata(beanName, beanType, null);
metadata.checkConfigMembers(beanDefinition);
}
进入findAutowiringMetadata()方法
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
//首先判断缓存中是否存在
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
//如果不存在则新建元数据
metadata = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
进入buildAutowiringMetadata()方法
private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
LinkedList<InjectionMetadata.InjectedElement> elements = new LinkedList<>();
Class<?> targetClass = clazz;
do {
final LinkedList<InjectionMetadata.InjectedElement> currElements = new LinkedList<>();
//又是一个匿名内部类,不过首先是doWithLocalFields()方法通过反射机制找到所有的 field
ReflectionUtils.doWithLocalFields(targetClass, field -> {
//再找到被 Autowired注解注释的 field
AnnotationAttributes ann = findAutowiredAnnotation(field);
if (ann != null) {
if (Modifier.isStatic(field.getModifiers())) {
if (logger.isWarnEnabled()) {
logger.warn("Autowired annotation is not supported on static fields: " + field);
}
return;
}
boolean required = determineRequiredStatus(ann);
currElements.add(new AutowiredFieldElement(field, required));
}
});
//忽略代码。。。。
}
while (targetClass != null && targetClass != Object.class);
return new InjectionMetadata(clazz, elements);
}
进入 ReflectionUtils.doWithLocalFields();
public static void doWithLocalFields(Class<?> clazz, FieldCallback fc) {
for (Field field : getDeclaredFields(clazz)) {
try {
fc.doWith(field);
}
catch (IllegalAccessException ex) {
throw new IllegalStateException("Not allowed to access field '" + field.getName() + "': " + ex);
}
}
}
private static Field[] getDeclaredFields(Class<?> clazz) {
Assert.notNull(clazz, "Class must not be null");
Field[] result = declaredFieldsCache.get(clazz);
if (result == null) {
try {
//最终还是反射
result = clazz.getDeclaredFields();
declaredFieldsCache.put(clazz, (result.length == 0 ? NO_FIELDS : result));
}
catch (Throwable ex) {
throw new IllegalStateException("Failed to introspect Class [" + clazz.getName() +
"] from ClassLoader [" + clazz.getClassLoader() + "]", ex);
}
}
return result;
}
首先通过反射找到所有的 field,再区分出被 autowired注释的 field(本部分比较复杂,本文不做分析了),然后再通过反射给这些 field 的赋值(这部分也比较简单,就是 Invoke 一下 set方法)。bean 的注入就完成了。
还是有很多细节的部分没有分析到,但是面面俱到也不现实,重要是要知道其思想和大致原理。