目录
声明:文章内容仅代表个人对源码的理解和观点,可能存在理解错误的地方,欢迎留言探讨、指正。不喜勿喷,谢谢。
个人用的是 v5.2.4.RELEASE 版本的源码,因为几年前阅读时已经写了一些注释,所以没有拉取最新的源码,与最新的源码会存在一定的差异。
可以将Bean实例化看做是 Bean生命周期 的第一步,实例化Bean的主流程在AbstractAutowireCapableBeanFactory.createBeanInstance()
,该方法在AbstractAutowireCapableBeanFactory.doCreateBean()
中被调用。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);
}
/*
* 第一步:实例化Bean。
* 使用合适的实例化策略来实例化新的Bean:回调函数、工厂方法、带参的构造函数、无参构造函数。默认使用无参构造器实例化Bean。
* 构造函数自动注入发生在这一步
*/
if (instanceWrapper == null) {
// 为null,说明不是FactoryBean,那么调用工厂或者构造函数实例化Bean
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 省略掉大量代码,这些代码用于初始化Bean、属性赋值、循环依赖处理等
return exposedObject;
}
createBeanInstance
// AbstractAutowireCapableBeanFactory
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
// 从bean定义中解析出当前bean的class对象
Class<?> beanClass = resolveBeanClass(mbd, beanName);
// 检测类的访问权限。对于非public类,默认是允许访问的;若被设置为禁止访问非public的类,则这里会抛出异常
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());
}
/*
* 这是Spring5提供的一种替换工厂方法的方式,提供一个回调函数实例化Bean
* 自己创建BeanDefinition对象,然后注册到IoC容器中时,有可能使用到这种方式
*/
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
// 这里的代码很简单,就是执行回调函数获取Bean的实例
return obtainFromSupplier(instanceSupplier, beanName);
}
/*
* 判断是不是使用工厂实例化Bean,工厂方法名称不为空,即表示使用工厂方法进行实例化。
* 无论是静态工厂还是实例工厂,都是走这一步
* 通过Java配置类配置的Bean,实例化方式采用的是实例工厂方法,工厂实例就是Java配置类的代理对象
*/
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
boolean resolved = false; // 判断Bean定义中的构造函数或者工厂方法是否已被解析过
boolean autowireNecessary = false; // 有没有必要进行依赖注入
if (args == null) {
// getBean方法传入的参数为null
synchronized (mbd.constructorArgumentLock) {
/*
* 判断bean定义中的resolvedConstructorOrFactoryMethod属性是否有值
* 该属性用来缓存构造函数或者工厂方法,Bean在第一次被实例化的时候,会将解析得到的构造函数或者工厂方法赋值给这个属性
* 对于非单例模式的Bean来说,只需要解析一次Bean定义中的构造函数或工厂方法即可,后续可以直接从Bean定义中拿来使用
*/
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true; // 标记构造函数已被解析过了,原型等非单例模式的Bean,从第二次实例化开始就会进入这里
// 构造函数参数是否被解析过?当使用有参构造函数或者工厂方法实例化Bean时,该属性会被设置为true
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
// 已经解析过了,直接实例化Bean即可
if (autowireNecessary) {
// 使用有参构造函数实例化对象
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 使用无参构造函数实例化对象
return instantiateBean(beanName, mbd);
}
}
// Candidate constructors for autowiring?
/*
* 调用处理器(AutowiredAnnotationBeanPostProcessor),获取用于实例化Bean的构造函数
* 如果有多个构造函数,构造函数上都有@Autowired注解,无论required属性为何值,都会抛出异常,如果仅有一个构造函数有注解,则使用这个
* 如果只有xml配置,这里一般都是返回null
*/
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
/*
* 1. 上一行后置处理器解析出的构造函数不为null
* 2. bean定义中指定自动注入模式是构造器注入
* <bean id="order" class="org.xxx.Order" autowire="constructor"/> 这种方式定义的Bean即是构造函数自动注入
* 在构造函数上使用了@Autowire注解,也是构造函数自动注入
* 通过Java配置类定义的Bean,无论方法参数是否有值,都会被解析为构造函数自动注入
* 在Bean定义时,显式指定了构造函数参数(constructor-arg),则不是构造函数自动注入(注意,这里指的自动注入模式)
* 静态工厂和实例工厂定义的Bean,不是构造函数自动注入
* 3. bean定义中指定了构造函数,无论参数是通过名称、类型、下标配置,都是走这一步
* 4. 在外层,调用getBean方法传入的构造器函数参数类型不为null
* 四个条件有一个满足,就使用指定的构造函数进行实例化Bean
*/
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
// 使用指定的构造函数实例化对象,构造函数自动注入在这里完成
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
/*
* bean定义中的首选构造器
* 目前只有 GenericApplicationContext#ClassDerivedBeanDefinition类的这个方法有返回值,其它都是返回null
* 所以,Bean的实例化,基本不会走这一步
*/
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
// 实例化Bean
return autowireConstructor(beanName, mbd, ctors, null);
}
// No special handling: simply use no-arg constructor.
// 如果前面的条件都不匹配,则使用无参构造函数实例化对象
return instantiateBean(beanName, mbd);
}
从上面的源码可以看出,Spring提供了三种实例化Bean的方式:
- Supplier回调函数。这是从Spring5开始提供的一种实例化方式。通过工厂、构造函数实例化对象时,Spring使用的都是反射,而反射的性能相对较差。Supplier回调函数可以自定义实例化过程,无须通过反射调用,直接执行函数即可。
- 工厂方法。又分为静态工厂和实例工厂。
- 构造函数。有参构造函数、无参构造函数。当没有配置使用哪个构造函数时,默认使用无参构造函数实例化。
还有一种实例化方式是FactoryBean
,例如Spring Cloud中实例化FeignClient对象,使用的就是FeignClientFactoryBean
。这种方式的流程相对长一些、麻烦一些,这篇文章不做分析。
在Java配置类中配置的Bean,使用的是实例工厂实例化,实例工厂是Java配置类的代理对象,这个代理对象是在Spring解析Java配置类时创建的。
对于非单例模式的Bean,Spring做了一些性能优化,只有第一次实例化Bean时,才需要解析Bean定义的构造函数、工厂方法、参数值等,解析完成之后会将这些数据回写到Bean定义对象的对应属性。下次再创建时,直接从Bean定义中获取即可,无须再次解析。
实例化Bean的方式
回调函数实例化Bean
通过回调函数实例化Bean的代码非常简单,直接执行Bean定义中的回调函数,无须解析参数,也不需要进行反射调用。源码如下:
// AbstractAutowireCapableBeanFactory
protected BeanWrapper obtainFromSupplier(Supplier<?> instanceSupplier, String beanName) {
Object instance;
// 设置当前正在实例化的Bean的名称到ThreadLocal
String outerBean = this.currentlyCreatedBean.get();
this.currentlyCreatedBean.set(beanName);
try {
instance = instanceSupplier.get(); // 调用函数,拿到Bean实例
}
finally {
// 重置ThreadLocal
if (outerBean != null) {
this.currentlyCreatedBean.set(outerBean);
}
else {
this.currentlyCreatedBean.remove();
}
}
if (instance == null) {
instance = new NullBean();
}
// BeanWrapper接口提供了一些操作目标对象属性值的方法
BeanWrapper bw = new BeanWrapperImpl(instance);
initBeanWrapper(bw);
return bw;
}
配置回调函数的示例
提供一个简单的回调函数配置示例
public class MemberRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
RootBeanDefinition bd = new RootBeanDefinition();
bd.setBeanClass(Member.class);
bd.setInstanceSupplier(Member::new); // 这里注册一个回调函数
registry.registerBeanDefinition("member", bd);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
工厂方法实例化Bean
使用工厂方法实例化Bean的主要代码在ConstructorResolver.instantiateUsingFactoryMethod()
方法中,AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod()
方法仅仅只有一行代码。具体源码如下:
// AbstractAutowireCapableBeanFactory
protected BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
return new ConstructorResolver(this).instantiateUsingFactoryMethod(beanName, mbd, explicitArgs);
}
// ConstructorResolver
public BeanWrapper instantiateUsingFactoryMethod(
String beanName, RootBeanDefinition mbd, @Nullable Object[] explicitArgs) {
BeanWrapperImpl bw = new BeanWrapperImpl();
this.beanFactory.initBeanWrapper(bw);
// 实例工厂Bean对象,如果是静态工厂,值为null
Object factoryBean;
// 工厂的类型
Class<?> factoryClass;
// 是否静态工厂
boolean isStatic;
// 实例工厂的BeanName,如果是静态工厂,则值为null
String factoryBeanName = mbd.getFactoryBeanName();
if (factoryBeanName != null) {
// 如果是实例工厂,进入这个分支
// 实例工厂的Bean名称和需要使用工厂实例化的Bean对象的名称相同,则抛出异常
if (factoryBeanName.equals(beanName)) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"factory-bean reference points back to the same bean definition");
}
// 从IoC容器中获取实例工厂对象
factoryBean = this.beanFactory.getBean(factoryBeanName);
// 单例Bean,并且在IoC容器的一级缓存中已存在,说明这个Bean已经被创建过了,不能再次创建,抛出异常
if (mbd.isSingleton() && this.beanFactory.containsSingleton(beanName)) {
throw new ImplicitlyAppearedSingletonException();
}
factoryClass = factoryBean.getClass(); // 实例工厂的类名,这里可能得到CGLIB生成的子类名称
isStatic = false;
}
else {
// It's a static factory method on the bean class.
// 如果是静态工厂,则进入这个分支
if (!mbd.hasBeanClass()) {
throw new BeanDefinitionStoreException(mbd.getResourceDescription(), beanName,
"bean definition declares neither a bean class nor a factory-bean reference");
}
factoryBean = null;
factoryClass = mbd.getBeanClass(); // 静态工厂的类名
isStatic = true;
}
Method factoryMethodToUse = null; // 用于实例化Bean的工厂方法
ArgumentsHolder argsHolderToUse = null; // 持有 用于实例化Bean的参数 对象
Object[] argsToUse = null; // 用于实例化Bean的参数
if (explicitArgs != null) {
argsToUse = explicitArgs;
}
else {
Object[] argsToResolve = null;
synchronized (mbd.constructorArgumentLock) {
/*
* 工厂方法是否已经被解析过
* 第一次实例化Bean时,解析Bean定义,找到实例化Bean的工厂方法,
* 然后会将工厂方法回写到Bean定义中的resolvedConstructorOrFactoryMethod属性,并且constructorArgumentsResolved属性也会被设置为true。
* 当下次再需要实例化这个Bean时,就无须再次解析,直接从Bean定义中获取即可,这是对非单例作用域的Bean实例化过程的优化
*/
factoryMethodToUse = (Method) mbd.resolvedConstructorOrFactoryMethod;
if (factoryMethodToUse != null && mbd.constructorArgumentsResolved) {
// Found a cached factory method...
argsToUse = mbd.resolvedConstructorArguments;
if (argsToUse == null) {
argsToResolve = mbd.preparedConstructorArguments;
}
}
}
if (argsToResolve != null) {
argsToUse = resolvePreparedArguments(beanName, mbd, bw, factoryMethodToUse, argsToResolve, true);
}
}
if (factoryMethodToUse == null || argsToUse == null) {
// Need to determine the factory method...
// Try all methods with this name to see if they match the given arguments.
// 获取工厂的实际类型,如果是CGLIB生成的子类,则返回原始类;否则返回的就是参数值
factoryClass = ClassUtils.getUserClass(factoryClass);
List<Method> candidates = null; // 可用于实例化Bean的工厂方法
if (mbd.isFactoryMethodUnique) {
// 如果是宰Java配置类中配置的Bean,会走这块代码
if (factoryMethodToUse == null) {
factoryMethodToUse = mbd.getResolvedFactoryMethod();
}
if (factoryMethodToUse != null) {
candidates = Collections.singletonList(factoryMethodToUse);
}
}
if (candidates == null) {
// 如果是静态工厂或者实例工厂,会走块代码
candidates