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