剑指Spring源码:俯瞰Spring的Bean的生命周期(大众版,计算机类专业毕业

if(beanName.equals(“springBean”)) {

System.out.println(“postProcessBeforeInitialization”);

}

return bean;

}

@Override

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

if(beanName.equals(“springBean”)) {

System.out.println(“postProcessAfterInitialization”);

}

return bean;

}

}

定义一个配置类,完成自动扫描,但是SpringBean是手动注册的,并且声明了initMethod和destroyMethod:

@Configuration

@ComponentScan

public class AppConfig {

@Bean(initMethod = “initMethod”,destroyMethod = “destroyMethod”)

public SpringBean springBean() {

return new SpringBean();

}

}

最后就是启动类了:

public static void main(String[] args) {

AnnotationConfigApplicationContext annotationConfigApplicationContext =

new AnnotationConfigApplicationContext(AppConfig.class);

annotationConfigApplicationContext.destroy();

}

运行结果:

SpringBean构造方法:null

SpringBean构造方法

setBeanName:com.codebear.StudentServiceImpl@31190526

setBeanName

setBeanClassLoader

setBeanFactory

postProcessBeforeInitialization

afterPropertiesSet

initMethod

postProcessAfterInitialization

destroy

destroyMethod

可以看到,试验结果和上面分析的完全一致。

这就是广为流传的Spring生命周期。

也许你在应付面试的时候,是死记硬背这些结论的,现在我带着你找到这些方法,跟我来。

首先我们来到AnnotationConfigApplicationContext的构造方法:

//根据参数类型可以知道,其实可以传入多个annotatedClasses,但是这种情况出现的比较少

public AnnotationConfigApplicationContext(Class<?>… annotatedClasses) {

//调用无参构造函数,会先调用父类GenericApplicationContext的构造函数

//父类的构造函数里面就是初始化DefaultListableBeanFactory,并且赋值给beanFactory

//本类的构造函数里面,初始化了一个读取器:AnnotatedBeanDefinitionReader read,一个扫描器ClassPathBeanDefinitionScanner scanner

//scanner的用处不是很大,它仅仅是在我们外部手动调用 .scan 等方法才有用,常规方式是不会用到scanner对象的

this();

//把传入的类进行注册,这里有两个情况,

//传入传统的配置类

//传入bean(虽然一般没有人会这么做

//看到后面会知道spring把传统的带上@Configuration的配置类称之为FULL配置类,不带@Configuration的称之为Lite配置类

//但是我们这里先把带上@Configuration的配置类称之为传统配置类,不带的称之为普通bean

register(annotatedClasses);

//刷新

refresh();

}

进入refresh方法,refresh方法中有一个finishBeanFactoryInitialization小方法,这个方法是用来实例化懒加载单例Bean的,也就是我们的Bean都是在这里被创建出来的(当然我这里说的的是绝大部分情况是这样的):

finishBeanFactoryInitialization(beanFactory);

我们再进入finishBeanFactoryInitialization这方法,里面有一个beanFactory.preInstantiateSingletons()方法:

//初始化所有的非懒加载单例

beanFactory.preInstantiateSingletons();

我们尝试再点进去,这个时候你会发现这是一个接口,好在它只有一个实现类,所以可以我们来到了他的唯一实现,实现类就是org.springframework.beans.factory.support.DefaultListableBeanFactory,这里面是一个循环,我们的Bean就是循环被创建出来的,我们找到其中的getBean方法:

getBean(beanName);

这里有一个分支,如果Bean是FactoryBean,如何如何,如果Bean不是FactoryBean如何如何,好在不管是不是FactoryBean,最终还是会调用getBean方法,所以我们可以毫不犹豫的点进去,点进去之后,你会发现,这是一个门面方法,直接调用了doGetBean方法:

return doGetBean(name, null, null, false);

再进去,不断的深入,接近我们要寻找的东西。

这里面的比较复杂,但是有我在,我可以直接告诉你,下一步我们要进入哪里,我们要进入

