Spring註解學習之:Bean的初始化和銷燬

首先,一個Bean是有生命週期的,IOC容器幫我創建--->初始化---->銷燬Bean;通過配置文件的方式,可以再<bean/>標籤中進行參數設定,init-method屬性和destroy-method的屬性。通過該屬性,分別指定沒有參數的方法,進行初始化和銷燬操作;同樣的,我們可以通過註解的形式,來自定義初始化或者銷燬方法;

1、@Bean(initMethod = "",destroyMethod = "")

1、定義一個Student類
public class Student {
    public Student() {
        System.out.println("Student構造器方法開始執行...");
    }

    public void init(){
        System.out.println("Student初始化方法開始執行...");
    }
    public void destroy(){
        System.out.println("Student銷燬方法開始執行...");
    }
}

------------------------------------------------------------
2、MyConfig.class
@Configuration
public class MyConfig {

    @Bean(initMethod = "init",destroyMethod = "destroy")
    public Student student(){
        return new Student();
    }
}

首先第一種情況,只僅僅創建IOC容器,看下會有什麼結果,上代碼:

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootAnnocationApplicationTests {


    @Test
    public void contextLoads() {
        ApplicationContext alicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
    }

}



結果:
Student構造器方法開始執行...
Student初始化方法開始執行...
2019-04-25 10:15:26.529  INFO 9576 --- [       Thread-2] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'
Student銷燬方法開始執行...

可以看到,只是僅僅創建IOC容器,Student的無參構造方法,初始化方法,銷燬方法都有執行,why?因爲我們在創建bean的時候,默認是單實例的,而單實例的Bean會在IOC創建的時候創建,銷燬的時候銷燬。我們獲取兩個student,看看==是否爲true,上代碼:

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootAnnocationApplicationTests {


    @Test
    public void contextLoads() {
        ApplicationContext alicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
        Object student1 = alicationContext.getBean("student");
        Object student2 = alicationContext.getBean("student");
        System.out.println(student1 == student2);
    }

}


結果:
Student構造器方法開始執行...
Student初始化方法開始執行...
true
2019-04-25 10:21:49.300  INFO 5612 --- [       Thread-2] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'
Student銷燬方法開始執行...

打印結果符合預期效果!那這裏修改一下Bean的作用域爲prototype,看下打印結果,上代碼:

MyConfig.class

@Configuration
public class MyConfig {


    @Bean(initMethod = "init",destroyMethod = "destroy")
    @Scope("prototype")
    public Student student(){
        return new Student();
    }
}


--------------------------------------------------------
測試一:只創建IOC容器,看打印結果:
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootAnnocationApplicationTests {


    @Test
    public void contextLoads() {
        ApplicationContext alicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
    }

}

結果什麼也沒有

-----------------------------------------------------------
測試一:創建IOC容器,獲取2次Bean,看打印結果:
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootAnnocationApplicationTests {


    @Test
    public void contextLoads() {
        ApplicationContext alicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
        Object student1 = alicationContext.getBean("student");
        Object student2 = alicationContext.getBean("student");
        System.out.println(student1 == student2);
    }

}

結果:
Student構造器方法開始執行...
Student初始化方法開始執行...
Student構造器方法開始執行...
Student初始化方法開始執行...
false

當把Bean的作用域轉爲Prototype之後,創建IOC的時候,並沒有打印Student的無參構造方法和初始化方法,每次getBean的時候,都要打印,而且==爲false,符合多實例Bean的定義;還有一點要注意:多實例下的Bean,IOC容器直管創建,不管銷燬!!!!故而看不到有打印“Student銷燬方法開始執行...”這句話。

2、通過Bean實現InitializingBean, DisposableBean 接口,來實現Bean的初始化和銷燬方法;InitializingBean接口有一個afterPropertiesSet()的方法,該方法就是說再完成Bean的創建以及屬性設定完成之後執行,相當於初始化;DisposableBean接口有一個destroy()方法,用於銷燬Bean;上代碼:

1、自定義一個Student的bean,實現InitializingBean, DisposableBean接口

public class Student implements InitializingBean, DisposableBean {
    public Student() {
        System.out.println("Student構造器方法開始執行...");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("Student,afterPropertiesSet方法開始執行...");

    }

    @Override
    public void destroy() throws Exception {
        System.out.println("Student,destroy方法開始執行...");
    }
}
-------------------------------------------------------------------------
2、MyConfig.class
@Configuration
public class MyConfig {
    @Bean
    public Student student(){
        return new Student();
    }
}
------------------------------------------------------------------------
3、測試類及打印結果
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootAnnocationApplicationTests {
    @Test
    public void contextLoads() {
        ApplicationContext alicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
    }

}

結果:
Student構造器方法開始執行...
Student,afterPropertiesSet方法開始執行...
2019-04-25 10:37:53.386  INFO 9252 --- [       Thread-2] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'applicationTaskExecutor'
Student,destroy方法開始執行...

當然,這裏的Bean是單實例的,所以在IOC創建的時候就打印了,把Bean改爲多實例的,和上面的情況一樣,這裏就不說了;

3、JSR250的@PostConstruct來初始化,@PreDestroy來銷燬

4、BeanPostProcesser方式

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章