Spring框架源码关键点
CommonAnnotationBeanPostProcessor
AutowiredAnnotationBeanPostProcessor
BeanDefinition
DefaultListableBeanFactory
GenericApplicationContext
AnnotationConfigApplicationContext
DefaultListableBeanFactory is a key delegate of GenericApplicationContext container
通过 BeanPostProcessor 实现的aop,相关的还有 LoadTimeWeaver
compatible 兼容的
complicated 复杂的
explicitly: 显式的
implicitly: 隐式的
CopyOnWriteArrayList
Spring’s DataBinder and the lower-level BeanWrapper both use PropertyEditorSupport implementations to parse and format property values.
BeanFactory:
单例的存放位置:
1. 非工厂bean创建的单例对象
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#singletonObjects
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
2. 由工厂bean创建的单例对象
org.springframework.beans.factory.support.FactoryBeanRegistrySupport#factoryBeanObjectCache
private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);
3. 针对class="${custom.strategy.class}"的解析代码在
org.springframework.beans.factory.support.AbstractBeanFactory#evaluateBeanDefinitionString
4. 根据BeanDefinition创建bean的代码在
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])
策略模式:做同一件事的不同方法
getBean(String)的过程
bean的初始化过程:
-
找到构造方法
- 可能是普通的构造方法
- 可能是工厂方法
-
执行构造方法
执行策略:cglib和simple,具体参考InstantiationStrategy接口的实现类。
这一步仅仅创建了这么一个实例,但还没有进行DI等操作。 -
执行 MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
-
对实例的字段进行赋值
如果被赋值的对象是一个引用,会~~递归~~(不确定是否是单线程递归,如果单线程递归的话那循环引用怎么处理的?)进行创建 -
初始化对象
- invokeAwareMethods
- applyBeanPostProcessorsBeforeInitialization
这个方法就是在应用BeanProcessors的 postProcessBeforeInitialization 方法
这里面就包含了对 javax.annotation.PostConstruct 注解方法的执行 - invokeInitMethods
- InitializingBean#afterPropertiesSet
- 自定义的init-method
- applyBeanPostProcessorsAfterInitialization
这个方法就是在应用BeanProcessors的 postProcessAfterInitialization 方法
这里面就包含了对 javax.annotation.PreDestroy 注解方法的执行
-
doGetBean通过name的查找bean的过程(name不带地址符)
- 获取name对应的规范名称。(如果name本身就是规范名称,则直接返回,如果是别名,则返回别名对应的规范名称)
- 尝试从缓存中获取实例
初始化过程个人觉得太复杂了,让你不容易理解。Spring也许是为了追求代码的重复利用,我去完成的话,我可能偏向代码的阅读性,当然也许经过很多版本的迭代后也会成为类似Spring这样的代码
好像针对任何一步输入都设置了回调方法能够进行对输入进行更改
比如:BeanPostProcessor的很多子接口和实现类
关于实例化和初始化的回调。
-
实例化前
postProcessBeforeInstantiation -
实例化后
postProcessAfterInstantiation -
初始化前
postProcessBeforeInitialization -
初始化后
postProcessAfterInitialization -
对属性值的修改
postProcessProperties -
对BeanDefinition对象进行操作
postProcessMergedBeanDefinition
InitDestroyAnnotationBeanPostProcessor
CommonAnnotationBeanPostProcessor
支持解析的注解
- Resource(来自JSR-250 javax.annotation.Resource)
- PostConstruct ( javax.annotation.PostConstruct)
- PreDestroy ( javax.annotation.PreDestroy)
- WebServiceRef (javax.xml.ws.WebServiceRef)
- EJB (javax.ejb.EJB)
AutowiredAnnotationBeanPostProccessor
默认支持解析的注解
AutowiredAnnotationBeanPostProccessor 类支持解析三个注解:
- @Autowired
- @Value
- @Inject (来自JSR-330 javax.inject.Inject)
使用@Inject注解的地方都能使用@Autowired注解替换
查找指定注解元数据的过程
- ReflectionUtils.doWithLocalFields 遍历指定类的所有field,在field上找
- ReflectionUtils.doWithLocalMethods 遍历指定类的所有方法,在method上找
- 获取指定的父类,循环上述过程
注意:如果字段或者方法上同时添加了@Value @Autowired @Inject注解,只会处理一个注解,处理哪个注解呢? 这个加入的顺序了。代码如下:
@Nullable
private MergedAnnotation<?> findAutowiredAnnotation(AccessibleObject ao) {
MergedAnnotations annotations = MergedAnnotations.from(ao);
for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
MergedAnnotation<?> annotation = annotations.get(type);
if (annotation.isPresent()) {
//找到一个目标注解就返回。 也就是说如果一个字段或者方法同时加了 Autowired Value Inject注解,Autowired的优先级最高。
//具体哪个优先级最好,看加入的顺序了
return annotation;
}
}
return null;
}
疑问
为什么Spring里很多地方要对ConcurrentHashMap对象进行加锁?
Spring的DCL案例:
AutowiredAnnotationBeanPostProcessor#findAutowiringMetadata
private InjectionMetadata findAutowiringMetadata(String beanName, Class<?> clazz, @Nullable PropertyValues pvs) {
// Fall back to class name as cache key, for backwards compatibility with custom callers.
String cacheKey = (StringUtils.hasLength(beanName) ? beanName : clazz.getName());
// Quick check on the concurrent map first, with minimal locking.
InjectionMetadata metadata = this.injectionMetadataCache.get(cacheKey);
//存在一个 DCL
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
synchronized (this.injectionMetadataCache) {
metadata = this.injectionMetadataCache.get(cacheKey);
if (InjectionMetadata.needsRefresh(metadata, clazz)) {
if (metadata != null) {
metadata.clear(pvs);
}
metadata = buildAutowiringMetadata(clazz);
this.injectionMetadataCache.put(cacheKey, metadata);
}
}
}
return metadata;
}
AbstractBeanFactory#markBeanAsCreated
protected void markBeanAsCreated(String beanName) {
if (!this.alreadyCreated.contains(beanName)) {
synchronized (this.mergedBeanDefinitions) {
if (!this.alreadyCreated.contains(beanName)) {
// Let the bean definition get re-merged now that we're actually creating
// the bean... just in case some of its metadata changed in the meantime.
clearMergedBeanDefinition(beanName);
this.alreadyCreated.add(beanName);
}
}
}
}
SmartInitializingSingleton
public interface SmartInitializingSingleton {
//在所有bean执行了getBean后才会执行这个方法
void afterSingletonsInstantiated();
}
替换占位符的查找位置
- 应用本身指定的配置信息
- System.getProperties();
- System.getenv();
代码如下:(在ConfigurableApplicationnContext中)
/**
* Name of the {@link Environment} bean in the factory.
* <p>
* Environment实例的名字
*
* @since 3.1
*/
String ENVIRONMENT_BEAN_NAME = "environment";
/**
* Name of the System properties bean in the factory.
*
* @see java.lang.System#getProperties()
*/
String SYSTEM_PROPERTIES_BEAN_NAME = "systemProperties";
/**
* Name of the System environment bean in the factory.
*
* @see java.lang.System#getenv()
*/
String SYSTEM_ENVIRONMENT_BEAN_NAME = "systemEnvironment";
ApplicationContext事件的发布
发布一个事件后,不仅会在本容器中发布还会在父容器中发布。
代码在:AbstractApplicationContext#publishEvent(java.lang.Object, org.springframework.core.ResolvableType)
// 发布一个事件后,不仅会在本容器中发布,还会在父容器中发布
// Publish event via parent context as well...
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
} else {
this.parent.publishEvent(event);
}
}
一些内置组件的名字
AbstractApplicationContext中定义的
- messageSource
- lifycycleProcessor
- applicationEventMulticaster
ConfigurableApplicationContext中定义的
- conversionService
- loadTimeWeaver
- environment
Application启动流程
- 初始化环境,也就是初始化配置文件。
比如 xxx.properties xxxx.yml - 初始化BeanDefinition
MergedBeanDefinitionPostProcessor
public interface MergedBeanDefinitionPostProcessor extends BeanPostProcessor {
/**
*
* 调用时机:实例化bean后,初始化bean前
*/
void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
default void resetBeanDefinition(String beanName) {
}
}
InstantiationAwareBeanPostProcessor
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {
/**
* 实例化前调用的,返回null表示采用默认的实例化方法
*/
@Nullable
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
return null;
}
/**
* 实例化后调用的
* 返回true: 表示应该执行populateBean
* 返回false:表示应该跳过执行populateBean
*/
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
return true;
}
/**
* 执行postProcessAfterInstantiation后调用这个方法
*/
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
throws BeansException {
return null;
}
/**
* 已过期,由postProcessProperties方法替代
*/
@Deprecated
@Nullable
default PropertyValues postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
return pvs;
}
}
系统推荐
- Cordova+Umi项目搭建步骤
- JVM垃圾收集器
- 微博关注关系如何实现
- JDK命令行工具
- K8S 无感发布
- 搭建基于docker的elk平台来分析java日志
- 推荐几个适用小工具
- JetBrains-License-Server
- JVM杂项
- RocketMQ
- 批量替换文件名中的指定字符串
- Hbase 总览
- 随机毒鸡汤:不要鹤立鸡群,要试着离开那群鸡。