Spring面试的几大问题

一、Bean的生命周期

1.Bean生命周期的概述

Spring面试的几大问题_第1张图片

2.debug看源码

(1)准备工作

让Father类实现InitializingBean, DisposableBean接口,并实现下面两个方法,自定义内容的输出。并手动创造初始化法和销毁方法,还依赖注入Son对象。

package com.csc.pojo;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * 自定义的Father类
 */
@Component
public class Father implements InitializingBean, DisposableBean {

    @Autowired
    private Son son;

    @PostConstruct
    public void initMethod(){
        System.out.println("Father...initMethod...执行了...");
    }

    @PreDestroy
    public void destroyMethod(){
        System.out.println("Father...destroyMethod...执行了...");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean...afterPropertiesSet...执行了...");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean...destroy...执行了...");
    }
}

自定义的Son类。

package com.csc.pojo;

import org.springframework.stereotype.Component;

/**
 * 自定义的Son类
 */
@Component
public class Son {
}

自定义的bean的后置处理器。

package com.csc.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

/**
 * bean的后置处理器,当bean对象初始化之前和之后都会调用下面两个方法
 */
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    //初始化之前调用
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("MyBeanPostProcessor...postProcessBeforeInitialization..."+beanName);
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    //初始化之后调用
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("MyBeanPostProcessor...postProcessAfterInitialization..."+beanName);
        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}

(2)debug看源码

接上一篇文章IOC容器初始化的流程,其中this.finishBeanFactoryInitialization(beanFactory)就是创建单例非懒加载的实例。

Spring面试的几大问题_第2张图片

(3)看源码的基本原则

首先,我们要明确要看的代码,其次,与目标代码无关的最好不要看防止干扰,最后要根据中文名字来猜测相关的英文单词。

(4)看实例化相关的源码

1.步入进来,该方法里面有许多代码,根据上面方法发现beanFactory.preInstantiateSingletons(),应该就是预实例化单例bean。Spring面试的几大问题_第3张图片

2.步入进去发现里面有个beanDefinitionNames集合,beanDefinition就是存储bean的信息,从里面可以看到我们自定义bean的名字,有father和son等等。Spring面试的几大问题_第4张图片

3.步过,发现这是循环实例化非懒加载单实例bean,我们在729行打上断点,一直放行找到我们自定义的father类,看debug有个beanName就是实例的bean名字。Spring面试的几大问题_第5张图片

4.然后步过跳转到了this.getBean(beanName),这个就是获取bean实例。Spring面试的几大问题_第6张图片

5.步入进去,看见了doGetBean(),就是真正获取bean实例的方法了。Spring面试的几大问题_第7张图片

6.再步入,发现该方法代码也是一样非常非常多,非常复杂,但是按看代码原则去寻找,应该可以快速找到相应的代码。Spring面试的几大问题_第8张图片

7.找到了下面代码。发现该段代码就是获取单例bean的方法,包含了bean的名字和一个lamda表达式,其中重点就是lamda表达式里面的内容。Spring面试的几大问题_第9张图片

8.步入getSingleeton(),发现133行代码的singletonFactory就是getSingleeton()里面的一个参数,也就是lamda表达式的值。Spring面试的几大问题_第10张图片

9.步入,就是会跳转到lamda表达式里面了,发现了createBean()应该就是创建bean实例了。Spring面试的几大问题_第11张图片

10.步入,找创建bean相关的代码,doCreateBean()就是核心创建bean的代码。Spring面试的几大问题_第12张图片

11.其中BeanWrapper就是bean实例的包装对象,作用就是为bean实例提供很多方法,方便操作,例如属性的获取,设置等等,类似反射。Spring面试的几大问题_第13张图片

12.这个就是最终创建bean实例,这个方法底层就是通过反射来创建的,没必要再步入看bean怎么创建的了,以及快到jdk级别了,没有意义步入进去了。

13.最终就可以发现这个bean就是father。至此,bean实例化已经结束。

(5)看依赖注入相关的源码

1.现在已经创建好了father对象,但是son并没有依赖注入,接下来就是看怎么依赖注入的。Spring面试的几大问题_第14张图片

2.找注入这些类似的单词,发现了populateBean。Spring面试的几大问题_第15张图片

3.步过,发现就是依赖注入好了,可以看exposedObject对象,有了son这个bean实例了。Spring面试的几大问题_第16张图片

(6)初始化bean相关源码

1.这个就是初始化的方法。

2.其中的invokeAwareMethods()就是执行Aware接口回调,就是感知接口。Spring面试的几大问题_第17张图片

3.执行BeanPostProcessors,PostProcessorsBeforeInitialization两个方法。可以看到控制台输出的内容。一个就是bean的后置处理器,一个就是手动添加的初始化,通过@PostConstruct就可以知道是手动添加的,然后自动处理。Spring面试的几大问题_第18张图片

4.执行InitializingBean回调。Spring面试的几大问题_第19张图片

5.执行BeanPostProcessors,PostProcessorsBeforeInitialization两个方法。Spring面试的几大问题_第20张图片

6.最后返回创建好的WrappedBean。至此,bean的初始化就到此结束了。Spring面试的几大问题_第21张图片

7.还有个细节,我们发现son其实已经创建好了,为什么呢?在father创建的时候,需要依赖注入son实例,所以就会创建好son实例。所以在创建son实例的时候,会直接返回,并不会再创建。

(7)使用对象

这就是程序员自己去使用了。

(8)销毁对象

停止运行spring,控制台输出,先执行@PreDestroy,后执行BeanPostProcessor。

3.面试的时候应该如何去说呢?

参考黑马程序员的图,如下图所示:

Spring面试的几大问题_第22张图片

你可能感兴趣的:(spring,面试,java)