了解Bean的作用域与生命周期

一、Bean的作用域

1、了解作用域

源代码中限定程序中变量的可用范围,叫作作用域
Bean的作用域是指Bean在Spring整个框架中的某种行为模式,比如singleton单例作用域,就表示Bean在整个Spring中只有一份,它是全局共享的,一个人修改了Bean的属性,另一个人读取到的就是修改了的Bean

2、作用域问题

model包中创建一个普通类

package com.model;

public class Student {
    private String name;
    private String Address;

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", Address='" + Address + '\'' +
                '}';
    }

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

    public void setAddress(String address) {
        Address = address;
    }
}

Component包中创建一个“实体类”

package com.bit.component;

@Component
public class StudentComponent {
    @Bean
    public Student getStudent(){
        Student student = new Student();
        student.setName("刘文");
        student.setAddress("郑州路");
        return student;
    }
}

在Controller包中,创建两个不同的“操作者”

StudentControllerA
修改Bean的属性,“郑州路” —> “松岭路”

package com.bit.controller;

@Controller
public class StudentControllerA {

    @Autowired
    private Student student;

    public Student update(){
        System.out.println("student对象修改前: " + student);
        System.out.println("修改student");
        student.setAddress("松岭路");

        return student;
    }
}

StudentControllerB
获取Bean对象

package com.bit.controller;

@Controller
public class StudentControllerB {

    @Autowired
    private Student student;

    public Student getStudent(){
        return student;
    }
}

启动类 App

// 启动类
public class App {
    public static void main(String[] args) {
        // 获取 Spring 上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");

        StudentControllerA studentControllerA = context.getBean("studentControllerA", StudentControllerA.class);
        System.out.println(studentControllerA.update());
        
        StudentControllerB studentControllerB = context.getBean("studentControllerB", StudentControllerB.class);
        System.out.println(studentControllerB.getStudent());
        
         // 打印
         // 刘文 松岭路
         // 刘文 松岭路
    }
}

此处的Bean(Student)就是单例作用域(Singleton作用域),StudentControllerA和StudentController获取、修改的都是同一个对象

3、Bean的六种作用域

  1. singleton:单例作用域,Spring所有生态都支持

Bean在默认情况下是单例作用域
Bean在IoC容器中只有一个实例,每次获取(getBean())、装配(@Autowired)的Bean都是同一个对象(就可着一个人造)

  1. prototype:多例作用域(原型作用域),Spring所有生态支持

每次获取(getBean())、装配(@Autowired)Bean时,都要创建新的实例,所以每一次得到的都是新的对象(你玩你的,我玩我的,互不影响)
即使是在同一个类中,得到的也是不同的对象

  1. request:请求作用域,仅Spring MVC(Spring Web)支持

每次HTTP请求都会创建新的Bean的实例

  1. session:会话作用域,仅Spring MVC支持

在一个 http session 中,定义一个Bean实例

  1. application:全局作用域,仅Spring MVC支持

在一个 http application context中,定义一个Bean实例

  1. websocket:HTTP WebSocket作用域,仅Spring MVC支持

4、设置作用域

将 Student 类在存储到 Spring容器时,设置为全局作用域,解决上述问题

package com.bit.component;

@Component
public class StudentComponent {
    
    //    @Scope("prototype")
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    @Bean
    public Student getStudent(){
        Student student = new Student();
        student.setName("刘文");
        student.setAddress("郑州路");
        return student;
    }
}

启动类

// 启动类
public class App {
    public static void main(String[] args) {
        // 获取 Spring 上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");

        StudentControllerA studentControllerA = context.getBean("studentControllerA", StudentControllerA.class);
        System.out.println(studentControllerA.update());
        
        StudentControllerB studentControllerB = context.getBean("studentControllerB", StudentControllerB.class);
        System.out.println(studentControllerB.getStudent());
        
         // 打印
         // 刘文 松岭路
         // 刘文 郑州路
    }
}

