目录

Spring Bean 生命周期

In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans。

BeanDefinition

Bean定义,最常见方式有两种,xml方式和java注解方式。

一个bean定义有以下9种属性:

  • Class :定义bean的 class 名字。
  • Name:定义bean的名称
  • Scope:定义bean的作用域
  • Constructer Arguments:定义使用的构造方法
  • Properties:属性
  • Autowired Mode:注入模型
  • Lazy initialization mode:懒加载
  • Initialization method:初始化方法
  • Destruction method:销毁方法
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class Deer {

  public Deer(){
    System.out.println("Dear constructs");
  }
}
public class Horse {

  public Horse(){
    System.out.println("Horse constructs");
  }
}

public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

  @Override
  public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    GenericBeanDefinition definitionClass = (GenericBeanDefinition) beanFactory.getBeanDefinition("deer");
    ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
    definitionClass.setBeanClass(Horse.class);
  }
}

public class TestApp {
  public static void main(String[] args) {
    AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
    context.register(Deer.class);
    context.register(MyBeanFactoryPostProcessor.class);
    context.refresh();

    System.out.println(context.getBean("deer").getClass());
  }
}

打印出的是Horse,这就是指鹿为马。

再联想一下,mybatis为什么只写Mapper接口就能进行dao操作?我们知道接口是无法实例化的。

没错,mybatis就是在这点进行了扩展,通过修改mapper的bean定义中的class属性,把 mapper 的 GenericBeanDefinition 的 class 修改成了一个 MapperFactoryBean,从而实现了mapper的代理类。

Autowired Mode(注入模型)

注入模型分为四种,分别是

  • no:不注入,这也是默认的选项。意味着如果我们不在某个字段上标记@Autowired等标签,spring就把该字段当做是普通字段,不会进行自动注入。

  • byName:在容器中寻找和属性同名的bean进行注入。

  • byType:在容器中寻找字段的class的bean并注入。 AbstractBeanDefinition.AUTOWIRE_BY_TYPE

  • constructor:和byType相似,只不过是在构造函数上注入。

Bean 扫描

bean定义最后都会放到BeanFactory的beanDefinitionMap中去。

BeanFactoryPostProcessor

在spring容器启动时,加载我们的bean定义后,来到spring提供的第一个扩展点!那就是BeanFactoryPostProcessor。

BeanFactoryPostProcessor允许我们读取bean的配置信息,然后在spring初始化bean之前去修改bean定义。

只需要实现该接口,并添加到容器中,spring就会执行实现的方法,进行你需要的增强。

BeanFactoryPostProcessor只有一个方法需要实现 postProcessBeanFactory,在这个方法中我们可以根据传递过来的beanfactory来获取想要修改的bean定义。正如我们之前修改的注入模型和class时候做的。

实例化

实例化意味着执行构造方法。

在refresh方法的finishBeanFactoryInitialization方法中,会对所有的单例非懒加载的bean进行创建,实例化便是其中步骤之一。

首先会先去获取bean,不存在就创建bean,解决循环依赖等。

如果你不知道bean是在哪个方法实例化的,那么你就打断点在构造方法上,毕竟只要实例化,无论是反射也好new也罢,都会走构造方法。

注意实例化是初始化的区别,实例化仅仅是调用构造方法进行对象的创建,不包含属性的赋值等初始化方法。

属性赋值

在上一步对象构造完之后,对象内的属性还没有进行赋值。

1
2
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean

初始化

把初始化前置增强,初始化,初始化后置增强,统一归为初始化

自定义初始化的操作,这里我们还可以进行扩展,通过实现BeanPostProcessor接口。

当然init方法我们也是可以定义!可以通过实现InitializingBean接口,或者在初始化方法上添加@PostConstruct注解。

1
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean

总结

  • bean 定义
  • bean定义被spring解析
  • post process bean factory
  • Constructs with no arg
  • before initialization
  • post construct (init)
  • after initialization
  • pre destory

针对 spring bean生命周期,推荐结合spring的官方文档和代码断点调试,来彻底理解整个生命周期,以及我们能对其做怎样的扩展。