Spring bean初始化(2) - bean实例化
XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("/spring-code-test.xml"));
// bean实例化是由getBean调用触发的
TestBean bean = (TestBean) bf.getBean("testbean");
上一节讲了上面的第一步,载入和解析xml,此步完成后,是将bean的定义转为BeanDefinition对象, getBean方法实际将BeanDefinition的信息进行实例化。
循环依赖为什么使用3级缓存 https://www.cnblogs.com/asker009/p/14376955.html
下面讲一下实例化过程
// AbstractBeanFactory 类
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// 先获取当前bean,如果能获取到bean对象,
// 或者能获取到bean对应的 ObjectFactory.getObject() 返回的对象
// ObjectFactory.getObject() 就是为了解决单例的循环依赖问题的,后面详细说
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// 普通bean,此方法不做处理,如果是 FactoryBean,
// 实际会返回 FactoryBean.getObject()返回的对象
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
//略过 当前beanfactory没有bean的话,会查询parent beanfactory
try {
// 将beanDefinition转化为RootBeanDefinition, bean的创建都是基于RootBeanDefinition的
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// Guarantee initialization of beans that the current bean depends on.
// 若bean没有没创建过,则开始创建bean,实际会调用ObjectFactory中getObject方法,
// 进而调用 createBean 方法
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
// prototype类型不允许循环依赖,因为它是使用时创建,没有单例相关的缓存协助解决循环依赖
else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}
else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
}
}
}
// Check if required type matches the type of the actual bean instance.
return (T) bean;
}
对于如何解决单例模式的bean的循环依赖问题,实际是通过缓存记录解决的,假设A 依赖B, B依赖A, 创建A对象的时候,会先实例化A,然后将A的ObjectFactory对象放入缓存 singletonFactories,然后发现A的属性注入B,开始B的创建,实例化B,将B的ObjectFactory对象放入 singletonFactories, 然后发现依赖A,进行A的实例化,进入上面代码的方法getSingleton(beanNam),此时可以得到A在singletonFactories的对象,虽然A没有完初始化完成,但是此时A的引用已经拿到,可以继续完成B的初始化和属性注入,B完成后,继续A的依赖注入B和A的初始化。getSingleton的代码如下
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 从已经完成创建的bean对象缓存中查找,找到则返回
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 从 earlySingletonObjects 中找
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
// 没有找到,则去 singletonFactories 找
// 正在创建的对象会先将ObjectFactory放入 singletonFactories
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
// 加入缓存,下次访问提高效率
this.earlySingletonObjects.put(beanName, singletonObject);
// 这两个缓存是互斥的,上面的加了,下面这个就没用了
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
下面重点讲一下创建bean的过程, 即 createBean()方法的具体实现
// AbstractAutowireCapableBeanFactory 类
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) {
try {
// BeanPostProcessors 前置处理,可以创建代理
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
// 创建bean, 里面仍然可以 有 BeanPostProcessors 的代理可能
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
urn beanInstance;
}
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
// 将 RootBeanDefinition 实例化为 BeanWrapper, 后面都是基于这个对象操作
// instanceWrapper已经是对象地址引用了
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
// 这一步就是为了解决循环依赖的,将bean的ObjectFactory对象放入缓存
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
// 属性注入和进行bean的其他初始化
Object exposedObject = bean;
try {
// 属性注入,包括bean属性注入,注入bean属性,会先实例化相应的bean
populateBean(beanName, mbd, instanceWrapper);
if (exposedObject != null) {
// 会调用配置的init-method方法,
// 里面还会调用 BeanPostProcessors,进行处理,AOP 的代理就是在这里面触发
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
}
分享到:
相关推荐
进入`doGetBean()`方法,这是Bean实例化的关键步骤。`doGetBean()`会处理Bean的依赖注入、类型检查等操作。 7. **创建Bean**: `createBean(beanName, mbd, args)`在`AbstractAutowireCapableBeanFactory`中实现...
但是,这并不总是可靠的,因为Spring通常会延迟初始化Bean,除非显式要求或存在依赖关系。 2. **依赖注入**:Spring容器会根据Bean之间的依赖关系来决定实例化顺序。如果一个Bean依赖于另一个Bean,那么被依赖的...
在"Spring--2.Spring 中的 Bean 配置-2-2"这个主题下,我们将深入探讨如何在Spring中进行Bean的详细配置。 1. **XML配置方式:** 在早期版本的Spring中,Bean的配置主要通过XML文件来完成。一个典型的`beans`标签...
在Spring框架中,我们可以使用多种方式来初始化Bean,下面我们将介绍两种常见的方式: 1、使用@Bean的initMethod 在使用@Bean注解时,我们可以使用initMethod属性来指定Bean的初始化方法。例如: ```java @Bean...
以上是Spring中基于XML的Bean配置的基本知识点,通过这些配置,我们可以精细控制Spring容器如何管理和实例化Bean,以及它们之间的依赖关系。随着Spring的发展,Java配置和注解配置逐渐成为主流,它们提供了更简洁、...
3. **@PostConstruct与初始化回调**:Spring允许我们在Bean初始化后执行特定代码,通常通过`@PostConstruct`注解的方法来实现。如果这个方法被意外地调用了两次,那么Bean也会被构造两次。检查是否有多处调用或配置...
在Spring框架中,bean的实例化是其核心功能之一,它允许我们管理应用程序中的对象生命周期。本篇将详细探讨两种工厂方法——实例工厂方法和静态...在实际项目中,应根据实际情况权衡利弊,选择最适合的Bean实例化策略。
Spring Bean 加载过程是 Spring 框架中最核心的部分之一,涉及到 ApplicationContext 的初始化、Bean 的加载和注册等过程。在 Spring Boot 应用程序中,SpringApplication 负责加载和管理 Bean。 SpringApplication...
- **实例化**:Spring通过`Class.forName()`或`new`关键字实例化Bean。如果在XML配置中指定了`class`属性,Spring将根据该属性创建Bean。 - **属性注入**:Spring会将依赖注入到Bean中,包括值注入(value,ref)...
在Spring框架中,Bean配置是核心概念之一,它关乎到对象的创建、初始化、装配以及管理。本节我们将深入探讨Spring中的Bean配置,主要关注如何通过XML、注解以及Java配置方式来管理Bean。 首先,让我们从XML配置说起...
- 初始化:Spring容器在创建Bean实例时,会执行初始化过程,包括实例化、属性设置(通过setter方法或构造函数注入)、初始化回调(如`InitializingBean`接口的`afterPropertiesSet()`方法或`@PostConstruct`注解的...
一旦XML配置加载到Spring容器中,容器将根据配置创建Bean实例,并按照定义进行初始化、依赖注入,最后完成Bean的生命周期管理。 10. **实践操作**: 在实际开发中,我们可以使用Eclipse的Spring插件来简化Bean...
在Spring框架中,"工厂Bean"是一个非常关键的概念,它扩展了传统的Bean定义,使得我们可以在Spring IoC容器中创建自定义的实例化逻辑。工厂Bean允许开发者在对象实例化时进行更复杂的控制,比如引入特定的初始化过程...
此外,Spring提供了一种名为BeanPostProcessor的接口,它允许我们自定义Bean实例化和初始化过程中的逻辑。通过实现`postProcessBeforeInitialization()`和`postProcessAfterInitialization()`方法,可以在Bean初始化...
- **init-method属性**:指定Bean初始化方法,通常用于资源的初始化。 - **destroy-method属性**:指定Bean销毁方法,用于清理资源。 - **factory-bean/factory-method属性**:通过工厂方法创建Bean。`factory-...
- 容器在创建Bean实例时调用初始化方法,在销毁Bean实例前调用销毁方法。 - Bean的生命周期过程包括实例化、属性赋值、BeanNameAware和BeanFactoryAware接口方法调用、BeanPostProcessor接口方法调用、...
Spring允许自定义BeanPostProcessor,它们在Bean实例化后执行特定的处理,比如AOP代理。这些后处理器将在Bean实例化后,初始化前介入。 7. **Bean初始化**: 实例化完成后,Spring会执行Bean的初始化方法,包括...
整个Spring Bean的生命周期流程是:如果有Bean实现了InstantiationAwareBeanPostProcessor接口,则会在Bean实例化前后被调用。Spring容器首先对Bean进行实例化,默认情况下Bean是单例的。实例化完成后,如果有Bean...
在本篇文章中,我们将深入探讨Spring源码中关于Bean初始化的过程,特别是`finishBeanFactoryInitialization()`方法和`preInstantiateSingletons()`方法。 首先,`finishBeanFactoryInitialization(Confi...
默认情况下,`lazy-init`的值为`default`或`false`,意味着容器启动时就会初始化Bean。 Bean的初始化过程包括以下几个步骤: 1. **装载Bean定义**:Spring容器读取XML配置文件,解析Bean的定义,包括其类型、依赖...