if (mbd.isSingleton()) {

//getSingleton中的第二个参数类型是ObjectFactory<?>,是一个函数式接口,不会立刻执行,而是在

//getSingleton方法中,调用ObjectFactory的getObject,才会执行createBean

sharedInstance = getSingleton(beanName, () -> {

try {

return createBean(beanName, mbd, args);

}

catch (BeansException ex) {

destroySingleton(beanName);

throw ex;

}

});

bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);

}

这里面的createBean方法,再点进去啊,但是又点不进去了,这是接口啊,但是别慌,这个接口又只有一个实现类,所以说 没事,就是干,这个实现类为org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory。

这个实现的方法里面又做了很多事情,我们就不去看了,我就是带着大家找到那几个生命周期的回调到底定义在哪里就OK了。

Object beanInstance = doCreateBean(beanName, mbdToUse, args);//创建bean,核心

if (logger.isDebugEnabled()) {

logger.debug(“Finished creating instance of bean '” + beanName + “'”);

}

return beanInstance;

再继续深入doCreateBean方法,这个方法又做了一堆一堆的事情,但是值得开心的事情就是 我们已经找到了我们要寻找的东西了。

创建实例

首先是创建实例,位于:

instanceWrapper = createBeanInstance(beanName, mbd, args);//创建bean的实例。核心

填充属性

其次是填充属性,位于:

populateBean(beanName, mbd, instanceWrapper);//填充属性,炒鸡重要

在填充属性下面有一行代码:

exposedObject = initializeBean(beanName, exposedObject, mbd);

继续深入进去。

aware系列接口的回调

aware系列接口的回调位于initializeBean中的invokeAwareMethods方法:

invokeAwareMethods(beanName, bean);

private void invokeAwareMethods(final String beanName, final Object bean) {

if (bean instanceof Aware) {

if (bean instanceof BeanNameAware) {

((BeanNameAware) bean).setBeanName(beanName);

}

if (bean instanceof BeanClassLoaderAware) {

ClassLoader bcl = getBeanClassLoader();

if (bcl != null) {

((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);

}

}

if (bean instanceof BeanFactoryAware) {

((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);

}

}

}

BeanPostProcessor的postProcessBeforeInitialization方法

BeanPostProcessor的postProcessBeforeInitialization方法位于initializeBean的

if (mbd == null || !mbd.isSynthetic()) {

wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);

}

@Override

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数同学面临毕业设计项目选题时,很多人都会感到无从下手,尤其是对于计算机专业的学生来说,选择一个合适的题目尤为重要。因为毕业设计不仅是我们在大学四年学习的一个总结,更是展示自己能力的重要机会。

因此收集整理了一份《2024年计算机毕业设计项目大全》,初衷也很简单,就是希望能够帮助提高效率,同时减轻大家的负担。
img
img
img

既有Java、Web、PHP、也有C、小程序、Python等项目供你选择,真正体系化!

由于项目比较多,这里只是将部分目录截图出来,每个节点里面都包含素材文档、项目源码、讲解视频

如果你觉得这些内容对你有帮助,可以添加VX:vip1024c (备注项目大全获取)
img

业设计不仅是我们在大学四年学习的一个总结,更是展示自己能力的重要机会。**

因此收集整理了一份《2024年计算机毕业设计项目大全》,初衷也很简单,就是希望能够帮助提高效率,同时减轻大家的负担。
[外链图片转存中…(img-lAo27SYc-1712556652316)]
[外链图片转存中…(img-DVVtWdzD-1712556652317)]
[外链图片转存中…(img-lV4xz8kf-1712556652317)]

既有Java、Web、PHP、也有C、小程序、Python等项目供你选择,真正体系化!

由于项目比较多,这里只是将部分目录截图出来,每个节点里面都包含素材文档、项目源码、讲解视频

如果你觉得这些内容对你有帮助,可以添加VX:vip1024c (备注项目大全获取)
[外链图片转存中…(img-G2Dd1Dig-1712556652317)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值