Bean的实例化和Bean的初始化有什么区别?

Bean的实例化是指创建Bean对象的过程,在Spring容器中,当Bean需要被使用时,会通过Bean的定义信息创建Bean对象,这个过程也叫做Bean的实例化。

而Bean的初始化是指在Bean对象被创建之后,Spring容器会执行一些额外的操作来准备Bean对象,使其可以被使用。这个过程也叫做Bean的生命周期,包括如下阶段:

  1. Bean的实例化
  2. 属性注入
  3. BeanPostProcessor的前置处理
  4. 初始化方法调用
  5. BeanPostProcessor的后置处理

其中,第2阶段是属性注入,是指将Bean的属性值设置到Bean对象中。第4阶段是初始化方法调用,是指在Bean对象创建完毕之后调用Bean中定义的初始化方法。初始化方法可以使用注解@PostConstruct标注,也可以在Bean定义中使用init-method属性指定。

因此,Bean的实例化和Bean的初始化是两个不同的概念,但是它们都是Bean的创建过程中的重要阶段。

1. Bean的实例化

在Spring容器中,Bean的实例化是通过BeanFactory接口的实现类DefaultListableBeanFactory来完成的。具体实现过程如下:

a. 读取并解析Bean的定义信息,包括Bean的名称、类型、作用域、依赖关系等。

b. 根据Bean的定义信息创建Bean实例,创建过程中会调用Bean的构造方法。

c. 将创建好的Bean对象保存到BeanFactory的缓存中,以供后续使用。

示例代码:

// 创建一个默认的可列表化的Bean工厂对象
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 创建一个通用的BeanDefinition对象
BeanDefinition beanDefinition = new GenericBeanDefinition();
// 设置BeanDefinition对象所对应的Bean的类名为com.example.MyBean
beanDefinition.setBeanClassName("com.example.MyBean");
// 将BeanDefinition对象注册到Bean工厂中,指定Bean的名称为myBean
beanFactory.registerBeanDefinition("myBean", beanDefinition);
// 通过Bean的名称获取注册的Bean对象,并强制转换为MyBean类型
MyBean myBean = (MyBean) beanFactory.getBean("myBean");

2. 属性注入

属性注入是指将Bean实例中的属性值设置为指定的值,可以通过以下两种方式进行注入:

a. 使用构造方法注入:在Bean的构造方法中接收一个或多个参数,并将这些参数注入到Bean实例的属性中。

b. 使用Setter方法注入:在Bean中定义与属性对应的Setter方法,容器会在创建Bean实例后调用这些Setter方法来进行属性注入。

示例代码:

public class MyBean {
  private String name;
  private int age;

  public MyBean(String name, int age) {
    this.name = name;
    this.age = age;
  }

  public void setName(String name) {
    this.name = name;
  }

  public void setAge(int age) {
    this.age = age;
  }
}

// 创建一个通用的Bean定义实例
BeanDefinition beanDefinition = new GenericBeanDefinition();
// 设置Bean的类路径为com.example.MyBean
beanDefinition.setBeanClassName("com.example.MyBean");
// 获取Bean的构造函数参数值,并添加两个泛型参数值"张三"和18
beanDefinition.getConstructorArgumentValues()
   .addGenericArgumentValue("张三")
   .addGenericArgumentValue(18);
// 创建DefaultListableBeanFactory实例,作为Bean工厂类
BeanFactory beanFactory = new DefaultListableBeanFactory();
// 将beanDefinition注册到Bean工厂,beanId为"myBean"
((DefaultListableBeanFactory) beanFactory)
   .registerBeanDefinition("myBean", beanDefinition);
// 从Bean工厂中获取beanId为"myBean"的Bean实例,并强制转换为MyBean类型
MyBean myBean = (MyBean) beanFactory.getBean("myBean");

3. BeanPostProcessor的前置处理

