天天看點

Spring——Bean的作用域和生命周期lombok使用Bean的作用域Spring執行流程Bean的生命周期

lombok使用

當我們建立一個類時,裡面會涉及到很多的get,set和構造方法,我們可以使用lombok來簡化代碼

引入依賴

去maven中央倉庫搜尋lombok

Spring——Bean的作用域和生命周期lombok使用Bean的作用域Spring執行流程Bean的生命周期

選擇一個版本

Spring——Bean的作用域和生命周期lombok使用Bean的作用域Spring執行流程Bean的生命周期

複制其中的代碼

Spring——Bean的作用域和生命周期lombok使用Bean的作用域Spring執行流程Bean的生命周期

導入到我們的項目中

Spring——Bean的作用域和生命周期lombok使用Bean的作用域Spring執行流程Bean的生命周期

在idea的設定中添加lombok插件

Spring——Bean的作用域和生命周期lombok使用Bean的作用域Spring執行流程Bean的生命周期

這樣的話,我們就可以使用注解來替代寫代碼了

lombok常用注解

注解 功能
@Getter 自動添加Getter方法
@Setter 自動添加Setter方法
@ToString 自動添加toString方法
@EqualsAndHashCode 自動添加equals和hashCode方法
@NoArgsConstructor 自動添加無參數構造方法
@AllArgsConstructor 自動添加全部參數的構造方法
@NonNull 屬性不能為空
@RequiredArgsConstructor 自動添加必需屬性的構造方法
@Data 包含上述注解的所有功能

Bean的作用域

代碼案例

當我們建立了一個User類

package com.demo.model;

import lombok.Data;

@Data
public class User {
    private int id;
    private String name;
    private String password;
}

           

在UserBean中,我們建立了一個user1,将其姓名設定為“san”

@Component
public class UserBeans {
    @Bean
    public User user1(){
        User user = new User();
        user.setId(1);
        user.setName("san");
        user.setPassword("123");
        return user;
    }
}

           

小a寫了一個關于UserController的類,在其中,她用屬性注入獲得user1,并且在自己的getUser方法中,用u引用了user1,更改其姓名為“si”,并列印相關屬性

/**
 * author:小a
 */
@Controller
public class UserController {
    @Autowired
    private User user1;

    public void getUser(){
        System.out.println("User1: " + user1.toString());
        User u = user1;
        u.setName("si");
        System.out.println("U: " + u.toString());
    }
}

           

小b寫了一個UserAdviceController類,也用屬性注入的方式獲得user1,并在getUser方法中列印其相關屬性

/**
 * author:小b
 */
@Controller
public class UserAdviceController {
    @Resource
    private User user1;

    public void getUser(){
        System.out.println("b的user1 : " + user1);
    }
}
           

在主程式中擷取小a的UserController和小b的UserAdviceController,并分别調用其getUser方法

public class App {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        UserController uc = context.getBean("userController",UserController.class);
        uc.getUser();

        UserAdviceController uac = context.getBean("userAdviceController", UserAdviceController.class);
        uac.getUser();
    }
}

           

最終我們可以發現,小a将user更改了姓名為“si”,導緻小b這裡的user的姓名也被更改為“si”

Spring——Bean的作用域和生命周期lombok使用Bean的作用域Spring執行流程Bean的生命周期

這是由于Bean的預設作用域為singleton,也就是單例模式,所有人擷取的都是同一個對象,是以一個人改變了對象的屬性,其他人的對象的屬性也會被改變

Bean一共有下面幾種作用域:

  • singleton:單例作用域,整個IoC容器隻存在一個執行個體
  • prototype:原型作用域,每次Bean請求都建立新的執行個體
  • request:請求作用域,每次http請求建立新的執行個體
  • session:會話作用域,每次會話建立新的執行個體
  • application:全局作用域,一個http servlet context中定義一個Bean執行個體
  • websocket:HTTP WebSocket作用域,一個HTTP WebSocket中定義一個Bean執行個體

需要注意的是前兩個作用域是spring中的,後四個是spring mvc中的

設定作用域

使用@Scope注解可以設定Bean的作用域

@Component
public class UserBeans {
    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public User user1(){
        User user = new User();
        user.setId(1);
        user.setName("san");
        user.setPassword("123");
        return user;
    }
}

           

設定為原型作用域後,小b的user的姓名就不會改為“si”了

Spring——Bean的作用域和生命周期lombok使用Bean的作用域Spring執行流程Bean的生命周期

Spring執行流程

Spring執行一般分為下面幾步

  1. 啟動Spirng容器
  2. 執行個體話Bean
  3. 将Bean注冊到Spring中
  4. 将Bean注入到類中

Bean的生命周期

Bean的生命周期一般為下面幾步:

  1. 執行個體話Bean(配置設定記憶體空間)
  2. 設定屬性(Bean的注入)
  3. Bean的初始化
  4. 使用Bean
  5. 銷毀Bean

其中Bean初始化中有這樣幾步:

  • 實作各種Aware通知方法
  • 執行BeanPostProcessor初始化前置方法
  • 執行BeanPostConstruct初始化方法
  • 執行自己制定的init-method方法
  • 執行BeanPostProcessor初始化後置方法

我們寫一個類,繼承BeanNameAware,可以重寫其中的setBeanName,我們再通過@PostConstruct來執行其方法

//@Component
public class BeanLifeComponent implements BeanNameAware {

    @Override
    public void setBeanName(String s) {
        System.out.println("執行了通知方法");
    }

    @PostConstruct
    public void postConstruct(){
        System.out.println("執行了postConstruct");
    }

    public void init(){
        System.out.println("執行了init method方法");
    }

    @PreDestroy
    public void preDestroy(){
        System.out.println("執行preDestroy方法");
    }
}

           

在主程式中調用相關的方法

import com.demo.component.BeanLifeComponent;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App2 {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext =
                new ClassPathXmlApplicationContext("spring-config.xml");
        BeanLifeComponent beanLifeComponent =
                applicationContext.getBean("myComponent", BeanLifeComponent.class);
        System.out.println("使用bean");
        applicationContext.destroy();
    }
}
           

我們可以看到執行順序和我們的預期是一緻的

Spring——Bean的作用域和生命周期lombok使用Bean的作用域Spring執行流程Bean的生命周期