Spring bean生命周期

一、Bean实例化

1.1 加载Spring Bean

通过XML、Java annotation(注解)以及Java Configuration(配置类)等方式加载Spring
Bean:这是指在Spring容器启动时,通过配置文件、注解或配置类等方式告诉Spring框架需要创建哪些Bean。

1.2. 解析Bean的定义

BeanDefinitionReader:这是一个解析器,它将Bean的定义解析成Spring内部的BeanDefinition结构。可以将其理解为将配置文件中的标签转换为Spring框架内部使用的数据结构。

1.3. Bean属性定义

BeanDefinition:它包含了Bean的各种属性和方法,例如id(标识符)、class(类名)、scope(作用域)、ref(依赖的Bean)等。BeanDefinition实际上是将配置文件中的标签的定义信息存储到对应的BeanDefinition属性中。

1.4. BeanFactoryPostProcessor 扩展接口

BeanFactoryPostProcessor:这是Spring容器的扩展接口,它在Spring容器加载完BeanDefinition之后、Bean实例化之前执行。它可以对Bean的元数据(BeanDefinition)进行加工处理,例如填充或修改BeanDefinition的属性。

1.5. 实例化Bean对象

BeanFactory:它是Bean的工厂,根据我们的要求生产各种不同的Bean。BeanFactory根据配置文件中的BeanDefinition信息来实例化Bean对象,并进行属性赋值。(根据class属性反射机制实例化对象,反射赋值设置属性)

1.6. Aware感知

Aware 感知是一种机制,它允许在Bean的生命周期中获取对Spring容器的访问权限。通过实现相应的Aware接口,Bean可以获得与Spring容器的交互能力,以便在特定的生命周期阶段执行自定义操作。

在Spring框架中,有多个Aware接口可供实现,每个接口都提供了不同的功能。以下是一些常见的Aware接口及其作用:

  • BeanNameAware:通过实现BeanNameAware接口,Bean可以获取自己在Spring容器中的名称。这对于需要知道自己在容器中的标识的Bean非常有用。

  • ApplicationContextAware:通过实现ApplicationContextAware接口,Bean可以获取对Spring应用上下文的引用。这使得Bean能够在需要时访问Spring容器中的其他Bean或执行其他与容器相关的操作。

  • BeanFactoryAware:通过实现BeanFactoryAware接口,Bean可以获取对Spring Bean工厂的引用。这使得Bean能够在需要时访问Bean工厂中的其他Bean或执行其他与Bean工厂相关的操作。

    通过实现这些Aware接口,Bean可以在初始化过程中获得对Spring容器的访问权限,并在需要时执行特定的操作。这为开发人员提供了更大的灵活性和控制权,使得他们能够根据自己的需求自定义Bean的行为。

1.7. 初始化方法

如果Bean定义中指定了初始化方法,容器会在属性赋值完成后调用该方法进行一些初始化操作。可以使用@PostConstruct注解或者实现InitializingBean接口来指定初始化方法。如果Bean在Spring配置文件中配置了 init-method 属性,则会自动调用其配置的初始化方法。

1.8. 后置处理

BeanPostProcessor:它是一个后置处理器,在Bean对象实例化和依赖注入完成后,在显示调用初始化方法之前或之后添加自定义的逻辑。可以将其类比为AOP中的环绕通知。

注:只有当检测到Bean对象实现了BeanPostProcessor接口时,才会执行Before和After方法。

BeanPostProcessor的执行顺序是:

Before方法 -> 初始化Bean(InitializingBean接口和init-method方法)-> After方法。

1.9. destroy 销毁

destroy:这是Bean的销毁阶段,如果这个Bean的Spring配置中配置了destroy-method属性,在Spring容器关闭时调用。在销毁阶段,可以执行一些清理工作,例如释放资源等。

二、Bean的单例与多例模式

2.1 单例模式

单例模式是指在整个应用程序中只创建一个Bean实例。
当使用单例模式时,Spring容器在首次请求该Bean时创建一个实例,并将其缓存起来。之后的每次请求都会返回同一个实例。

  • 优点:减少了对象创建和销毁的开销,节省了系统资源。
  • 缺点:由于共享同一个实例,可能导致状态信息被多个线程共享,需要注意线程安全问题。

2.2 多例模式

多例模式是指每次请求时都会创建一个新的Bean实例。
当使用多例模式时,Spring容器在每次请求该Bean时都会创建一个新的实例,而不是返回之前创建的实例。

  • 优点:每次请求都会返回一个全新的实例,避免了状态信息共享的问题。
  • 缺点:频繁创建和销毁对象可能导致系统资源消耗增加。

2.3 实例

假设我们有一个简单的Number类,用于计数:

public class Number {
    private int count;
 
    public int getCount() {
        return count;
    }
 
    public void increment() {
        count++;
    }
}

我们将使用Spring配置来演示单例和多例模式的区别。

2.3.1 单例模式:

<bean id="counter" class="com.xqx.Number" scope="singleton" />
public class SingletonDemo {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Counter count1 = context.getBean("number", Number.class);
        Counter count2 = context.getBean("number", Number.class);
 
        counter1.increment();
        System.out.println("Count 1: " + count1.getCount()); // 输出:Count 1: 1
        System.out.println("Count 2: " + count2.getCount()); // 输出:Count 2: 1
    }
}

在单例模式下,count1和count2引用的是同一个实例,因此它们的计数值是相同的。

2.3.2 多例模式:

<bean id="counter" class="com.xqx.Number" scope="prototype" />
public class PrototypeDemo {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
         Counter count1 = context.getBean("number", Number.class);
        Counter count2 = context.getBean("number", Number.class);
 
        counter1.increment();
        System.out.println("count 1: " + count1.getCount()); // 输出:count 1: 1
        System.out.println("count 2: " + count2.getCount()); // 输出:Count 2: 0
    }
}

在多例模式下,count1和count2引用的是不同的实例,因此它们的计数值是独立的。

2.4 总结

单例模式和多例模式各有优缺点,具体使用哪种模式取决于应用程序的需求和设计考虑。在需要共享状态或资源的场景下,可以使用单例模式;在需要独立状态或避免状态共享的场景下,可以使用多例模式。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值