Spring之Bean生命周期源码解析

  • Post author:
  • Post category:其他


1.启动接口介绍

具体的流程图:

Spring扫描底层流程 | ProcessOn免费在线作图,在线流程图,在线思维导图 |

  1. AnnotationConfigApplicationContext接口主要做了两件事情:1.scan 2.加载非懒加载的spring
    a.对象68和70行是java中的JFR机制,相当于查看69行代码执行的黑盒子(耗时,性能等)
    

     b.ClassPathBeanDefinitionScanner接口主要是把扫描到的BeanDefinition注册到spring容器中

c.当有两个类通过component注解的时候,如果内容一致,那么是不会报错的,isCompatible->中newDefinition.getSource().equals(existingDefinition.getSource())会判断资源是不是一致,如果一致直接返回false,这样checkCandidate接口就不会添加新的bean

if (this.checkCandidate(beanName, candidate)) {
    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    beanDefinitions.add(definitionHolder);
    this.registerBeanDefinition(definitionHolder, this.registry);
}

d.可以在resources添加spring.components

其中文件内容:com.zhouyu.service.UserService=org.springframeweork.stereotype.Colmponent

e.加载非懒加载的spring

this.refresh()->this.finishBeanFactoryInitialization(beanFactory)->beanFactory.preInstantiateSingletons()

f.SmartInitializingSingleton是在所有的非懒加载的单例Bean创建完成之后执行的代码

g.这样在getBean的时候会调用有参的构造函数,但是因为UserService是一个单例对象,在new AnnotationConfigApplicationConfig的时候就创建了,所以此处还是打印了0.

@Component
public class UserService {

	private OrderService orderService;

	public UserService() {
		System.out.println(0);
	}

	public UserService(OrderService orderService) {
		System.out.println(1);
		this.orderService = orderService;
	}

	public void test() {

		System.out.println("test");
	}
}
public class Test {

	public static void main(String[] args) {

		AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
		UserService userService = (UserService) applicationContext.getBean("userService", new OrderService());
		userService.test();

	}
}

2.实例化前

当前BeanDefinition对应的类成功加载后,就可以实例化对象了,但是…

在Spring中,实例化对象之前,Spring提供了一个扩展点,允许用户来控制是否在某个或某些Bean实例化之前做一些启动动作。这个扩展点叫

InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()

。比如:

@Component
public class ZhouyuBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		if ("userService".equals(beanName)) {
			System.out.println("实例化前");
		}
		return null;
	}
}

如上代码会导致,在userService这个Bean实例化前,会进行打印。

值得注意的是,postProcessBeforeInstantiation()是有返回值的,如果这么实现:

@Component
public class ZhouyuBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		if ("userService".equals(beanName)) {
			System.out.println("实例化前");
			return new UserService();
		}
		return null;
	}
}

userService这个Bean,在实例化前会直接返回一个由我们所定义的UserService对象。如果是这样,表示不需要Spring来实例化了,并且后续的Spring依赖注入也不会进行了,会跳过一些步骤,直接执行初始化后这一步。具体的代码细节在:createBean->resolveBeforeInstantiation中

3.实例化

在这个步骤中就会根据BeanDefinition去创建一个对象了。

3.1 实例化后,属性初始化之前可以使用MergedBeanDefinitionPostProcessor接口,进行一些初始化的操作,可以调用初始化接口、属性填充···

【eg】

扩展:对于任何一个Bean的执行流程如下:

  1. InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()
  2. 实例化
  3. MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition()
  4. InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation()
  5. getResolvedAutowireMode属性赋值(spring自带的依赖注入)
  6. InstantiationAwareBeanPostProcessor.postProcessProperties()(解析spring自带的autowired)
  7. Aware对象
  8. BeanPostProcessor.postProcessBeforeInitialization(),(包括@PostConstruct方法)
  9. 初始化
  10. BeanPostProcessor.postProcessAfterInitialization()
  • beans.xml中<context:annotation-config/>就是将AutowiredAnnotationBeanPostProcessor作为一个bean加入到了spring容器中,然后对所有的注解@Autowired进行解析

4.Bean的销毁过程(销毁只涉及单例,原型的不涉及销毁,因为每次都是使用的时候再创建,并且没有任何保存操作)

Bean的销毁过程是在spring容器的关闭过程中的。比如:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
UserService userService = (UserService) context.getBean("userService");
userService.test();

// 容器关闭
context.close();

在Bean创建过程中,在最后(初始化之后),有一个步骤会去判断当前创建的Bean是不是DisposableBean:

  1. 当前Bean是否实现了DisposableBean接口
  2. 或者,当前Bean是否实现了AutoCloseable接口
  3. BeanDefinition中是否指定了destroyMethod
  4. 调用DestructionAwareBeanPostProcessor.requiresDestruction(bean)进行判断
    1. ApplicationListenerDetector中直接使得ApplicationListener是DisposableBean
    2. InitDestroyAnnotationBeanPostProcessor中使得拥有@PreDestroy注解了的方法就是DisposableBean
  1. 把符合上述任意一个条件的Bean适配成DisposableBeanAdapter对象,并存入disposableBeans中(一个LinkedHashMap)

在Spring容器关闭过程时:

  1. 首先发布ContextClosedEvent事件
  2. 调用lifecycleProcessor的onCloese()方法
  3. 销毁单例Bean
    1. 遍历disposableBeans
      1. 把每个disposableBean从单例池中移除
      2. 调用disposableBean的destroy()
      3. 如果这个disposableBean还被其他Bean依赖了,那么也得销毁其他Bean
      4. 如果这个disposableBean还包含了inner beans,将这些Bean从单例池中移除掉 (inner bean参考

        Core Technologies

        )
    1. 清空manualSingletonNames,是一个Set,存的是用户手动注册的单例Bean的beanName
    2. 清空allBeanNamesByType,是一个Map,key是bean类型,value是该类型所有的beanName数组
    3. 清空singletonBeanNamesByType,和allBeanNamesByType类似,只不过只存了单例Bean

这里涉及到一个设计模式:

适配器模式

在销毁时,Spring会找出实现了DisposableBean接口的Bean。

但是我们在定义一个Bean时,如果这个Bean实现了DisposableBean接口,或者实现了AutoCloseable接口,或者在BeanDefinition中指定了destroyMethodName,那么这个Bean都属于“DisposableBean”,这些Bean在容器关闭时都要调用相应的销毁方法。

所以,这里就需要进行适配,将实现了DisposableBean接口、或者AutoCloseable接口等适配成实现了DisposableBean接口,所以就用到了DisposableBeanAdapter。

会把实现了AutoCloseable接口的类封装成DisposableBeanAdapter,而DisposableBeanAdapter实现了DisposableBean接口。



版权声明:本文为c243311364原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。