Spring 的执行流程以及 Bean 的作用域和生命周期

文章目录

  • Bean 的作用域
    • 更改作用域的方式
    • singleton
    • prototype
  • Spring 执行流程
  • Bean 的生命周期

Bean 的作用域

Spring 容器在初始化⼀个 Bean 的实例时,同时会指定该实例的作用域。Bean 有6种作用域

  1. singleton:单例作用域
  2. prototype:原型作用域(多例作用域)
  3. request:请求作用域 (一个http 请求共享一个 Bean)
  4. session:会话作用域 (一个会话共享一个 Bean)
  5. application:全局作用域 (一个上下文对象共享一个 Bean)
  6. websocket:HTTP WebSocket 作用域(只适用于Spring WebSocket 项目)

其中后面四种是基于 Spring MVC 生效的

更改作用域的方式

使用 @Scope 标签就可以用来声明 Bean 的作用域,不指定默认为 singleton(单例)作用域

方式一:直接设置值

@Scope("prototype")
public class User {
    private Integer id = 1;
    private String name = "张三";

    @Override
    public String toString() {
        return "UserController{" +
                "id = " + id + ", " +
                "name = " + name +
                '}';
    }
}

方式二:使用枚举设置

@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class User {
    private Integer id = 1;
    private String name = "张三";

    @Override
    public String toString() {
        return "UserController{" +
                "id = " + id + ", " +
                "name = " + name +
                '}';
    }
}

singleton

作用域下的Bean在IoC容器中只存在⼀个实例:获取Bean及装配Bean都是同⼀个对象。

通常Bean对象的属性状态不需要更新的时候使用。

该种作用域也是 Bean 默认的作用域

@Getter // Lombok
@Setter // Lombok
@Controller
public class User {
    private Integer id = 1;
    private String name = "张三";

    @Override
    public String toString() {
        return "UserController{" +
                "id = " + id + ", " +
                "name = " + name +
                '}';
    }
}
public class Start {
    public static void main(String[] args) {
        // 获取 Spring 的上下文对象
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        // 获取 Bean 对象
        User user1 = context.getBean("user", User.class);
        System.out.println("user1 -> " + user1);
        user1.setId(2);
        user1.setName("王五");

        User user2 = context.getBean("user", User.class);
        System.out.println("user2 -> " + user2);
    }
}

Spring 的执行流程以及 Bean 的作用域和生命周期_第1张图片

可以看到,当第一次获取 bean 时在没有任何修改的情况下,打印的结果是初始值。但对这个 bean 进行修改后,之后再次获取该 bean 的结果就是修改后的结果

prototype

每次对该作用域下的Bean的请求都会创建新的实例,也就是说获取Bean 和装配Bean(即通过@Autowired注入)都是新的对象实例。

@Getter // Lombok
@Setter // Lombok
@Controller
@Scope("prototype")
public class User {
    private Integer id = 1;
    private String name = "张三";

    @Override
    public String toString() {
        return "UserController{" +
                "id = " + id + ", " +
                "name = " + name +
                '}';
    }
}

Spring 的执行流程以及 Bean 的作用域和生命周期_第2张图片

此时,user1 和 user2就互不干扰了

Spring 执行流程

分为四个步骤

  1. 启动 Spring 容器(加载配置文件)
  2. 实例化 Bean(分配内存空间)
  3. Bean 注册到 Spring 中(存)
  4. 将 Bean 装配到需要的类(取)

Bean 的生命周期

Bean 的生命周期分为五大部分

  1. 实例化 Bean(分配内存空间)
  2. 设置属性(注入和装配)
  3. Bean 初始化
    1. 实现各种 Aware 通知的方法(例如 BeanNameAware,BeanFactoryAware的接口方法)
    2. 执行 BeanPostProcessor 初始化前置方法
    3. 执行 @PostConstruct 初始化方法,依赖注入操作之后被执行
    4. 如果有指定init-method 方法则执行
    5. 执行 BeanPostProcessor 初始化后置方法
  4. 使用 Bean
  5. 销毁 Bean(销毁方法例如:如 @PreDestroy、DisposableBean 接口方法、destroy-method)
@Controller
public class User {
    private Integer id = 1;
    private String name = "张三";

    // 初始化
    @PostConstruct
    public void PostConstruct(){
        System.out.println("执行初始化");
    }

    // 指定 init-method 方法
    public void Init(){
        System.out.println("执行Init-method方法");
    }

    // 销毁
    @PreDestroy
    public void Des(){
        System.out.println("执行销毁");
    }

    @Override
    public String toString() {
        return "UserController{" +
                "id = " + id + ", " +
                "name = " + name +
                '}';
    }
}

如果需要使用指定的 init-method 方法,需要在xml 文件进行配置

<bean id="user" class="spring.demo.entity.User" init-method="Init">bean>

接着启动类启动

public class Start {
    public static void main(String[] args) {
        // 获取 Spring 的上下文对象
        ApplicationContext context =
                new ClassPathXmlApplicationContext("spring-config.xml");
        // 获取 Bean 对象
        User user1 = context.getBean("user", User.class);
        System.out.println(user1);
        user1.Des();
    }
}

Spring 的执行流程以及 Bean 的作用域和生命周期_第3张图片

你可能感兴趣的:(Spring,spring,java)