BeanPostProcessor是Spring框架中用于扩展Bean初始化过程的接口,它提供了前置处理和后置处理两个扩展点。在Bean初始化过程中,容器会自动检测容器中所有实现了BeanPostProcessor接口的类,并在需要时调用这些类中的方法。

前置处理指的是在Bean初始化方法调用之前,对Bean进行一些处理,例如修改Bean属性值或初始化Bean的状态等操作。前置处理方法的方法名前缀为postProcessBeforeInitialization。

示例代码:

// 自定义一个 BeanPostProcessor
public class MyBeanPostProcessor implements BeanPostProcessor {
  
  // 在初始化之前,处理 Bean
  @Override
  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    // 如果 Bean 是 MyBean 类型,就将其名称设置为 "李四"
    if (bean instanceof MyBean) {
      ((MyBean) bean).setName("李四");
    }
    return bean;
  }
}

// 创建一个 Bean 工厂
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

// 注册 MyBeanPostProcessor 到 Bean 工厂中
beanFactory.addBeanPostProcessor(new MyBeanPostProcessor());

// 创建一个 Bean 定义,并设置其类名为 "com.example.MyBean"
BeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClassName("com.example.MyBean");

// 注册 Bean 定义到 Bean 工厂中,Bean 的名称为 "myBean"
beanFactory.registerBeanDefinition("myBean", beanDefinition);

// 从 Bean 工厂获取名称为 "myBean" 的 Bean,并将其转换为 MyBean 类型
MyBean myBean = (MyBean) beanFactory.getBean("myBean");

4. 初始化方法调用

初始化方法调用是指在Bean创建完成并进行了属性注入后,容器会自动调用Bean中定义的初始化方法。初始化方法可以使用注解@PostConstruct标注,也可以在Bean定义中使用init-method属性指定。

示例代码:

// 定义一个名为MyBean的类
public class MyBean {
  // 声明一个名为name的私有字符串属性
  private String name;

  // 在构造函数执行后执行该方法
  @PostConstruct
  public void init() {
    // 将name属性赋值为"张三"
    this.name = "张三";
  }
}

// 创建一个名为beanDefinition的Bean定义对象
BeanDefinition beanDefinition = new GenericBeanDefinition();
// 设置bean的类名为"com.example.MyBean"
beanDefinition.setBeanClassName("com.example.MyBean");

// 创建一个名为beanFactory的Bean工厂对象
BeanFactory beanFactory = new DefaultListableBeanFactory();
// 将beanDefinition注册到beanFactory中,并设置bean的名字为"myBean"
((DefaultListableBeanFactory) beanFactory).registerBeanDefinition("myBean", beanDefinition);

// 从beanFactory中获取名字为"myBean"的Bean对象,并将其转换为MyBean类型
MyBean myBean = (MyBean) beanFactory.getBean("myBean");

5. BeanPostProcessor的后置处理

后置处理指的是在Bean初始化方法调用之后,对Bean进行一些处理,例如修改Bean属性值或修改Bean状态等操作。后置处理方法的方法名前缀为postProcessAfterInitialization。

示例代码:

// 自定义BeanPostProcessor,用于在bean初始化后修改bean的属性
public class MyBeanPostProcessor implements BeanPostProcessor {
  @Override
  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    // 如果bean是MyBean类型的,则修改它的name属性为"李四"
    if (bean instanceof MyBean) {
      ((MyBean) bean).setName("李四");
    }
    return bean;
  }
}

// 创建一个DefaultListableBeanFactory实例
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

// 将自定义的BeanPostProcessor添加到beanFactory中
beanFactory.addBeanPostProcessor(new MyBeanPostProcessor());

// 创建一个GenericBeanDefinition实例,指定bean的className
BeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClassName("com.example.MyBean");

// 将BeanDefinition注册到beanFactory中,使用beanName为"myBean"
beanFactory.registerBeanDefinition("myBean", beanDefinition);

// 从beanFactory中获取myBean实例,并强制类型转换为MyBean类型
MyBean myBean = (MyBean) beanFactory.getBean("myBean");
Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