Spring官网阅读(一)容器及实例化

如何实例化一个Bean?

从官网上来看,主要有以下三种方法


  1. 构造方法
  2. 通过静态工厂方法
  3. 通过实例工厂方法

这三种例子,官网都有具体的演示,这里就不再贴了,我们通过自己查阅部分源码,来验证我们在官网得到的结论,然后通过debug等方式进行验证。

我们再从代码的角度进行一波分析,这里我们直接定位到 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance
这个方法中,具体定位步骤不再演示了,大家可以通过形如下面这段代码:

// 这里我们通过xml配置实例化一个容器
ClassPathXmlApplicationContext cc = new ClassPathXmlApplicationContext("classpath:application.xml");
MyServiceImpl luBan = (MyServiceImpl) cc.getBean("myServiceImpl");

直接main方法运行,然后在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance
这个方法的入口打一个断点,如图:



接下来我们对这个方法进行分析,代码如下:

protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 1.获取这个bean的class属性,确保beanDefinition中beanClass属性已经完成解析
// 我们通过xml从标签中解析出来的class属性在刚刚开始的时候必定是个字符串
Class beanClass = resolveBeanClass(mbd, beanName);

// 省略异常判断代码.....

// 2.通过beanDefinition中的supplier实例化这个bean
Supplier instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}

// 3.通过FactoryMethod实例化这个bean
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}

// 4.下面这段代码都是在通过构造函数实例化这个Bean,分两种情况,一种是通过默认的无参构造,一种 是通过推断出来的构造函数
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}



if (resolved) {
if (autowireNecessary) {
return autowireConstructor(beanName, mbd, null, null);
}
else {
return instantiateBean(beanName, mbd);
}
}

// Candidate constructors for autowiring?
Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
return autowireConstructor(beanName, mbd, ctors, args);
}

// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
return autowireConstructor(beanName, mbd, ctors, null);
}

// No special handling: simply use no-arg constructor.
return instantiateBean(beanName, mbd);
}

我们主要关注进行实例化的几个方法:

  1. 通过 BeanDefinition
    中的 instanceSupplier
    直接获取一个实例化的对象。这个 instanceSupplier
    属性我本身不是特别理解,在xml中的标签以及注解的方式都没有找到方式配置这个属性。后来在 org.springframework.context.support.GenericApplicationContext
    这个类中找到了以下两个方法


经过断点测试,发现这种情况下,在实例化对象时会进入上面的supplier方法。下面是测试代码:

public static void main(String[] args) {
// AnnotationConfigApplicationContext是GenericApplicationContext的一个子类
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
ac.registerBean("service", Service.class,Service::new);
ac.refresh();
System.out.println(ac.getBean("service"));
}

可以发现进入了这个方法进行实例化


这个方法一般不常用,平常我们也使用不到,就不做过多探究,笔者认为,这应该是Spring提供的一种方便外部扩展的手段,让开发者能够更加灵活的实例化一个bean。

  1. 接下来我们通过不同的创建bean的手段,来分别验证对象的实例化方法