AnnotationConfigApplicationContext源码解析&SpringBean的生命周期
1 BeanFactory与ApplicationContext区别
AnnotationConfigApplicationContext注解启动原理
Spring有两个核心接口:BeanFactory和ApplicationContext,其中ApplicationContext是BeanFactory的子接口。它们都可以代表Spring容器,Spring容器是生成Bean实例的工厂,并且管理容器中的Bean。
BeanFactory与ApplicationContext之间区别是什么?
- BeanFactory负责读取bean配置文档,管理bean的加载,实例化,维护bean之间的依赖关系,负责bean的生命周期。
- ApplicationContext除了提供上述BeanFactory所能提供的功能外,还提供了更完整的框架功能:
a. 国际化支持
b. 资源访问:Resource rs = ctx.getResource(“classpath:config.properties”), “file:c:/config.properties”
c. 事件传递:通过实现ApplicationContextAware接口 - 常用的获取ApplicationContext的方法:
ClassPathXMLApplicationContext:从classpath的xml配置文件创建,可以从jar包中读取配置文件;
AnnotationConfigApplicationContext:基于注解使用,不需要配置文件,采用java配置类和各种注解来配置
public class V2Spring {
public static void main(String[] args) {
// 1.基于注解方式实现启动
ApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
// 2.使用xml启动的话
ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("bean");
// 生成类图 ctrl + alt + u
// ApplicationContext其实就是上下文操作,AnnotationConfigApplicationContext和ClassPathXmlApplicationContext都是基于它的扩展类
// ApplicationContext继承BeanFactory实现扩展的功能
}
}
2 AnnotationConfig启动流程源码分析
AnnotationConfigApplicationContext源码分析
3 单例与多例对象是如何初始化的
课题内容:
1.SpringBean的生命周期有那些?
2.Spring的BeanPostProcessors作用
3.Spring的底层如何获取Spring上下文
单例和多例是在什么时候初始化的? 默认的情况下
单例默认情况下是在容器被加载的时候就会被初始化;
多例是在每次获取bean对象的时候就会去初始化;
底层使用beanFactory.preInstantiateSingletons();预执行初始化所有非懒加载的单例对象
4 对象的初始化与销毁过程01
SpringBean的生命周期
Bean的创建(执行构造函数)->初始化(自定义init方法)->销毁过程。
可以自定义对象初始化与销毁的方法
@Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")
对象的初始化和销毁
- 对象的初始化
对象创建完成,并赋值好,调用初始化方法 - 对象的销毁
单实例:容器关闭的时候(调用close方法)
多实例:容器不会管理这个bean;容器不会调用销毁方法
@Component
//@Scope("prototype")
public class UserEntity {
public UserEntity(){
System.out.println(">>UserEntity无参构造函数执行...");
}
/**
* initMethod是在无参构造函数之后执行
*/
private void initMethod() {
System.out.println(">>UserEntity initMethod 执行...");
}
private void destroyMethod() {
System.out.println(">>UserEntity destroyMethod 执行...");
}
}
@Configuration
@ComponentScan("com.mayikt.entity")
public class MyConfig {
/**
* initMethod 指定初始化方法执行 创建对象成功执行initMethod方法
* destroyMethod 指定销毁方法
* @return
*/
@Bean(initMethod = "initMethod", destroyMethod = "destroyMethod")
public UserEntity userEntity() {
return new UserEntity();
}
}
public class Test001 {
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
// annotationConfigApplicationContext.getBean("userEntity");
/**
* bean初始化 指的就是对象已经创建,里面所有的set方法都执行完毕了;可以指定方法进行执行
*/
// 调用close方法销毁单例对象 Map集合存储bean对象 底层调用clear()
annotationConfigApplicationContext.close();
}
}
运行结果
5 对象的初始化与销毁过程02
初始化和销毁的方法
方法一:通过@Bean指定init-method和destroy-method
方法二:通过让Bean实现InitializingBean(定义初始化逻辑),DisposableBean(定义销毁逻辑);
@Component
public class MemberEntity implements InitializingBean, DisposableBean {
public MemberEntity(){
System.out.println("MemberEntity >>无参构造函数");
}
// afterPropertiesSet等同于initMethod方法
// 对象创建->给对象属性赋值 set方法全部执行完成之后走afterPropertiesSet
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("MemberEntity >>afterPropertiesSet");
}
@Override
public void destroy() throws Exception {
System.out.println("MemberEntity >>destroy");
}
}
运行结果:
方法三:可以使用JSR250;(java规范自带)
@PostConstruct:在bean创建完成并且属性赋值完成,来执行初始化方法
@PreDestroy:在容器销毁bean之前通知我们进行清理工作
@Component
public class MemberEntity2 {
public MemberEntity2() {
System.out.println("MemberEntity2 >>无参构造函数");
}
@PostConstruct
public void afterPropertiesSet() throws Exception {
System.out.println("MemberEntity2 >>afterPropertiesSet");
}
@PreDestroy
public void destroy() throws Exception {
System.out.println("MemberEntity2 >>destroy");
}
}
运行结果:
6 ApplicationContextAware接口
过滤器中,是否可以使用注解方式获取bean的对象 不可以(自己单独获取上下文applicationContext)
BeanPostProcessor(后置处理器作用:对bean的初始化实现增强)
实现ApplicationContextAware接口
@Component
public class MyApplicationContext implements ApplicationContextAware {
private ApplicationContext applicationContext;
/**
* spring底层中为什么实现ApplicationContextAware接口 就能拿到applicationContext 靠的就是后置处理器
* @param applicationContext
* @throws BeansException
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
MemberEntity memberEntity = applicationContext.getBean("memberEntity", MemberEntity.class);
System.out.println("memberEntity:" + memberEntity);
}
}
配置类中增加注入语句@Import({MyApplicationContext.class})
对象初始化并且赋值完成之后走到setApplicationContext方法里面
运行结果:
实现ApplicationContextAware类,可以获取到applicationContext对象
@Component
public class PayEntity implements ApplicationContextAware {
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("获取到applicationContext对象");
}
}
底层代码执行流程:
7 BeanNameAware与BeanFactoryAware区别
测试BeanNameAware与BeanFactoryAware使用
(作用:拿到注入类的beanName/beanClassLoader/beanFactory)
@Component
public class PayEntity implements BeanNameAware, BeanFactoryAware {
public PayEntity() {
System.out.println("1.对象的实例化完成..");
}
@Override
public void setBeanName(String name) {
System.out.println("2.beanName:" + name);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("3.beanFactory:" + beanFactory);
}
}
运行结果:
8 BeanPostProcessor的作用
BeanPostProcessor的作用是对Bean的对象实现增强,在方法之前和之后进行处理
@Component
public class PayEntity implements BeanNameAware, BeanFactoryAware, InitializingBean {
public PayEntity() {
System.out.println("1.对象的实例化完成..");
}
@Override
public void setBeanName(String name) {
System.out.println("2.beanName:" + name);
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("3.beanFactory:" + beanFactory);
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("4.bean init方法执行..");
}
}
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
// BeanPostProcessor后置处理器
// 执行自定义init方法之前进行处理
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("执行init方法之前处理.." + beanName);
return null;
}
// 执行自定义init方法之后进行处理
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("执行init方法之后处理.." + beanName);
return null;
}
}
运行结果:
9 SpringBean的生命周期总结01
Spring的生命周期
1.实例化对象;
2.Setter注入,执行Bean的属性依赖注入;
3.BeanNameAware的setBeanName(),如果实现该接口,则执行其setBeanName方法;
4.BeanFactoryAware的setBeanFactory(),如果实现该接口,则执行其setBeanFactory方法;
5.BeanPostProcessor的processBeforeInitialization(),如果有关联的processor,则在Bean初始化之前都会执行这个实例的processBeforeInitialization()方法;
6.InitializingBean的afterPropertiesSet(),如果实现了该接口,则执行afterPropertiesSet()方法;(等同于Bean定义文件中定义init-method)
7.BeanPostProcessors的processAfterInitialization(),如果有关联的processor,则在Bean初始化之前都会执行这个实例的processAfterInitialization()方法;
8.DisposableBean的destroy(),在容器关闭时,如果Bean类实现了该接口,则执行它的destroy()方法;
9.Bean定义文件中定义destroy-method,在容器关闭时,可以在Bean定义文件中使用”destroy-method”定义的方法。