源码解析:Spring源码解析笔记启动过程(下)
Posted colodoo_纸伞
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了源码解析:Spring源码解析笔记启动过程(下)相关的知识,希望对你有一定的参考价值。
本文由colodoo(纸伞)整理
QQ 425343603
Java学习交流群(717726984)当前Spring源码版本是 5.2.10.RELEASE
承接上一篇文章源码解析:Spring源码解析笔记(三)启动过程(中)。
上一篇文章,我们了解了我们定义的beanDefinition是怎么被实例化的,但还不是完全体,还不是我们平常用到的bean对象,我们继续阅读源码,看看bean是怎么属性填充并完成初始化的。
完成刷新(finishRefresh)
org.springframework.context.support.AbstractApplicationContext#finishRefresh
protected void finishRefresh() {
// Clear context-level resource caches (such as ASM metadata from scanning).
clearResourceCaches();
// 为此上下文初始化生命周期处理器。
initLifecycleProcessor();
// 获取生命周期
// 刷新生命周期
// 首先将刷新传播到生命周期处理器.
getLifecycleProcessor().onRefresh();
// 发布最终活动.
publishEvent(new ContextRefreshedEvent(this));
// 参与 LiveBeansView MBean(如果活动).
LiveBeansView.registerApplicationContext(this);
}
初始化生命周期处理器(initLifecycleProcessor)
org.springframework.context.support.AbstractApplicationContext#initLifecycleProcessor
protected void initLifecycleProcessor() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 获取生命周期处理器
if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
// 获取到这设置到当前对象lifecycleProcessor中
this.lifecycleProcessor =
beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
if (logger.isTraceEnabled()) {
logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
}
}
else {
// 初始化默认生命周期处理器
DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
// 为生命周期处理器设置bean工厂对象
defaultProcessor.setBeanFactory(beanFactory);
// 设置生命周期处理器
this.lifecycleProcessor = defaultProcessor;
// 注册生命周期处理器到bean工厂中
beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
if (logger.isTraceEnabled()) {
logger.trace("No \'" + LIFECYCLE_PROCESSOR_BEAN_NAME + "\' bean, using " +
"[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");
}
}
}
总结一下这段代码
- 获取容器中存在的生命周期处理器,存在则设置,不存在则初始化。
- 初始化默认生命周期处理器(DefaultLifecycleProcessor)
- 默认生命周期处理器(defaultProcessor)注册到bean工厂(beanFactory)中。
这一步顾名思义就是把我们生命周期初始化需要用到的lifecycleProcessor准备好,接下来就要真正进入bean生命周期了。
生命周期刷新(onRefresh)
org.springframework.context.support.DefaultLifecycleProcessor#onRefresh
public void onRefresh() {
startBeans(true);
this.running = true;
}
进入到这个方法中发现具体实现逻辑在startBeans方法中,继续往下阅读。
启动 Beans(startBeans)
org.springframework.context.support.DefaultLifecycleProcessor#startBeans
private void startBeans(boolean autoStartupOnly) {
// 获取生命周期Bean对象(多个)
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
// 阶段
Map<Integer, LifecycleGroup> phases = new HashMap<>();
// 遍历所有生命周期对象
lifecycleBeans.forEach((beanName, bean) -> {
//
if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
int phase = getPhase(bean);
LifecycleGroup group = phases.get(phase);
if (group == null) {
group = new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly);
phases.put(phase, group);
}
group.add(beanName, bean);
}
});
if (!phases.isEmpty()) {
List<Integer> keys = new ArrayList<>(phases.keySet());
Collections.sort(keys);
for (Integer key : keys) {
phases.get(key).start();
}
}
}
总结下这部分代码:
- 获取生命周期bean(getLifecycleBeans)
- 同时进行生命周期bean实例化(getLifecycleBeans)
我们继续阅读getLifecycleBeans这个方法,看看有没有我们想要的东西。
获取生命周期 Bean(getLifecycleBeans)
org.springframework.context.support.DefaultLifecycleProcessor#getLifecycleBeans
protected Map<String, Lifecycle> getLifecycleBeans() {
// 获取bean工厂对象
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// 初始化beans
Map<String, Lifecycle> beans = new LinkedHashMap<>();
// 获取所有生命周期对象
// 这里获取到的值是lifecycleProcessor
String[] beanNames = beanFactory.getBeanNamesForType(Lifecycle.class, false, false);
for (String beanName : beanNames) {
// 获取用于注册的bean名称
// 默认情况输出 -> lifecycleProcessor
String beanNameToRegister = BeanFactoryUtils.transformedBeanName(beanName);
// 判断是否为工厂bean
// 这里默认情况输出 -> false
boolean isFactoryBean = beanFactory.isFactoryBean(beanNameToRegister);
// 如果为工厂bean则首字母加一个“&”符号
// 这里不是工厂bean 输出 -> lifecycleProcessor
String beanNameToCheck = (isFactoryBean ? BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName);
// 判断是否存在该对象
if ((beanFactory.containsSingleton(beanNameToRegister) &&
(!isFactoryBean || matchesBeanType(Lifecycle.class, beanNameToCheck, beanFactory))) ||
matchesBeanType(SmartLifecycle.class, beanNameToCheck, beanFactory)) {
// 对该对象进行实例化
Object bean = beanFactory.getBean(beanNameToCheck);
if (bean != this && bean instanceof Lifecycle) {
beans.put(beanNameToRegister, (Lifecycle) bean);
}
}
}
// 返回实例化后的生命周期对象
return beans;
}
这一步很明显,前面都是对生命周期对象的bean名称进行获取。
看到我们很熟悉的beanFactory.getBean,说明它又帮生命周期bean进行了实例化,最后返回实例化后的生命周期对象。
beanFactory.getBean 这部分的源码,可以阅读上一篇文章 源码解析:Spring源码解析笔记(三)启动过程(中)
阅读到这里,我们没有发现属性注入的地方,反过头来看看是不是知道遗漏了哪些地方。
经过我的调试,发现需要改造一下我们的代码,因为我发现我们的代码并没有存在依赖关系,我们的userService并没有依赖任何的其他bean。
我们新建一个userController去调用它,并且依赖userService这个bean。
改造代码
UserController
package com.zhisan.spring.controller;
import com.zhisan.spring.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
public class UserController {
private UserService userService;
public void login() {
userService.login();
}
public UserService getUserService() {
return userService;
}
public void setUserService(UserService userService) {
this.userService = userService;
}
}
MainXml.java
package com.zhisan.spring;
import com.zhisan.spring.config.Config;
import com.zhisan.spring.controller.UserController;
import com.zhisan.spring.service.UserService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MainXml {
public static void main(String[] args) {
// XML方式
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
UserController userController = applicationContext.getBean("userController", UserController.class);
userController.login();
}
}
spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:task="http://www.springframework.org/schema/task" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="userController" class="com.zhisan.spring.controller.UserController">
<property name="userService" ref="userService"></property>
</bean>
<bean id="userService" class="com.zhisan.spring.service.UserService"> </bean>
</beans>
改造完后,我们继续调试。
在下面这populateBean方法上打上断点,方便调试。
因为寻找入口的过程比较漫长,所以中间的篇幅就省略了。
填充 Bean(populateBean)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
// 这里省略了一些无关的逻辑代码...
// 这里会把类中的属性值都获取到
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
// 省略一些校验代码...
// 判断属性值列表是否为空,不空则进入属性应用
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
这部分的代码主要是完成属性填充的一些获取和校验,真正的填充属性值逻辑在applyPropertyValues,我们继续阅读这个方法。
应用属性值(applyPropertyValues)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyPropertyValues
protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {
// 判断是否为空
if (pvs.isEmpty()) {
return;
}
// 校验环境
if (System.getSecurityManager() != null && bw instanceof BeanWrapperImpl) {
((BeanWrapperImpl) bw).setSecurityContext(getAccessControlContext());
}
// 变量准备
MutablePropertyValues mpvs = null;
List<PropertyValue> original;
// 判断类型
if (pvs instanceof MutablePropertyValues) {
mpvs = (MutablePropertyValues) pvs;
// 判断是否已经转换
if (mpvs.isConverted()) {
// Shortcut: use the pre-converted values as-is.
try {
bw.setPropertyValues(mpvs);
return;
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
// 获取属性值列表
// result = {ArrayList@1625} size = 1
// 0 = {PropertyValue@1990} "bean property \'userService\'"
// name = "userService"
// value = {RuntimeBeanReference@2000} "<userService>"
// optional = false
// converted = false
// convertedValue = null
// conversionNecessary = null
// resolvedTokens = null
// source = null
// attributes = {LinkedHashMap@2001} size = 0
original = mpvs.getPropertyValueList();
}
else {
original = Arrays.asList(pvs.getPropertyValues());
}
TypeConverter converter = getCustomTypeConverter();
if (converter == null) {
converter = bw;
}
BeanDefinitionValueResolver valueResolver = new BeanDefinitionValueResolver(this, beanName, mbd, converter);
// Create a deep copy, resolving any references for values.
List<PropertyValue> deepCopy = new ArrayList<>(original.size());
boolean resolveNecessary = false;
for (PropertyValue pv : original) {
if (pv.isConverted()) {
deepCopy.add(pv);
}
else {
String propertyName = pv.getName();
Object originalValue = pv.getValue();
if (originalValue == AutowiredPropertyMarker.INSTANCE) {
Method writeMethod = bw.getPropertyDescriptor(propertyName).getWriteMethod();
if (writeMethod == null) {
throw new IllegalArgumentException("Autowire marker for property without write method: " + pv);
}
originalValue = new DependencyDescriptor(new MethodParameter(writeMethod, 0), true);
}
// 属性值实例化
Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);
Object convertedValue = resolvedValue;
boolean convertible = bw.isWritableProperty(propertyName) &&
!PropertyAccessorUtils.isNestedOrIndexedProperty(propertyName);
if (convertible) {
convertedValue = convertForProperty(resolvedValue, propertyName, bw, converter);
}
if (resolvedValue == originalValue) {
if (convertible) {
pv.setConvertedValue(convertedValue);
}
deepCopy.add(pv);
}
else if (convertible && originalValue instanceof TypedStringValue &&
!((TypedStringValue) originalValue).isDynamic() &&
!(convertedValue instanceof Collection || ObjectUtils.isArray(convertedValue))) {
pv.setConvertedValue(convertedValue);
deepCopy.add(pv);
}
else {
resolveNecessary = true;
deepCopy.add(new PropertyValue(pv, convertedValue));
}
}
}
if (mpvs != null && !resolveNecessary) {
mpvs.setConverted();
}
// 中间没有中文注释的部分可以忽略...不是主要逻辑
try {
// 设置属性值
bw.setPropertyValues(new MutablePropertyValues(deepCopy));
}
catch (BeansException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Error setting property values", ex);
}
}
这部分做了如下几件事:
- 遍历了所有的属性值(for)
- 实例化属性值所需的bean并获取(resolveValueIfNecessary)
- 转换属性(convertForProperty)
- 填充属性(setPropertyValues)
设置属性(setValue)
org.springframework.beans.BeanWrapperImpl.BeanPropertyHandler#setValue
public void setValue(@Nullable Object value) throws Exception {
// 通过反射获取到setter方法的对象
// 这里输出:public void com.zhisan.spring.controller.UserController.setUserService(com.zhisan.spring.service.UserService)
Method writeMethod = (this.pd instanceof GenericTypeAwarePropertyDescriptor ?
((GenericTypeAwarePropertyDescriptor) this.pd).getWriteMethodForActualAccess() :
this.pd.getWriteMethod());
// 设置可访问
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
ReflectionUtils.makeAccessible(writeMethod);
return null;
});
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>)
() -> writeMethod.invoke(getWrappedInstance(), value), acc);
}
catch (PrivilegedActionException ex) {
throw ex.getException();
}
}
else {
// 设置可访问方法
ReflectionUtils.makeAccessible(writeMethod);
// 执行方法
// value=userService对象
writeMethod.invoke(getWrappedInstance(), value);
}
}
这里是真正填充属性的逻辑方法,原理也是基于反射。
- 通过反射获取到setter方法
- 通过执行setter方法把处理后的参数设置到属性中。
至此,完成是填充属性这个步骤,接下来就是要完成bean生命周期中的最后一步,完成初始化。
初始化Bean(initializeBean)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
// 调用Aware方法
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
这里除了调用invokeInitMethods这个方法是主要逻辑,其他部分暂时可以忽略,继续阅读invokeInitMethods方法。
调用设置方法(invokeInitMethods)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods
protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
// 是否初始化bean
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name \'" + beanName + "\'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
// 调用自定义初始化方法
// 判断该bean上是否含有初始化方法
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
这个部分最主要的逻辑就是判断对象是否,需要执行初始化方法,具体逻辑在invokeCustomInitMethod这个方法中。
调用自定义初始化方法(invokeCustomInitMethod)
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeCustomInitMethod
- 获取bean定义(beanDefinition)中的初始化方法。
- 通过反射获取初始化方法
- 执行初始化方法
这是这个方法的逻辑,就不详细解析源码了。
最后
至此,完成bean生命周期的所有过程,启动过程篇幅结束!
接下来的文章我们会继续研究这些接口相关的设计。
以上是关于源码解析:Spring源码解析笔记启动过程(下)的主要内容,如果未能解决你的问题,请参考以下文章