一.spring读取配置或注解的过程
1.先通过扫描指定包路径下的spring注解,比如@Component、@Service、@Lazy @Sope等spring识别的注解或者是xml配置的属性(通过读取流,解析成Document,Document)然后spring会解析这些属性,将这些属性封装到BeanDefintaion这个接口的实现类中.
spring也会将className、scope、lazy等这些属性装配到PersonAction对应的BeanDefintaion中.具体采用的是BeanDefinitionParser接口中的parse(Element element, ParserContext parserContext)方法,该接口有很多不同的实现类。通过实现类去解析注解或者xml然后放到BeanDefination中,BeanDefintaion的作用是集成了我们的配置对象中的各种属性,重要的有这个bean的ClassName,还有是否是Singleton、对象的属性和值等(如果是单例的话,后面会将这个单例对象放入到spring的单例池中)。
二.spring的bean的生命周期
spring的bean生命周期其实最核心的分为4个步骤,只要理清三个关键的步骤,其他的只是在这三个细节中添加不同的细节实现,也就是spring的bean生命周期:
- 实例化 Instantiation
- 初始化
- 使用和销毁 Destruction
实例化和初始化的区别:实例化是在jvm的堆中创建了这个对象实例,此时它只是一个空的对象,所有的属性为null。而初始化的过程就是讲对象依赖的一些属性进行赋值之后,调用某些方法来开启一些默认加载。比如spring中配置的数据库属性Bean,在初始化的时候就会将这些属性填充,比如driver、jdbcurl等,然后初始化连接
2.1.实例化 Instantiation
AbstractAutowireCapableBeanFactory.doCreateBean中会调用createBeanInstance()方法,该阶段主要是从beanDefinitionMap循环读取bean,获取它的属性,然后利用反射(core包下有ReflectionUtil会先强行将构造方法setAccessible(true))读取对象的构造方法(spring会自动判断是否是有参数还是无参数,以及构造方法中的参数是否可用),然后再去创建实例(newInstance)
2.2.初始化(初始化主要包括两个步骤,一个是属性填充,另一个就是具体的初始化过程)
2.2.1.属性赋值 PopulateBean()会对bean的依赖属性进行填充,@AutoWired注解注入的属性就发生这个阶段,假如我们的bean有很多依赖的对象,那么spring会依次调用这些依赖的对象进行实例化,注意这里可能会有循环依赖的问题。后面我们会讲到spring是如何解决循环依赖的问题
2.2.2:初始化 Initialization
初始化的过程包括将初始化好的bean放入到spring的缓存中、填充我们预设的属性进一步做后置处理等
3.使用和销毁 Destruction
在Spring将所有的bean都初始化好之后,我们的业务系统就可以调用了。而销毁主要的操作是销毁bean,主要是伴随着spring容器的关闭,此时会将spring的bean移除容器之中。此后spring的生命周期到这一步彻底结束,不再接受spring的管理和约束。
三.spring的BeanPostProcessor处理器
3.1.实例化阶段
该阶段会调用对象的空构造方法进行对象的实例化,在进行实例化之后,会调用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法
-InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation();
这个阶段允许在Bena进行实例化之前,允许开发者自定义逻辑,如返回一个代理对象。不过需要注意的是假如在这个阶段返回了一个不为null的实例,spring就会中断后续的过程。
-BeanPostProcessor.postProcessAfterInstantiation();
这个阶段是Bean实例化完毕后执行的后处理操作,所有在初始化逻辑、装配逻辑之前执行
3.2.初始化阶段
3.2.1.BeanPostProcessor.postProcessBeforeInitialization
该方法在bean初始化方法前被调用,Spring AOP的底层处理也是通过实现BeanPostProcessor来执行代理逻辑的
3.2.2.InitializingBean.afterPropertiesSet
自定义属性值 该方法允许我们进行对对象中的属性进行设置,假如在某些业务中,一个对象的某些属性为null,但是不能显示为null,比如显示0或者其他的固定数值,我们就可以在这个方法实现中将null值转换为特定的值
3.2.3.BeanPostProcessor.postProcessAfterInitialization(Object bean, String beanName)。
可以在这个方法中进行bean的实例化之后的处理,比如我们的自定义注解,对依赖对象的版本控制自动路由切换。比如有一个服务依赖了两种版本的实现,我们如何实现自动切换呢?这时候可以自定义一个路由注解,假如叫@RouteAnnotaion,然后实现BeanPostProcessor接口,在其中通过反射拿到自定义的注解@RouteAnnotaion再进行路由规则的设定。
3.2.4.SmartInitializingSingleton.afterSingletonsInstantiated
4.1.容器启动运行阶段
4.1.1.SmartLifecycle.start
容器正式渲染完毕,开始启动阶段,bean已经在spring容器的管理下,程序可以随时调用
5.1.容器停止销毁
5.1.1.SmartLifecycle.stop(Runnable callback)
spring容器停止运行
5.1.2.DisposableBean.destroy()
spring会将所有的bean销毁,实现的bean实例被销毁的时候释放资源被调用