Spring最重要的功能就是帮助程序员创建对象(也就是IOC),而启动Spring就是为创建Bean对象做准备,所以我们先明白Spring到底是怎么去创建Bean的,也就是先弄明白Bean的生命周期。
这里省略了一些逻辑,bean生命周期主要逻辑如下
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
spring启动在applicationContext时会构造一个BeanFactory对象
Spring启动的时候会进行扫描,会先调用
org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#scanCandid
ateComponents(String basePackage)
扫描某个包路径,并得到BeanDefinition的Set集合。
扫描的逻辑也是比较复杂,后面有时间的话再拿出来单独讲。
由于Spring中支持父子BeanDefinition,所以需要进行BeanDefinition的合并,得到完整的child的BeanDefinition。(很少用这样定义)
<bean id="parent" class="com.zhouyu.service.Parent" scope="prototype"/>
<bean id="child" class="com.zhouyu.service.Child"/>
BeanDefinition合并之后,就可以去创建Bean对象了,而创建Bean就必须实例化对象,而实例化就必须先加载当前BeanDefinition所对应的class
如果beanClass属性的类型是Class,那么就直接返回,如果不是,则会根据类名进行加载(doResolveBeanClass方法所做的事情)会利用BeanFactory所设置的类加载器来加载类,如果没有设置,则默认使用
ClassUtils.getDefaultClassLoader()所返回的类加载器来加载。
当前BeanDefinition对应的类成功加载后,就可以实例化对象了,但是…
在Spring中,实例化对象之前,Spring提供了一个扩展点,允许用户来控制是否在某个或某些Bean实例化之前做一些启动动作。这个扩展点叫InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()。比如:
@Component
public class ZhouyuBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName)throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("实例化前");
}
return null;
}
}
如上代码会导致,在userService这个Bean实例化前,会进行打印。
值得注意的是,postProcessBeforeInstantiation()是有返回值的,如果这么实现:
@Component
public class ZhouyuBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName)throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("实例化前");
return new UserService();
}
return null;
}
}
userService这个Bean,在实例化前会直接返回一个由我们所定义的UserService对象。如果是这样,表示不需要Spring来实例化了,并且后续的Spring依赖注入也不会进行了,会跳过一些步骤,直接执行初始化后这一步。
在这个步骤中就会根据BeanDefinition去创建一个对象了。
这里实例化的时候涉及到知识点推断构造方法, 大家可以看我的另一篇博客
Bean对象实例化出来之后,接下来就应该给对象的属性赋值了。在真正给属性赋值之前,Spring又提供了一个扩展点
MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition(),可以对此时的BeanDefinition进行加工,比如:
@Component
public class ZhouyuMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition,Class<?> beanType, String beanName) {
if ("userService".equals(beanName)) {
beanDefinition.getPropertyValues().add("orderService", new OrderService());
}
}
}
在Spring源码中,AutowiredAnnotationBeanPostProcessor就是一个
MergedBeanDefinitionPostProcessor,它的postProcessMergedBeanDefinition()中会去查找注入点,并缓存在AutowiredAnnotationBeanPostProcessor对象的一个Map中
(injectionMetadataCache)。
在处理完BeanDefinition后,Spring又设计了一个扩展点:
InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation(),比如:
@Component
public class ZhouyuInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
UserService userService = (UserService) bean;
userService.test();
}
return true;
}
}
上述代码就是对userService所实例化出来的对象进行处理。
这个扩展点,在Spring源码中基本没有怎么使用。
这里的自动注入指的是Spring的自动注入,也就是填充属性(依赖注入)
这个步骤中,就会处理@Autowired、@Resource、@Value等注解,
这其中的逻辑也比较复杂,后面有时间的话再拿出来单独讲。
完成了属性赋值之后,Spring会执行一些回调,包括:
初始化前,也是Spring提供的一个扩展点:
BeanPostProcessor.postProcessBeforeInitialization(),比如
@Component
public class ZhouyuBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("初始化前");
}
return bean;
}
}
利用初始化前,可以对进行了依赖注入的Bean进行处理。
这是Bean创建生命周期中的最后一个步骤,也是Spring提供的一个扩展点:
BeanPostProcessor.postProcessAfterInitialization(),比如:
@Component
public class ZhouyuBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if ("userService".equals(beanName)) {
System.out.println("初始化后");
}
return bean;
}
}
可以在这个步骤中,对Bean最终进行处理,Spring中的AOP就是基于初始化后实现的,初始化后返回的对象才是最终的Bean对象。
Bean销毁是发送在Spring容器关闭过程中的。
在Spring容器关闭时,比如:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) context.getBean("userService");
userService.test();
// 容器关闭
context.close();
在Bean创建过程中,在最后(初始化之后),有一个步骤会去判断当前创建的Bean是不是DisposableBean:
在Spring容器关闭过程时: