首先,一個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方式