spring bean 的生命周期

32 篇文章 0 订阅
文章介绍了SpringBean的生命周期,包括实例化、字段赋值、初始化和销毁过程。重点讨论了如何通过分析初始化耗时来优化系统性能,特别是关注在init方法中执行的耗时操作。通过实现BeanPostProcessor接口,可以在bean初始化前后记录时间,从而获取每个bean的初始化耗时,帮助识别影响系统启动效率的bean。
摘要由CSDN通过智能技术生成

spring bean 的生命周期

  • 实例化(instantiate), 用构造器创建一个对象

  • 字段赋值(populate)

  • 初始化(initialize), 执行bean配置里的init方法或者InitializingBean#afterPropertiesSet方法

  • 销毁(destruct)

实例化和字段赋值一般都很快,但是一些重型的bean被IOC容器创建时,需要调用远程服务或者执行耗时的操作,这些操作往往在init方法里实现。统计bean初始化耗时可以发现那些bean影响了系统的启动效率。业务方的bean可以推动业务优化,自己的bean也可以想方法优化性能。

那么如何统计初始化的耗时呢?

spring bean初始化源码分析

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean 观察执行初始化方法的逻辑

protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
 if (System.getSecurityManager() != null) {
  AccessController.doPrivileged(new PrivilegedAction<Object>() {
   @Override
   public Object run() {
    invokeAwareMethods(beanName, bean);
    return null;
   }
  }, getAccessControlContext());
 }
 else {
  invokeAwareMethods(beanName, bean);
 }

 Object wrappedBean = bean;
 if (mbd == null || !mbd.isSynthetic()) {
  // 初始化前spring提供的系统钩子
  wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
 }

 try {
  // 执行初始化方法
  invokeInitMethods(beanName, wrappedBean, mbd);
 }
 catch (Throwable ex) {
  throw new BeanCreationException(
    (mbd != null ? mbd.getResourceDescription() : null),
    beanName, "Invocation of init method failed", ex);
 }
 if (mbd == null || !mbd.isSynthetic()) {
  // 初始化后spring提供的系统钩子
  wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
 }
 return wrappedBean;
}

applyBeanPostProcessorsBeforeInitialization做了什么?

取出所有实现BeanPostProcessor的bean,逐个执行一遍postProcessBeforeInitialization方法。

同理,applyBeanPostProcessorsAfterInitialization逻辑依然,只是执行的是postProcessInitialization方法。

@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
  throws BeansException {

 Object result = existingBean;
 for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
  result = beanProcessor.postProcessBeforeInitialization(result, beanName);
  if (result == null) {
   return result;
  }
 }
 return result;

spring系统钩子 BeanPostProcessor

Factory hook that allows for custom modification of new bean instances, e.g. checking for marker interfaces or wrapping them with proxies.

ApplicationContexts can autodetect BeanPostProcessor beans in their bean definitions and apply them to any beans subsequently created. Plain bean factories allow for programmatic registration of post-processors, applying to all beans created through this factory

BeanPostProcessor接口仅仅提供两个方法,用在在初始化bean的时候进行定制开发。

public interface BeanPostProcessor {

 Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

 Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}

bean初始化耗时功能开发demo

简单demo

package org.dubbo.server.service.tool;

import com.google.common.collect.Maps;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

import java.util.Map;

/**
 * @author LvSheng
 **/
@Component
public class TimeCostBeanPostProcessor implements BeanPostProcessor {
 
 Map<String, Long> costMap = Maps.newConcurrentMap();
 
 @Override
 public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  costMap.put(beanName, System.currentTimeMillis());
  return bean;
 }
 
 @Override
 public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  long start = costMap.get(beanName);
  long cost  = System.currentTimeMillis() - start;
  if (cost > 0) {
   costMap.put(beanName, cost);
   System.out.println("class: " + bean.getClass().getName()
            + "\tbean: " + beanName
            + "\ttime" + cost);
  }
  return bean;
 }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wis57

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值