bena的初始化的过程中, 我们作为spring框架的使用者,spring允许我们干预bean的生命周期过程。
代码Github地址:https://github.com/abelzha/spring-framework
代码包含springframework 5.2.0.BUILD-SNAPSHOT版本源码
1. 干预方法
通过@Bean
(org.springframework.context.annotation.Bean)注解指定initMethod
和destroyMethod
使用示例:
initbean.AppConfigInit.java
package initbean;
import org.springframework.context.annotation.*;
@EnableAspectJAutoProxy
@Configuration
@ComponentScan("initbean")
public class AppConfigInit {
@Bean(initMethod = "initPerson", destroyMethod = "destroyPerson")
@Scope("prototype")
public Person person(){
return new Person();
}
}
initbean.InitMain.java
package initbean;
import aspectdemo.AppConfigAspect;
import aspectdemo.PersonService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.util.Arrays;
public class InitMain {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfigInit.class);
System.out.println(Arrays.asList(context.getBeanFactory().getBeanDefinitionNames()).toString().replaceAll(",", "\n"));
Person person = context.getBean(Person.class);
System.out.println(person.getName());
context.close();
}
}
initbean.Person.java
package initbean;
import org.springframework.stereotype.Component;
@Component
public class Person {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void initPerson(){
System.out.println("initPerson");
this.name = "kobe";
}
//Multiple instances will not call
public void destroyPerson(){
System.out.println("destoryPerson");
}
}
运行结果:(因为已经标注@Scope("prototype")
所以destroyMethod 不会被调用, 由此可见SpringIOC容器只负责单实例bean的销毁工作)
@Bean(initMethod = "initPerson", destroyMethod = "destroyPerson")
@Scope("prototype")
public Person person(){
return new Person();
}
调用顺序:先调用new Person()无参构造函数——>initMethod方法
2. 源码分析
initPerson方法的调用栈截图如下:
从调用栈也能看出Bean的实例化的时机是:第一次获取bean的实例对象(容器内部第一次获取或者容器外部第一次获取)。
PS:IOC启动时,只是加载了bean的定义信息(BeanDefinition)放到BeanDefinitionMap中。
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean
/**
* Actually create the specified bean. Pre-cre