二、Spring的执行流程

  1. 启动Spring容器(main启动时)
  2. 加载Spring的配置文件(xml),实例化并分配内存空间
  3. 扫描指定包路径,将添加注解(类注解、方法注解)的类注册到Spring容器中
  4. 装配Bean的属性(Bean中有些属性需要注入对象(@Autowired、@Resource))

三、Bean的生命周期

1、了解Bean的生命周期

Bean从创建到销毁的过程就叫做Bean的生命周期

  1. 实例化Bean,申请内存
  2. 设置Bean的属性(对象注入(@Autowired、@Resource))
  3. 初始化Bean
  • 调用各种Aware通知的方法,如BeanNameAware、BeanFactoryAware、ApplicationContextAware(均为接口)的方法
  • 执行BeanPostProcessor初始化前置方法
  • 执行@PostConstructor修饰的初始化方法
  • 执行InitialzingBean接口的afterPropertiesSet方法
  • 执行自己指定的init-method方法(在配置文件中(xml)中指定,没有指定就不调用)
  • 执行BeanPostProcessor初始化后置方法
  1. 使用Bean
  2. 销毁Bean
  • 调用@PreDestroy销毁前方法
  • 调用DisposableBean接口的destroy方法
  • 调用destroy-method方法

实例化和属性设置是Java级别的系统“事件”,其操作过程不可以人工干预和修改;
初始化是给开发者提供的,可以在实例化之后,类加载完成之前进行自定义“事件”处理

2、代码实现:

设置配置文件
指定init-method方法 和 destroy-method方法

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:content="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <!-- 配置一下:bean注解扫描的根路径(方面后面更简单存储对象到spring容器) 目的 提高效率-->
    <content:component-scan base-package="com.bit"></content:component-scan>
    <beans>
        <bean id="beanLife" class="com.bit.component.BeanLife" init-method="init" destroy-method="Mydestroy"></bean>
    </beans>
</beans>

Component包中创建一个“实体类”

package com.bit.component;

@Component
public class BeanLife implements BeanNameAware, InitializingBean, DisposableBean {

    /*
     * 初始化方法2
     * 方法名无所谓,只要是配置到 配置文件 中即可
     * */
    public void init(){
        System.out.println("执行了 init_method 方法");
    }

    /*
     * 初始化方法1
     * 只认这个注解,方法名无所谓的
     * */
    @PostConstruct
    public void postConstruct(){
        System.out.println("执行了 @PostConstrucet 注解修饰的方法");
    }


    // 构造方法
    public BeanLife(){
        System.out.println("执行构造方法");
    }

    /**
     * Aware通知的方法,此处实现了BeanNameAware接口,重写了setBeanName方法
     *
     */
    // 实现 BeanNameAware接口,重写setBeanName() 方法
    @Override
    public void setBeanName(String s) {
        System.out.println("执行 BeanNameAware setBeanName() 方法");
    }


    /*
     * 销毁前的方法1
     * 只认这个注解,方法名无所谓的
     */
    @PreDestroy
    public void preDestroy(){
        System.out.println("执行了 @PreDestory 注释修饰的方法");
    }

    /**
     * 销毁前的方法2
     */
    public void Mydestroy(){
        System.out.println("执行了 destroy_method 方法");
    }


    /**
     * InitialzingBean接口的afterPropertieSet方法
     *
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("执行了InitializingBean接口的 afterPropertiesSet方法");
    }

    /**
     * DisposableBean接口的destroy方法
     *
     */
    @Override
    public void destroy() throws Exception {
        System.out.println("执行了 DisposableBean 接口的destory方法");
    }
}

启动类

import com.bit.*;

// 启动类
public class App {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context1 = new ClassPathXmlApplicationContext("spring-config.xml");
        BeanLife beanLife = context1.getBean("beanLife", BeanLife.class);
        System.out.println(beanLife);
        context1.destroy();
    }
}

打印结果
在这里插入图片描述

整个项目的目录结构
在这里插入图片描述

aware - 意识到
processor - 处理器
construct - 建设
initialzing - 初始化
properties - 性能

disposable - 一次性

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

威少总冠军

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值