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年计算机毕业设计项目大全》,初衷也很简单,就是希望能够帮助提高效率,同时减轻大家的负担。
既有Java、Web、PHP、也有C、小程序、Python等项目供你选择,真正体系化!
由于项目比较多,这里只是将部分目录截图出来,每个节点里面都包含素材文档、项目源码、讲解视频
如果你觉得这些内容对你有帮助,可以添加VX:vip1024c (备注项目大全获取)
业设计不仅是我们在大学四年学习的一个总结,更是展示自己能力的重要机会。**
因此收集整理了一份《2024年计算机毕业设计项目大全》,初衷也很简单,就是希望能够帮助提高效率,同时减轻大家的负担。
[外链图片转存中…(img-lAo27SYc-1712556652316)]
[外链图片转存中…(img-DVVtWdzD-1712556652317)]
[外链图片转存中…(img-lV4xz8kf-1712556652317)]
既有Java、Web、PHP、也有C、小程序、Python等项目供你选择,真正体系化!
由于项目比较多,这里只是将部分目录截图出来,每个节点里面都包含素材文档、项目源码、讲解视频
如果你觉得这些内容对你有帮助,可以添加VX:vip1024c (备注项目大全获取)
[外链图片转存中…(img-G2Dd1Dig-1712556652317)]