Spring之Bean生命周期源码解析

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接口。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SpringBean生命周期码主要涉及到Bean的初始化、依赖注入、后置处理、销毁等各个阶段。以下是一个简化的Spring Bean生命周期解析: 1. 实例化(Instantiation):Spring通过反射机制实例化Bean对象。这是通过调用构造函数或者工厂方法来完成的。 2. 属性注入(Property Injection):在实例化后,Spring将通过依赖注入(Dependency Injection)来设置Bean的属性值。这是通过调用setter方法或者直接访问字段来完成的。 3. Aware接口回调:Spring会检查Bean是否实现了某些Aware接口(如BeanNameAware、ApplicationContextAware等),并通过回调方法将相关的信息注入到Bean中。 4. BeanPostProcessor前置处理(BeanPostProcessor Pre-Initialization):Spring会检查是否有注册的BeanPostProcessor,如果有,则在Bean初始化前调用它们的postProcessBeforeInitialization方法。 5. 初始化(Initialization):初始化阶段包括两个步骤: a. 调用自定义的初始化方法(如通过@PostConstruct注解标记的方法或实现了InitializingBean接口的afterPropertiesSet方法)。 b. 调用BeanPostProcessor后置处理方法postProcessAfterInitialization。 6. 使用(In Use):此时Bean已经初始化完成,可以使用了。 7. 销毁(Destruction):在容器关闭或者手动销毁时,Spring会调用销毁方法来释放Bean占用的资。 a. 调用自定义的销毁方法(如通过@PreDestroy注解标记的方法或实现了DisposableBean接口的destroy方法)。 b. 调用BeanPostProcessor后置处理方法postProcessBeforeDestruction。 以上是简化的Spring Bean生命周期解析,实际的码会更加复杂和详细。Spring通过BeanPostProcessor和各种回调接口,提供了丰富的扩展点和生命周期管理功能,使开发者能够在Bean的不同阶段进行自定义操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值