Spring Bean的无参创建过程

目录

概述

1. Spring Bean的无参创建过程

1.1 DEBUG追踪

1.1 总结

2. getBean方法的执行流程

2.1 总结


概述

        第一次阅读源码,主要查看的无参构造Bean对象的创建流程,采用debug的方式,会省略没有查看的源码,关注核心问题,其他的部分之后在继续阅读

1. Spring Bean的无参创建过程

实体类:

package com.righteye;

public class User {

    private String name;
    private Integer age;

    public User() {
        System.out.println("我是无参构造");
    }

    public User(String name, Integer age) {
        System.out.println("我是有参构造");
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

测试:

@Test
public void Test07() {
    String config = "applicationContext.xml";
    ApplicationContext ac = new ClassPathXmlApplicationContext(config);
    User user = (User) ac.getBean("user");
    System.out.println(user);
}

1.1 DEBUG追踪

执行后创建出对象

ApplicationContext ac = new ClassPathXmlApplicationContext(config);

 核心方法:refresh()

public ClassPathXmlApplicationContext(
		String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
		throws BeansException {

	super(parent);
	setConfigLocations(configLocations);
	if (refresh) {
		refresh();   // 执行后创建对象
	}
}

refresh() 方法很多,用来初始化spring等流程,,首先断点调试寻找创建Bean的那条语句

// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);   // 最终定位这句话

/**
* Finish the initialization of this context's bean factory,
* initializing all remaining singleton beans.   加载所有单例对象
*/

看注释可发现这个方法用来创建非懒加载的单例对象

调用方法:beanFactory.preInstantiateSingletons() 完成bean对象的创建
/**
 * Finish the initialization of this context's bean factory,
 * initializing all remaining singleton beans.
 */
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
	// 省略,不关注没有创建Bean的代码

	// Stop using the temporary ClassLoader for type matching.
	beanFactory.setTempClassLoader(null);

	// Allow for caching all bean definition metadata, not expecting further changes.
	beanFactory.freezeConfiguration();

	// Instantiate all remaining (non-lazy-init) singletons.
	beanFactory.preInstantiateSingletons();  // 该方法处完成Bean对象的创建
}

疑惑处:点进方法中会有这样一段代码:

获取的beanNames中包含所有xml中配置的信息,通过遍历这些bean信息然后最终调用getBean()方法获取对象

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)) {
			// 方便查看代码, 中间的代码没满足这回查看Bean创建的流程
		}
		else {
			getBean(beanName);  // 最终获取对象
		}
	}
}

进入getBean() 方法,然后发现他是BeanFacotry的重写方法 -》 疑惑:什么是BeanFactory

//---------------------------------------------------------------------
// Implementation of BeanFactory interface
//---------------------------------------------------------------------

@Override
public Object getBean(String name) throws BeansException {
	return doGetBean(name, null, null, false);  // 很明显,调用了这个方法
}

继续追踪: AbstractBeanFactory.java 类中的doGetBean()方法,这里我想要创建的bean对象是单例的,所以走了第一个分支,调用getSingleton()

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
	@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

	// 中间代码与我这次看的无关

		// Create bean instance.
		if (mbd.isSingleton()) {  // r如果对象是单例的
			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);
		}

		// 后面的代码处理不同的情况:prototype, 其他作用域
	}
}

 getSingleton()方法,通过给定的名字返回一个单例对象,如果这个对象没有注册执行注册操作

        阅读源码,发现在222行  singletonObject = singletonFactory.getObject(); 处实现了对象的创建并且对象的属性填充完毕。

this.singletonObjects: 单例缓存,首先通过beanName去这个缓存中获取对象
singletonObject = singletonFactory.getObject(); 缓存中为空,调用这个方法创建
if (newSingleton) {
    // Add the given singleton object to the singleton cache of this factory.
	addSingleton(beanName, singletonObject);
}

 完整代码:(源码很多不熟的,不敢瞎删,这次主要看三个关注点)

