-
getSingleton -
createBean -
initializeBean
总结
前言
停更三个多月了,哈哈哈。前几天大佬要我给他们小组做个ioc的分享,才想起来,之前一直想梳理一篇ioc的内容,隔了这么久,源码又有点生疏了。今天是1024程序员节,带大家再复习一下ioc。
1.createBean的方式
1.1 <bean/>标签
这是我们接触spring时最开始的用法。
/**
* <bean/>--》Spring bean
*/
private static void method1() {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
User user = applicationContext.getBean("user", User.class);
System.out.println(user);
}
spring.xml
1.2 @Bean
这种在configuration配置类中最常见。
public class BeanConfig {
@Bean
public User user(){
return new User();
}
}
/**
* @Bean --》Spring bean
*/
private static void method2() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);
User user = applicationContext.getBean("user", User.class);
System.out.println(user);
}
1.3 @Component
这种和@Bean很类似
先定义bean
@Component
public class User {
private String name;
private String age;
}
再配置扫描bean的类路径
@ComponentScan("com.windy.createBean")
public class BeanConfig {
}
获取bean
/**
* @Component-->Spring bean
*/
private static void method3() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);
User user = applicationContext.getBean("user", User.class);
System.out.println(user);
}
上面三种方式都是声明式的定义bean,这也是我们经常用的。
spring还有一种编程式定义bean的方式。这是最接近底层源码的一种方式。类似aop,transaction。spring都提供了两种方式来让大家使用。
1.4 beanDefinition
我们知道spring 的ioc主要分为两个阶段,1.beanDefinition ->容器的初始化阶段,2.getBean的阶段。
容器的初始化阶段又分为
资源的定位:用外部资源来描述bean对象;
装载:BeanDefinitionReader 读取、解析 Resource 资源,也就是将用户定义的 Bean 表示成 IoC 容器的内部数据结构:BeanDefinition;
注册:将第二步解析好的 BeanDefinition注册到一个 IOC 容器内部的一个HashMap 容器中。
这里就不带大家看这部分的源码了。大家感兴趣可以自己看看。
/**
* beanDefinition -->bean
*/
private static void method4() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(User.class);
applicationContext.registerBeanDefinition("user",beanDefinition);
//refresh能否去掉?
applicationContext.refresh();
User user = applicationContext.getBean("user", User.class);
System.out.println(user);
}
这里application.refresh()能否去掉?
我们可以注意到这里获取AnnotationConfigApplicationContext是无参构造,而前面声明式获取bean里面都有一个配置类。我们对比一下二者的区别。
声明式:
public AnnotationConfigApplicationContext(String... basePackages) {
this();
scan(basePackages);
refresh();
}
编程式:
public AnnotationConfigApplicationContext() {
StartupStep createAnnotatedBeanDefReader = this.getApplicationStartup().start("spring.context.annotated-bean-reader.create");
this.reader = new AnnotatedBeanDefinitionReader(this);
createAnnotatedBeanDefReader.end();
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
对比二者构造方式的不同,我们可以看到编程式无参构造少了一个refresh方法。这个refresh方法便是spring最核心的方法。这里就不再重复介绍refresh做了啥。前面讲springboot源码有详细介绍。SpringBoot启动原理这里借用之前画的图带大家再复习一下。
1.5 factoryBean
factoryBean 和beanFactory的区别?
一个是以Bean结尾,落脚点在bean,一个是以factory结尾,落脚点是factory 。factoryBean在很多源码中都有看到过它的身影。如前面介绍的FeignClient的创建。
/**
* factoryBean
*也可以用声明式 @Component等
*/
private static void method5() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
/**
* 会生成2个bean 对象
*
* 1:@user:WindyFactoryBean
* 2: user:person
*/
beanDefinition.setBeanClass(WindyFactoryBean.class);
applicationContext.registerBeanDefinition("user",beanDefinition);
//refresh能否去掉?
applicationContext.refresh();
WindyFactoryBean user1 = applicationContext.getBean("&user", WindyFactoryBean.class);
WindyFactoryBean.Person user2 = applicationContext.getBean("user", WindyFactoryBean.Person.class);
System.out.println(user1);
System.out.println(user2);
}
关于factoryBean的源码后面讲IOC时一并再讲。
1.6 supplier
/**
* supplier 方式
*/
private static void method6() {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
//applicationContext.registerBean(User.class);
applicationContext.registerBean(User.class, new Supplier<User>() {
@Override
public User get() {
User user = new User();
user.setName("windy");
return user;
}
});
//refresh能否去掉?
applicationContext.refresh();
User user = applicationContext.getBean("user", User.class);
System.out.println(user.getName());
}
通过看源码,其实registerBean最终也是调用的registerBeanDefinition
public <T> void registerBean(@Nullable String beanName, Class<T> beanClass,
@Nullable Supplier<T> supplier, BeanDefinitionCustomizer... customizers) {
ClassDerivedBeanDefinition beanDefinition = new ClassDerivedBeanDefinition(beanClass);
if (supplier != null) {
beanDefinition.setInstanceSupplier(supplier);
}
for (BeanDefinitionCustomizer customizer : customizers) {
customizer.customize(beanDefinition);
}
String nameToUse = (beanName != null ? beanName : beanClass.getName());
registerBeanDefinition(nameToUse, beanDefinition);
}
2.getBean
在讲ioc源码前,我们先简单看下整个ioc会有哪些步骤。
简单跑一下demo工程
可以看到ioc的基本流程如下。
接下来具体讲解该整个流程。
main 方法
public static void main(String[] args) {
//创建一个spring容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(IocConfig.class);
HelloService helloService = applicationContext.getBean("helloService", HelloService.class);
helloService.sayHello();
}
(贴的代码有部分删除)
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//❶
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
//❷
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {
/**
* containsBeanDefinition 中存在 beanName 相对应的 BeanDefinition
*/
try {
/**
* 合并父类相关属性
*/
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
/**
* 获取依赖。
* 在初始化 bean 时解析 depends-on 标签时设置
*/
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
// 迭代依赖
for (String dep : dependsOn) {
// 检验依赖的bean 是否已经注册给当前 bean
// 获取其他传递依赖bean
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
//没有注册到依赖bean中
// 注册到依赖bean中
registerDependentBean(dep, beanName);
try {
// 调用 getBean 初始化依赖bean
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
// Create bean instance.
if (mbd.isSingleton()) {
//❸
sharedInstance = getSingleton(beanName, () -> {
try {
/**
* beanName:bean 的名字
* mbd:已经合并了父类属性的(如果有的话)BeanDefinition
* args:用于构造函数或者工厂方法创建 bean 实例对象的参数
*/
//❹
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
}
return (T) bean;
}
❶处transformedBeanName主要是统一格式化处理beanName
比如前面factoryBean demo中通过applicationContext.getBean(“&user“, WindyFactoryBean.class)获取factoryBean,我们传入的name是&user,在这里会转成user,可能有人问,变成user,那和factoryBean包裹的bean的name不就一样了。这个时候你忘了一个细节,所有bean的信息都维护在BeanDefinition里,后面代码会判断是否是factoryBean.
2.1 getSingleton(❷)
我们知道spring会维护单例bean的生命周期,当getBean时会先从单例池里判断是否已经创建过了。
#DefaultSingletonBeanRegistry.class
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
接着
注意这里传入了一个true,这个方法在正在ioc过程中会调用几次。true表示允许对象提前暴露,主要用在处理循环依赖。
#DefaultSingletonBeanRegistry.class
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//❶
Object singletonObject = this.singletonObjects.get(beanName);
// 缓存中的 bean 为空,且当前 bean 正在创建
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//加锁保证 二级缓存添加和三级缓存删除操作的原子性,同时二级缓存和三级缓存就没有必要用concurrentHashMap了
synchronized (this.singletonObjects) {
//❷ 从 earlySingletonObjects 获取
singletonObject = this.earlySingletonObjects.get(beanName);
// earlySingletonObjects 中没有,且允许提前创建
if (singletonObject == null && allowEarlyReference) {
// ❸从 singletonFactories 中获取对应的 ObjectFactory
/**
* allowEarlyReference:从字面意思上面理解就是允许提前拿到引用。
* 其实真正的意思是是否允许从 singletonFactories 缓存中通过 getObject() 拿到对象,为什么会有这样一个字段呢?
* 原因就在于 singletonFactories 才是 Spring 解决 singleton bean 的诀窍所在
*/
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
// ObjectFactory 不为空,则创建 bean
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();//类似回调覆盖 执行lambda 表达式 AOP
this.earlySingletonObjects.put(beanName, singletonObject);//三级缓存升到二级缓存
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
我们知道spring主要通过map来管理单例bean的,在创建单例bean的时候涉及到三级缓存:
一级缓存 singletonObjects:bean name –> bean instance
二级缓存earlySingletonObjects:bean name –> bean instance,不一定完整
三级缓存 singletonFactories :bean name –> ObjectFactory
可以注意到除了一级缓存用的是concurrentHashMap外,其他两个缓存都是用的hashmap,原因在注释中已说明。
这里我们第一次获取bean,此时bean还标识为创建中,所以第一个判断条件不满足,直接返回null。
2.2 getSingleton(❸)
接下来调用重载的getSingleton方法创建Bean,不同于第❷步中的getSingleton
#DefaultSingletonBeanRegistry.class
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
//全局加锁
synchronized (this.singletonObjects) {
// 从缓存中检查一遍
//❶因为 singleton 模式其实就是复用已经创建的 bean 所以这步骤必须检查
Object singletonObject = this.singletonObjects.get(beanName);
// 为空,开始加载过程
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
//❷ 加载前置处理,将bean的状态修改为正在创建中
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// ❸初始化 bean
// 这个过程其实是调用 createBean() 方法
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
// 后置处理,将bean的状态从正在创建中移除
afterSingletonCreation(beanName);
}
// 加入缓存中
if (newSingleton) {
/**
* ❹一级缓存添加
*/
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
❶ 依旧从一级缓存singletonObjects中获取bean,此时也还是null.
❷beforeSingletonCreation
#DefaultSingletonBeanRegistry.class
protected void beforeSingletonCreation(String beanName) {
if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
}
❸singletonFactory.getObject()
这是一个函数回调接口实际上调用的是doGetBean中的createBean方法。
3.CreateBean
#AbstractAutowireCapableBeanFactory.class
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
RootBeanDefinition mbdToUse = mbd;
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
//❶ 验证和准备覆盖方法
try {
mbdToUse.prepareMethodOverrides();
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
//❷给 BeanPostProcessors 一个机会用来返回一个代理类而不是真正的类实例,如aop
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
//如果代理对象不为空,则直接返回代理对象,
//这一步骤有非常重要的作用,Spring 后续实现 AOP 就是基于这个地方判断的。
if (bean != null) {
return bean;
}
}
try {
//❸执行真正创建 bean 的过程
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
}
3.1 resolveBeforeInstantiation
实例化的前置处理
#AbstractAutowireCapableBeanFactory.class
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
//实例化前置处理
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
//初始化后置处理
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
@Nullable
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
if (result != null) {
return result;
}
}
}
return null;
}
这是spring的一个扩展接口,如果有我们有实现InstantiationAwareBeanPostProcessor类,则会调用。该前置处理是针对所有的bean,如果我们定义InstantiationAwareBeanPostProcessor,要确定好影响范围。
如:
前面一篇讲aop有讲过
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
//构建我们的缓存key
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
//如果被解析过直接返回
//❶
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
/**
* 判断是不是基础的Bean(Advice、PointCut、Advisor、AopInfrastructureBean)是就直接跳过
* 判断是不是应该跳过 (AOP解析直接解析出我们的切面信息(并且把我们的切面信息进行缓存),而事务在这里是不会解析的)
*/
//❷
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
//❸
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
3.2 doCreateBean
接下来是真正创建bean的步骤。
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
// BeanWrapper是对Bean的包装,其接口中所定义的功能很简单包括设置获取被包装的对象,获取被包装bean的属性描述器
BeanWrapper instanceWrapper = null;
// 单例模型,则从未完成的 FactoryBean 缓存中删除
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
// ❶使用合适的实例化策略来创建新的实例:工厂方法、构造函数自动注入、简单初始化
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 包装的实例对象
final Object bean = instanceWrapper.getWrappedInstance();
// 包装的实例对象的类型
Class<?> beanType = instanceWrapper.getWrappedClass();
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
//❷ 如果有后置处理,则允许后置处理修改 BeanDefinition
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
// applyMergedBeanDefinitionPostProcessors
//调用属性合并后置处理器, 进行属性合并
//这里会进行 一些注解 的扫描
//CommonAnnotationBeanPostProcessor -> @PostConstruct @PreDestroy @Resource
//AutowiredAnnotationBeanPostProcessor -> @Autowired @Value
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
mbd.postProcessed = true;
}
}
// ❸解决单例模式的循环依赖
// 单例模式 & 运行循环依赖&当前单例 bean 是否正在被创建
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
// 提前将创建的 bean 实例加入到三级缓存singletonFactories中
// 这里是为了后期避免循环依赖
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
Object exposedObject = bean;
try {
//❹对 bean 进行填充,将各个属性值注入,其中,可能存在依赖于其他 bean 的属性
// 则会递归初始依赖 bean
populateBean(beanName, mbd, instanceWrapper);
//❺调用初始化方法
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
/**
* ❻循环依赖处理
* Spring 循环依赖的场景有两种:
* 构造器的循环依赖
* field 属性的循环依赖
* 对于构造器的循环依赖,Spring 是无法解决的,只能抛出 BeanCurrentlyInCreationException 异常表示循环依赖
*/
if (earlySingletonExposure) {
// 获取 earlySingletonReference
Object earlySingletonReference = getSingleton(beanName, false);
// 只有在存在循环依赖的情况下,earlySingletonReference 才不会为空
if (earlySingletonReference != null) {
// 如果 exposedObject 没有在初始化方法中被改变,也就是没有被增强
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
// 处理依赖
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
}
}
}
// Register bean as disposable.
try {
// 注册 bean
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
return exposedObject;
}
❶createBeanInstance
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// 解析 bean,将 bean 类名解析为 class 引用
Class<?> beanClass = resolveBeanClass(mbd, beanName);
// 如果存在 Supplier 回调,则使用给定的回调方法初始化策略
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 如果工厂方法不为空,则使用工厂方法初始化策略
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
// 如果已缓存的解析的构造函数或者工厂方法不为空,则可以利用构造函数解析
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
// 已经解析好了,直接注入即可
if (resolved) {
if (autowireNecessary) {
// 自动注入,调用构造函数自动注入
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 使用默认构造函数构造
return instantiateBean(beanName, mbd);
}
}
// Need to determine the constructor...
// 确定解析的构造函数
// 主要是检查已经注册的 SmartInstantiationAwareBeanPostProcessor
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
// 构造函数自动注入
return autowireConstructor(beanName, mbd, ctors, args);
}
// No special handling: simply use no-arg constructor.
//使用默认构造函数注入
return instantiateBean(beanName, mbd);
}
如果我们不做其他处理,默认使用无参构造函数初始化对象。
❷applyMergedBeanDefinitionPostProcessors
这里会有一些注解的扫描,详见@Autowied原理
❸addSingletonFactory
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
}
继续看addSingletonFactory
#DefaultSingletonBeanRegistry.class
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(singletonFactory, "Singleton factory must not be null");
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.earlySingletonObjects.remove(beanName);
this.singletonFactories.put(beanName, singletonFactory);
this.registeredSingletons.add(beanName);
}
}
}
同时这段代码发生在 createBeanInstance() 方法之后,也就是说这个 bean 其实已经被创建出来了,但是它还不是很完美(没有进行属性填充和初始化)
,但是对于其他依赖它的对象而言已经足够了(可以根据对象引用定位到堆中对象),能够被认出来了。
3.3 populateBean 属性填充
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
/**
* 在设置属性之前给 InstantiationAwareBeanPostProcessors 最后一次改变 bean 的机会
*/
boolean continueWithPropertyPopulation = true;
// 是否持有 InstantiationAwareBeanPostProcessor
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
continueWithPropertyPopulation = false;
break;
}
}
}
}
// 如果后续处理器发出停止填充命令,则终止后续操作
if (!continueWithPropertyPopulation) {
return;
}
// bean 的属性值
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
// 将 PropertyValues 封装成 MutablePropertyValues 对象
// MutablePropertyValues 允许对属性进行简单的操作,
// 并提供构造函数以支持Map的深度复制和构造。
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// Add property values based on autowire by name if applicable.
// 根据名称自动注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// Add property values based on autowire by type if applicable.
// 根据类型自动注入
if (mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
// 是否已经注册了 InstantiationAwareBeanPostProcessors
boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
// 是否需要进行依赖检查
boolean needsDepCheck = (mbd.getDependencyCheck() != RootBeanDefinition.DEPENDENCY_CHECK_NONE);
if (hasInstAwareBpps || needsDepCheck) {
if (pvs == null) {
pvs = mbd.getPropertyValues();
}
// 从 bw 对象中提取 PropertyDescriptor 结果集
// PropertyDescriptor:可以通过一对存取方法提取一个属性
PropertyDescriptor[] filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
if (hasInstAwareBpps) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof InstantiationAwareBeanPostProcessor) {
// 对所有需要依赖检查的属性进行后处理
InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
pvs = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
if (pvs == null) {
return;
}
}
}
}
if (needsDepCheck) {
// 依赖检查,对应 depends-on 属性
checkDependencies(beanName, mbd, filteredPds, pvs);
}
}
if (pvs != null) {
// 将属性应用到 bean 中
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
postProcessAfterInstantiation在属性填充前,最后一次更改bean的机会。即实例化后置处理。这也是spring的扩展接口。
(下篇讲循环依赖处理。)
3.4 initializeBean 实例化
#AbstractAutowireCapableBeanFactory.class
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
//❶Aware织入
invokeAwareMethods(beanName, bean);
/**
* BeanPostProcessor 的作用:在 Bean 完成实例化后,
* 如果我们需要对其进行一些配置、增加一些自己的处理逻辑,那么请使用 BeanPostProcessor。
*/
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//❷初始化前置处理
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//❸初始化方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
if (mbd == null || !mbd.isSynthetic()) {
//❹初始化后置处理
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
❶Aware织入
#AbstractAutowireCapableBeanFactory.class
private void invokeAwareMethods(final String beanName, final Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
如我们常见的ApplicationContextAware,织入applicationContext对象。
❷applyBeanPostProcessorsBeforeInitialization初始化前置处理
#AbstractAutowireCapableBeanFactory.class
#List<BeanPostProcessor> beanPostProcessors = new ArrayList<>();
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
这也是spring的扩展之一
#AbstractAutowireCapableBeanFactory.class
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
// 如果实现了 InitializingBean 接口,则只掉调用bean的 afterPropertiesSet()
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
// 直接调用 afterPropertiesSet()
((InitializingBean) bean).afterPropertiesSet();
}
// 如果指定了 init-method(),则再调用制定的init-method
if (mbd != null && bean.getClass() != NullBean.class) {
String initMethodName = mbd.getInitMethodName();
if (StringUtils.hasLength(initMethodName) &&
!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
!mbd.isExternallyManagedInitMethod(initMethodName)) {
// 利用反射机制执行
invokeCustomInitMethod(beanName, bean, mbd);
}
}
}
❹applyBeanPostProcessorsAfterInitialization初始化后置处理
#AbstractAutowireCapableBeanFactory.class
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
Object current = beanProcessor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
这是我们一般扩展用的比较多的一个实现方式。
比如我们实现一个自定义的@Value注解。
1.定义注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyValue {
String value();
}
2. 后置处理给属性赋值
@Component
public class HelloBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof HelloService){
System.out.println("调用了BeanPostProcessor的postProcessAfterInitialization方法");
Class<?> clzz = bean.getClass();
for (Field field : clzz.getDeclaredFields()) {
if (field.isAnnotationPresent(MyValue.class)){
String value = field.getAnnotation(MyValue.class).value();
field.setAccessible(true);
try {
field.set(bean,value);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
return bean;
}
}
3. 应用
@MyValue("xxx")
private String name;
public void sayHello(){
System.out.println("hello :"+ name);
}
3.5 bean的依赖处理
截取上面doCreateBean部分代码
#AbstractAutowireCapableBeanFactory.class#doCreateBean
if (earlySingletonExposure) {
// 获取 earlySingletonReference
Object earlySingletonReference = getSingleton(beanName, false);
// 只有在存在循环依赖的情况下,earlySingletonReference 才不会为空
if (earlySingletonReference != null) {
// 如果 exposedObject 没有在初始化方法中被改变,也就是没有被增强
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
// 处理依赖
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
}
}这里调用前面分析的getSingleton(❷)
#DefaultSingletonBeanRegistry.class
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//❶
Object singletonObject = this.singletonObjects.get(beanName);
// 缓存中的 bean 为空,且当前 bean 正在创建
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//加锁保证 二级缓存添加和三级缓存删除操作的原子性,同时二级缓存和三级缓存就没有必要用concurrentHashMap了
synchronized (this.singletonObjects) {
//❷ 从 earlySingletonObjects 获取
singletonObject = this.earlySingletonObjects.get(beanName);
// earlySingletonObjects 中没有,且允许提前创建
if (singletonObject == null && allowEarlyReference) {
// ❸从 singletonFactories 中获取对应的 ObjectFactory
/**
* allowEarlyReference:从字面意思上面理解就是允许提前拿到引用。
* 其实真正的意思是是否允许从 singletonFactories 缓存中通过 getObject() 拿到对象,为什么会有这样一个字段呢?
* 原因就在于 singletonFactories 才是 Spring 解决 singleton bean 的诀窍所在
*/
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
// ObjectFactory 不为空,则创建 bean
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();//类似回调覆盖 执行lambda 表达式 AOP
this.earlySingletonObjects.put(beanName, singletonObject);//三级缓存升到二级缓存
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}因为bean已经实例化完成,所以不需要提前暴露。此时传入的值allowEarlyReference是false,
所以当从二级缓存中没有拿到singletonObject 后,不会继续从三级缓存中获取,因为第二个判断条件是false .所以到最后二级缓存没有对象。
创建bean的过程是个函数回调 的过程,创建好bean后回到getSingleton(❸)的第❸步,此时返回的bean是经过完整ioc返回的完整的bean
#DefaultSingletonBeanRegistry.class
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
Assert.notNull(beanName, "Bean name must not be null");
//全局加锁
synchronized (this.singletonObjects) {
// 从缓存中检查一遍
//❶因为 singleton 模式其实就是复用已经创建的 bean 所以这步骤必须检查
Object singletonObject = this.singletonObjects.get(beanName);
// 为空,开始加载过程
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
//❷ 加载前置处理,将bean的状态修改为正在创建中
beforeSingletonCreation(beanName);
boolean newSingleton = false;
boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
if (recordSuppressedExceptions) {
this.suppressedExceptions = new LinkedHashSet<>();
}
try {
// ❸初始化 bean
// 这个过程其实是调用 createBean() 方法
singletonObject = singletonFactory.getObject();
newSingleton = true;
}
finally {
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
// 后置处理,将bean的状态从正在创建中移除
afterSingletonCreation(beanName);
}
// 加入缓存中
if (newSingleton) {
/**
* ❹一级缓存添加
*/
addSingleton(beanName, singletonObject);
}
}
return singletonObject;
}
}
接下来看第❹步addSingleton
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}最终只有一级缓存singletonObjects中保存完整的bean对象。
4.总结
可以得出结论,当没有循环依赖产生时,整个ioc的过程只有一级缓存singletonObjects和三级缓存起了作用,二级缓存earlySingletonObjects自始至终都是空的。AOP源码分析那章也做了分析。一文弄懂AOP源码
(篇幅和时间关系,后续再将详细讲循环依赖解决和factoryBean的源码)。
最后祝所以程序员1024节日快乐。
关注我的你,是最香哒!
原文始发于微信公众号(小李的源码图):Spring IOC 源码一
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/145419.html