Spring之路:解析Spring bean创建bean过程,顺便谈谈bean的生命周期

本文探讨了Spring框架中bean的创建过程,详细分析了何时创建bean,特别是原型bean与单例bean的区别。文章通过源码解析,展示了从预初始化到实例化的完整步骤,并介绍了BeanPostProcessor接口在bean创建中的关键作用。此外,还讨论了Spring中bean的生命周期,包括初始化、使用和销毁阶段。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写在前面

原本计划写一篇从启动代码开始,逐行分析Spring Boot整个启动过程的文章。写完第一部分发现这样做并不现实,而且也不合理,且成品对读者也不友好。最后觉得,还是应该拆开,从不同部分去解读Spring这个框架。于是便有了该系列文章。
该系列文章会均以源码为基础,一起来探索Spring这个框架(以Spring Boot2的方式)。
该系列每篇文章都会带着一个疑问去看代码。本文的问题是:Spring是如何创建bean的?在什么时候创建?原型和单例的bean的创建有何不同?Spring中bean的生命周期如何?

准备

本文基于Spring boot2.2.1.RELEASE。
准备一个Person类

public class Person {
   
    private String name;
    private int age;

    public Person() {
   
    }

    public Person(String name, int age) {
   
        this.name = name;
        this.age = age;
    }
    //省略getter setter方法
}

一个Boy类,含有一个Person字段girlFriend,使用注解注册该类实例到容器中。

@Component
public class Boy extends Person{
   
    private Person girlFriend;
    //该对象依赖一个person实例,使用构造器注入
    @Autowired
    public Boy(@Qualifier("someonesGirlFriend") Person girlFriend) {
   
        this.girlFriend = girlFriend;
    }

    public Boy(String name, int age) {
   
        super(name, age);
    }
    //省略getter setter方法
}

一个配置类,使用注解注册,一个为原型的badMan,一个单例女朋友(暗示女朋友只有一个,坏男人千千万万)

@Configuration
public class CommonConfig {
   
    @Bean(value = "badMan")
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public Person man(){
   
        return new Person();
    }
    @Bean("someonesGirlFriend")
    public Person getXmm(){
   
        return new Person("liLi",20);
    }
}

启动类代码:

@SpringBootApplication
public class NaocosDiscoveryApplication {
   

    public static void main(String[] args) {
   
        ConfigurableApplicationContext run = SpringApplication.run(NaocosDiscoveryApplication.class, args);
        Person boy = run.getBean("boy", Person.class);
        System.out.println(boy.getName());
        System.out.println(boy.getAge());
        Person badMan = run.getBean("badMan", Person.class);
        System.out.println(badMan.getName());
    }
}

什么时候创建bean?

这里说的bean是指我们平时使用@Service、@Component、@Controller()注解注册的bean。
这边有个技巧就是在org.springframework.beans.factory.BeanFactory接口的getBean(…)这几个方法上打上断点,debug的时候就一目了然。
为了节省时间,大家请在org.springframework.context.support.AbstractApplicationContext的550行finishBeanFactoryInitialization(beanFactory);处打上断点,该处是实例化我们注册bean的核心入口。
进入该方法,看到核心方法

// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();

注释已经告诉大家了,这个方法的作用就是Instantiate all remaining (non-lazy-init) singletons.(细心的人会发现前面是会实例化一些bean,但不是本文关注的重点)
通过调用栈我们可以看到,创建bean的时机为:
bean创建时机

创建bean的过程解析

进入preInstantiateSingletons()方法

@Override
	public void preInstantiateSingletons() throws BeansException {
   
		if (logger.isTraceEnabled()) {
   
			logger.trace("Pre-instantiating singletons in " + this);
		}

		// Iterate over a copy to allow for init methods which in turn register new bean definitions.
		// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
		//获取需要创建的beanName列表
		//你会发现我们想要创建beanName都在
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {
   
		//这个方法有兴趣可以进去看,可以当做黑盒处理,获取bean的BeanDefinition信息
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			//判断是否不为抽象
			//单例
			//非懒加载
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
   
			//判断这个bean是不是FactoryBean
			//是的话走使用FactoryBean创建对象
				if (isFactoryBean(beanName)) {
   
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
   
						final FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
   
							isEagerInit = AccessController.do
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值