Springboot源码学习(一)Bean生命周期

Springboot核心概念

BeanDefinition

在springboot中定义Bean的几种方式
首先是声明式的:

  1. bean标签xml
  2. @Bean注解
  3. @Compent(@Service,@Controller等)
    编程式,创建BD然后注册Bean
//new 一个BD
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
// 当前Bean对象的类型
beanDefinition.setBeanClass(User.class);

// 将BeanDefinition注册到BeanFactory中
DefaultListableBeanFactory beanFac tory = new DefaultListableBeanFactory();
beanFactory.registerBeanDefinition("user", beanDefinition);

// 获取Bean
System.out.println(beanFactory.getBean("user"));

BeanDefinition可以理解为底层源码级别的一个概念,也可以理解为Spring提供的一种API使用的方式。

Bean生命周期

FactroyBean与别名问题

FactoryBean基本使用

FactroyBean是懒加载
在spring整合Mybatis中,注入的UserMapper就是Beanfactory实现的,继承FactroyBean之后,在getObjects方法中进行动态代理。
是BeanFactory容器的一个Bean,实现了FactoryBean接口就有三个方法

@Override
    public Object getObject() throws Exception {
        return new User();
    }
    @Override//Bean类型
    public Class<?> getObjectType() {
        return User.class;
    }
    @Override//对象是不是单例的
    public boolean isSingleton() {
        return false;
    }
}

再从容器中getBean(“lubanFactoryBean”)得到的是User对象,如果想要得到lubanFactoryBean,就要getBean("&lubanFactoryBean").
FactoryBean对应两个对象:
FactoryBean —>&lubanFactoryBean
User---->lubanFactoryBean.
当我们从单例池中拿到Bean之后,判断Bean是否是factroryBean
如果是name是&开头,直接调用factoryBean方法生成对象,放入到factoryBeanObjectCache中去(单例)。
懒加载

SmartFactroy

多了一个isEagerInit,默认返回false懒加载
返回true就是在容器初始化的时候加载

BeanName

Bean的名字有三种情况
beanname:标准名
alias:别名
&beanname:与FactoryBean有关

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
			@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

		// 对beanName进行转换 name如果是"&lubanFactoryBean",那么beanName就是"lubanFactoryBean"
		final String beanName = transformedBeanName(name);

先看是不是&开头的名字,是的话直接截掉&符号,

	Assert.notNull(name, "'name' must not be null");
		// 如果beanName没有以&开头,则直接返回
		if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {   // lubanFactoryBean
			return name;
		}
		// 如果beanName以&开头,截取&后的beanName,并且把截取前后的name存在transformedBeanNameCache中
		return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
			do {
				beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
			}
			while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
			return beanName;
		});

然后在从别名Map中找
aliasMap中key:alias,values:beanName。

public String canonicalName(String name) {
		String canonicalName = name;
		// Handle aliasing...
		String resolvedName;
		do {
			resolvedName = this.aliasMap.get(canonicalName);  // 别名:beanName
			if (resolvedName != null) {
				canonicalName = resolvedName;
			}
		}
		while (resolvedName != null);
		return canonicalName;
	}

之后再从单例池中拿到对象,再判断是不是beanInstance instanceof FactoryBean,是的话调用getObject方法,不是的话直接返回

容器初始化单例Bean

AnnotationConfigApplicationContext中的一个属性DefaultListableBeanFactory,来实现继承自BeanFactroy的方法
preInstantiateSingletons() 方法初始化单例Bean

1.合并BD

BD有两个重要实现类
RootBD,GBD
GBD是合并之前,RBD是合并之后的
扫描解析生成的BDM---->存放GBD,mergentMap—>RBD

如果某个BeanDefinition存在父BeanDefinition,那么则要进行合并
合并成RootBeanDenfintion—>MergentMap
在这里插入图片描述

2.doGetBean()

在这里插入图片描述

3.CreanBean()

加载类

这里要注意的是,Spring扫描完之后生成BD,并不是把class加载进jvm反射获取类的元信息,而是通过ASM技术解析class文件获得的,BD的一个属性BeanClass是Object类型的,扫描完成后是String类型,表示类的全限定类名,在这里又会把 BeanClass改为Class类型,也就是该Bean 的Class对象

实例化前

允许第三方可以不按照Spring的正常流程来创建一个Bean,可以利用InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation方法来提前返回一个Bean对象,直接结束Bean的生命周期
如果实例化前返回了一个对象,会直接执行postProcessAfterInitialization初始化后的方法。----初始化后的AOP

推断构造方法

实例化 Instantiation

BeanDefinition的后置处理

for (BeanPostProcessor bp : getBeanPostProcessors()) {
    if (bp instanceof MergedBeanDefinitionPostProcessor) {
        MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
        bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
    }
}

这里可以处理BeanDefinition,但是此时实例对象已经生成好了,所以修改beanClass已经没用了,但是可以修改PropertyValues,比如:
也可以setInitMethodName(),在初始化的时候会执行。参数是Bean中方法的名字

@Component
public class LubanMergedBeanDefinitionPostProcessor implements MergedBeanDefinitionPostProcessor {
    @Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
        if (beanName.equals("userService")) {
            beanDefinition.setBeanClass(User.class); // 没用
            beanDefinition.getPropertyValues().add("name","xxx");
        }
    }
}

填充属性

执行Aware

  1. ((BeanNameAware) bean).setBeanName(beanName);
  2. ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
  3. ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);

初始化前

Spring中的InitDestroyAnnotationBeanPostProcessor会找到Bean中实现这两个注解的方法,然后把这两个方法放到对应的List集合中去,再调用PostConstrust
@PostConstruct
@PreDestroy

for (BeanPostProcessor processor : getBeanPostProcessors()) {
    Object current = processor.postProcessBeforeInitialization(result, beanName);
    if (current == null) {
        return result;
    }
    result = current;
}
@PostConstruct与@PreDestroy

在扫描时会看Bean方法上是否有这两个注解
在4.2时会调用
InitDestroyAnnotationBeanPostProcessor后置处理器处理
构造方法反射得到一个实例,实例化分为四步

	// 4.1、执行Aware
			invokeAwareMethods(beanName, bean);
	// 4.2、初始化前
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
	// 4.3、初始化
			invokeInitMethods(beanName, wrappedBean, mbd);
	
	// 4.4、初始化后 AOP  ()
		applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

如果有一个BeanPostProcess调用方法返回空,剩下的就不会执行了,它有一个

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

		Object result = existingBean;
		for (BeanPostProcessor processor : getBeanPostProcessors()) {
			// BPP1--》BPP2-->BPP3
			Object current = processor.postProcessBeforeInitialization(result, beanName);
			if (current == null) {
				return result;
			}
			result = current;
		}
		return result;
	}

执行完之后没有返回一个对象就不会传入下一个。

初始化 Initialization

  1. ((InitializingBean) bean).afterPropertiesSet();
  2. 执行BeanDefinition中指定的初始化方法invokeInitMethods

初始化后

for (BeanPostProcessor processor : getBeanPostProcessors()) {
    Object current = processor.postProcessAfterInitialization(result, beanName);
    if (current == null) {
        return result;
    }
    result = current;
}

扩展点

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值