Spring全家桶面试题(一)之Spring Framework(四)

三、 Spring Beans(续)

24. 解释Spring框架中bean的生命周期

Bean生命周期:指定的就是Bean从创建到销毁的整个过程: 分4大步:
第1到第3步均是发生在IOC加载过程中的,第四步发生在Spring容器关闭时

  1. 实例化
    a. 通过反射去推断构造函数进行实例化
    b. 实例工厂、 静态工厂
  2. 属性赋值
    a. 解析自动装配(byname bytype constractor none @Autowired) DI的体现
    b. 循环依赖
  3. 初始化
    a. 调用XXXAware回调方法
    b. 调用初始化生命周期回调(三种)
    c. 如果bean实现aop 创建动态代理
  4. 销毁
    a. 在spring容器关闭的时候进行调用
    b. 调用销毁生命周期回调

25. Spring是如何解决Bean的循环依赖?

1. 什么是循环依赖

Spring全家桶面试题(一)之Spring Framework(四)_第1张图片

2. Spring是如何解决Bean的循环依赖的

如何解决:采用三级缓存解决,也就是3个map。

  1. 一级缓存:存储完整的Bean

  2. 三级缓存:
    a. 缓存的是函数接口:通过lambda 把方法传进去( 把Bean的实例(纯净态的实例)和Bean名字传进去(aop创建) )
    b. 不会立即调:(如果在实例化后立即调用的话:所有的aop 不管bean是否循环依赖都会在 实例化后创建
    proxy, 正常Bean 其实spring还是希望遵循生命周期在初始化创建动态代理, 只能循环依赖才创建)
    c. 会在 ABA (第二次getBean(A) 才会去调用三级缓存(如果实现了aop才会创建动态代理,如果没有实现
    依然返回的Bean的实例))
    d. 在c过程之后,放入二级缓存(避免重复创建)
    Spring全家桶面试题(一)之Spring Framework(四)_第2张图片夺命连环问:

  3. 二级缓存能不能解决循环依赖?
    a. 如果只是死循环的问题: 一级缓存就可以解决 :无法避免在并发下获取不完整的Bean?
    图灵课堂
    b. 二级缓存也可以解决循环依赖: 只不过如果出现重复循环依赖 会多次创建aop的动态代理

  4. Spring有没有解决多例Bean的循环依赖?
    a. 多例不会使用缓存进行存储(多例Bean每次使用都需要重新创建)
    b. 不缓存早期对象就无法解决循环

  5. Spring有没有解决构造函数参数Bean的循环依赖?
    a. 构造函数的循环依赖也是会报错
    b. 可以通过人工进行解决:@Lazy

    • i. 就不会立即创建依赖的bean了
    • ii. 而是等到用到才通过动态代理进行创建
      Spring全家桶面试题(一)之Spring Framework(四)_第3张图片

26. Spring如何避免在并发下获取不完整的Bean?

双重检查锁
为什么一级缓存不加到锁里面:
性能:因为一级缓存还有其他bean,避免获取其他已经创建好的Bean还要阻塞等待

线程1先检查一、二、三级缓存是否有bean(第一次肯定没有),接着线程1开始创建bean并锁住了二三级缓存,只有当线程1将对象存到一级缓存之后,才会解锁二级、三级缓存,但此时,因为线程1在将bean添加到一级缓存的同时,也remove了二级、三级缓存。因此线程2没有取到bean对象,再调用getSingleton(A,objectFactory)进行二次检查,这次在一级缓存就可以取到bean了。
Spring全家桶面试题(一)之Spring Framework(四)_第4张图片

27. BeanDefinition的加载过程:

Spring全家桶面试题(一)之Spring Framework(四)_第5张图片

28. 如何在Spring所有BeanDefinition注册完后做扩展?

通常可以使用beanFactoryPostProcessor 对已注册的BeanDefinition进行修改、
或者通过BeanDefinitionRegistryPostProcessor 再进行注册

在加了 beanDefinition.setScope(“prototype”);之后,user实例bean的创建由单例变成了多例。

@Component
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        //对已注册的BeanDefinition进行修改
        for (String beanDefinitionName:beanFactory.getBeanDefinitionNames()){
            System.out.println(beanDefinitionName);
        }
        BeanDefinition beanDefinition=beanFactory.getBeanDefinition("user");
        beanDefinition.setScope("prototype");
    }
}

29. 如何在Spring所有Bean创建完后做扩展?

哪里才算所有的Bean创建完: new ApplicationContext()---->refresh()---->finishBeanFactoryInitialization(循环所有的
BeanDefinition ,通过BeanFactory.getBean()生成所有的Bean) 这个循环结束之后所有的bean也就创建完了。

Spring全家桶面试题(一)之Spring Framework(四)_第6张图片

第一种方式:创建一个类实现SmartInitializingSingleton,在它的方法中做扩展

preInstantiateSingletons的部分代码

第一部分:循环所有的beanDefinition,利用beanFactory.getBean()创建所有的bean
第一二种方式的代码执行都是在该段代码之后
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
for (String beanName : beanNames) {
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				if (isFactoryBean(beanName)) {
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged(
									(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
							getBean(beanName);
						}
					}
				}
				else {
					getBean(beanName);
				}
			}
		}

		//第二部分:判断bean是不是SmartInitializingSingleton,如果是的,执行afterSingletonsInstantiated
		// Trigger post-initialization callback for all applicable beans...
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
						.tag("beanName", beanName);
				SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
				smartInitialize.end();
			}
		}

举例

@Component
public class SmartInitExtend implements SmartInitializingSingleton {
    @Override
    public void afterSingletonsInstantiated() {
        System.out.println("所有单例bean已经创建,SmartInitializingSingleton");
    }
}

第二种方式:通过监听事件

protected void finishRefresh() {
		// Clear context-level resource caches (such as ASM metadata from scanning).
		clearResourceCaches();

		// Initialize lifecycle processor for this context.
		initLifecycleProcessor();

		// Propagate refresh to lifecycle processor first.
		getLifecycleProcessor().onRefresh();

		// Publish the final event.
		//发布了一个事件
		publishEvent(new ContextRefreshedEvent(this));

		// Participate in LiveBeansView MBean, if active.
		if (!IN_NATIVE_IMAGE) {
			LiveBeansView.registerApplicationContext(this);
		}
	}

监听事件

@Component
public class RefreshedEventListener {

    @EventListener(ContextRefreshedEvent.class)
    public void onApplicationEvent(ContextRefreshedEvent event){
        System.out.println("所有单例bean已经创建,ContextRefreshedEvent");
    }
}

你可能感兴趣的:(后端,#,面试笔试,spring,java,缓存)