/**
 * Return the (raw) singleton object registered under the given name,
 * creating and registering a new one if none registered yet.
 * @param beanName the name of the bean
 * @param singletonFactory the ObjectFactory to lazily create the singleton
 * with, if necessary
 * @return the registered singleton object
 */
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
	Assert.notNull(beanName, "Bean name must not be null");
	synchronized (this.singletonObjects) {
		Object singletonObject = this.singletonObjects.get(beanName);  // 关注点
		if (singletonObject == null) {
			if (this.singletonsCurrentlyInDestruction) {
				throw new BeanCreationNotAllowedException(beanName,
						"Singleton bean creation not allowed while singletons of this factory are in destruction " +
						"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
			}
			if (logger.isDebugEnabled()) {
				logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
			}
			beforeSingletonCreation(beanName);
			boolean newSingleton = false;
			boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
			if (recordSuppressedExceptions) {
				this.suppressedExceptions = new LinkedHashSet<>();
			}
			try {
				singletonObject = singletonFactory.getObject();  // 关注这个地方
				newSingleton = true;
			}
			catch (IllegalStateException ex) {
				// Has the singleton object implicitly appeared in the meantime ->
				// if yes, proceed with it since the exception indicates that state.
				singletonObject = this.singletonObjects.get(beanName);
				if (singletonObject == null) {
					throw ex;
				}
			}
			catch (BeanCreationException ex) {
				if (recordSuppressedExceptions) {
					for (Exception suppressedException : this.suppressedExceptions) {
						ex.addRelatedCause(suppressedException);
					}
				}
				throw ex;
			}
			finally {
				if (recordSuppressedExceptions) {
					this.suppressedExceptions = null;
				}
				afterSingletonCreation(beanName);
			}
			if (newSingleton) {
				addSingleton(beanName, singletonObject);  // 关注这里
			}
		}
		return singletonObject;
	}
}

        当点击getObject()后,会跳转到之前getSingleton()方法中的匿名内部中,调用 createBean(beanName, mbd, args)

if (mbd.isSingleton()) {
	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);
}

        createBean(beanName, mbd, args)方法,实现了 AbstractBeanFactory 中的方法;看注释中有这样段话:是这个类的核心方法,创建bean的实例,为这个实例填充属性以及调用post-processors等;

        这里的post-processors是一种前置处理器,可以用来做一些增强操作

Central method of this class: creates a bean instance, populates the bean instance, applies post-processors, etc.

调用  Object beanInstance = doCreateBean(beanName, mbdToUse, args); 创建实例对象

上面的createBean()是一层跳板:真正创建对象的方法是 doCreateBean

方法签名:

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
// 实例对象,没有属性赋值操作
if (instanceWrapper == null) {
	instanceWrapper = createBeanInstance(beanName, mbd, args);
}

// 实例对象的属性赋值
populateBean(beanName, mbd, instanceWrapper);

1.1 总结

        简述无参构造函数下bean的创建流程:

         1. spring的加载过程会经过一个 refresh()方法,这个方法中会进行许多的操作,其中调用 finishBeanFactoryInitialization 完成非懒加载单例对象的实例化。

        2. 执行中,会存在一个BeanNames的集合,里面包含了需要创建的对象信息,然后执行相应的getBean()方法。

        3. 最终会调用 AbstractBeanFactory 的核心方法:doGetBean(), 完成实例化(createBeanInstance)属性的填充(populateBean)

        4.最后,在对象实例化后会放入成员变量中的  this.singletonObjects 是工厂中的一个单例缓存

        疑惑点:

        1. beanDefinitionNames 具体是什么,他如何创建出BeanNames集合

        2.beanFactory 的创建时机

        3. 有参构造的创建机制

        4.如果使用注解或其他配置方法,流程是否相同


2. getBean方法的执行流程

测试入口:

User user = (User) ac.getBean("user");
@Override
public Object getBean(String name) throws BeansException {
	assertBeanFactoryActive();
	return getBeanFactory().getBean(name);  // 实际调用成员变量beanFactory中的getBean
        // => this.beanFactory.getBean(name)
}

然后调用getBean(name)

@Override
public Object getBean(String name) throws BeansException {
	return doGetBean(name, null, null, false);  // 无参构造bean中的doGetBean
}

doGetBean()方法

// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);  // 首先无参构造已经实例化对象
if (sharedInstance != null && args == null) {
	
    // 打印日志的一些话,省略

    // 从单例池中通过beanName获取单例对象
	bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}

doGetBean方法声明:

doGetBean(final String name, 
			@Nullable final Class<T> requiredType,  // 要求取回的bean类型
			@Nullable final Object[] args, 
			boolean typeCheckOnly)

最后:

// Check if required type matches the type of the actual bean instance.
if (requiredType != null && !requiredType.isInstance(bean)) {}

2.1 总结

        getBean过程,主要通过beanName,调用beanFactory中的getBean方法;最后走到了doGetBean(), 然后从单例池中获取对象。

        doGetBean()中可以指定requiredType,要求获取bean的类型

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值