spring核心源码分析第十八篇 refresh流程一finishBeanFactoryInitialization三步曲之createBeanInstance

这里写目录标题

createBeanInstance核心流程

Supplier机制 FactoryMethod机制 autowireConstructor机制 instantiateBean机制
通过supplier机制创建实例 通过factorymethod创建实例 通过含参构造创建实例 一般走无参构造创建实例

demo讲解supplier与factorymethod

demo一supplier

return obtainFromSupplier(instanceSupplier, beanName);返回创建的对象

public class SupplierBean {
	private static User createUser(){
		return new User("小薇呀");
	}
	static class User{
		private String name;
		public User(String name) {
			this.name = name;
		}
		public String getName() {
			return name;
		}
		@PostConstruct
		public void init(){
			System.out.println("user 初始化.....");
		}
				}
			}
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(User.class);
beanDefinition.setInstanceSupplier(SupplierBean::createUser);

// 如此初始化之后 则会采用这里的Supplier 创建User对象
// 目的: 避免下面采用反射调用 从而提高相关性能

demo一instantiateUsingFactoryMethod

通过return instantiateUsingFactoryMethod(beanName, mbd, args);完成bean创建

	静态工厂和实例化工厂区别  class录入的是工厂类 而不是bean name实际对应的类  实例化工厂还需要 设置一个实例化工厂bean 如: hi13Factory
	### 静态工厂
	<!--  class 表示工厂bean的类型  但bean的类型是getHi11返回的类型-->
	<bean id="hi11" class="com.renxl.demo.Hi12StaticFactory" factory-method="getHi11" />
	### 实例化工厂
	<bean id="hi13Factory" class="com.renxl.demo.Hi13Factory"/>
	<!--    此时class属性可以省略  -->
	<bean id="hi11_1"  factory-bean="hi13Factory" factory-method="getHi11_1" />

源码分析

  • 先走Supplier机制实例化对象
  • 在走factoryMethod机制实例化对象
  • 曾经解析过则走缓存策略
  • 是否走构造参数注入实例化对象 通过后置处理器决定构造参数
  • 走无参构造实例化对象
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
	查找类class 对象确保可以实例化
	Class<?> beanClass = resolveBeanClass(mbd, beanName);
	走supplier策略
	Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
	if (instanceSupplier != null) {
		return obtainFromSupplier(instanceSupplier, beanName);
	}
	走FactoryMethod策略
	if (mbd.getFactoryMethodName() != null) {
		return instantiateUsingFactoryMethod(beanName, mbd, args);
	}
	.......删除创建走缓存相关代码
	后置处理器决定构造注入- 也就是说由后置管理器决定选择哪个构造方法
	Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
	if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
			mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
		可能还是有多个构造参数,需要方法内部进一步决定
		return autowireConstructor(beanName, mbd, ctors, args);
	}
	******************************************************************
	 一般情况下走的是这个方法进行实例化
	 业务里面的service ,controller 等基本都是这个地方进行单例的实例化
	******************************************************************
	return instantiateBean(beanName, mbd);
}

源码分析一构造方法的选择

源码分析一instantiateBean的实现

  • 通过CglibSubclassingInstantiationStrategy策略实例化对象
  • 策略根据有无需要增强的方法,从而使用jdk反射或者cglib创建对象
protected BeanWrapper instantiateBean(final String beanName, final RootBeanDefinition mbd) {
		......删除其他代码
		Object beanInstance = getInstantiationStrategy().instantiate(mbd, beanName, parent);
		BeanWrapper bw = new BeanWrapperImpl(beanInstance);
		initBeanWrapper(bw);
		return bw;
}	

public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
	......删除其他代码
	if (!bd.hasMethodOverrides()) {
		Constructor<?> constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
			if (constructorToUse == null) {
				final Class<?> clazz = bd.getBeanClass();
				constructorToUse = clazz.getDeclaredConstructor();
				bd.resolvedConstructorOrFactoryMethod = constructorToUse;
			}
		走反射创建对象 
		return BeanUtils.instantiateClass(constructorToUse);
	}
	else {
		// 有@Lookup @Replace注解的情况则需要使用cglib实现代理后的对象
		return instantiateWithMethodInjection(bd, beanName, owner);
	}
}	

jdk创建对象

此处了解spring支持Kotlin即可,一般项目也用不到

	public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
			如果是Kotlin相关 则引用其jvm技术完成对象创建 如果不是反射创建对象
			ReflectionUtils.makeAccessible(ctor);
			return (KotlinDetector.isKotlinReflectPresent() && KotlinDetector.isKotlinType(ctor.getDeclaringClass()) ?
					KotlinDelegate.instantiateClass(ctor, args) : ctor.newInstance(args));
		
	}

cglib创建对象

两个拦截器不在讲解其实现
同lite与full模式实现,如果要创建的对象存在@Lookup和@Replace方法 则对这些方法增加拦截 不在调用原方法 而是通过beanfactory.getBean实现

	protected Object instantiateWithMethodInjection(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner,
			@Nullable Constructor<?> ctor, Object... args) {
		return new CglibSubclassCreator(bd, owner).instantiate(ctor, args);
	}


	public Object instantiate(@Nullable Constructor<?> ctor, Object... args) {

	......  删除其他代码
	两个拦截器不在讲解其实现和lite与full模式的实现一样
	如果要创建的对象存在@Lookup和@Replace方法 则对这些方法增加拦截 不在调用原方法 二是通过beanfactory.getBean实现
	factory.setCallbacks(new Callback[] {NoOp.INSTANCE,
			new LookupOverrideMethodInterceptor(this.beanDefinition, this.owner),
			new ReplaceOverrideMethodInterceptor(this.beanDefinition, this.owner)});
	return instance;
}

总结

  • 讲解了对象创建的过程,分为supplier,factorymethod和构造实例化三种策略
  • 同时讲解了构造函数的选择方式
  • 需要注意的是,此时spring容器中bean处于创建中但尚未加入spring容器,也没有完成DI,Wrapper等功能
上一篇:uniapp原生组件_用AndroidStudio开发原生uniapp组件---uniapp一次开发_小程序_Android_IOS_快应用多端通用工作笔记005


下一篇:redis-string