Java面试题-Spring框架

Spring框架

1. BeanFactory和ApplicationContext有何区别

BeanFactory是Spring最底层的接口,是IoC的核心,定义IoC的基本功能。

BeanFactory具有:延迟实例化的特性。在启动的时候,不会实例化Bean,只有有需要从容器中获取Bean才会实例化Bean。(一般用在移动设备等内存较小的地方)

​ ApplicationContext是BeanFactory子接口,相较于BeanFactory多提供:国际化、资源访问、AOP等功能。

ApplicationContext在启动的时候,会实例化所有Bean,可以为Bean配置Lazy-init实现延迟实例化

2. Spring Bean的生命周期

一、加载Bean定义

​ 1、loadBeanDefinitions:将Bean定义记录在beanDefinitionMap中

registerBeanDefinition类-> registerBeanDefinition()方法

二、创建Bean对象

​ 1、构建对象

​ 通过遍历对对象进行逐个构造。

AbstractAutowireCapableBeanFactory类->createBeanInstance()

​ 2、填充属性

populateBean()

​ 3、初始化

initializeBean()

​ 3.1:applyBeanPostProcessorsBeforeInitialization():初始化前应用Bean后置处理器

​ 3.2:invokeInitMethods():初始化

​ 3.3:applyBeanPostProcessorsAfterInitialization():初始化后应用Bean后置处理器

三、使用

​ 初始化完成后的Bean对象即可正常使用。

四、销毁

​ 1、销毁前

@PreDestory注解的方法

​ 2、销毁

DisposableBean->destory()

Bean->destory-method()

3. Spring IOC如何实现

IoC:Inversion of Control 控制反转。

通俗易懂的理解:我们拥有创建对象的控制能力,反转为由程序进行创建对象,不在由我们去创建对象。

IoC有多种实现方式,其中最常见的DI(Dependency Injection 依赖注入)。对象通过构造方法参数、工厂方法参数、构造或工厂方法返回后在对象实例上设置的属性来定义它们的依赖项,从类外部注入依赖(容器在创建bean时注入这些依赖项)。

Spring常见依赖注入有3种方式:1、构造方法 2、set 3、注解注入@Autowired

Spring提供了两种IoC容器:

1、BeanFactory

2、ApplicationContext

具体可参考 面试题1

在了解了Spring Bean的生命周期后,我们能够发现Bean对象的创建已经不是由我们手动创建了,而是通过Spring底层的组件进行加载->创建->销毁,这一过程就是Spring IoC的过程。

4. 说说Spring AOP及实现原理

​ 4.1 AOP概念

​ AOP:Aspect Orient Programming 面向切面编程。

​ 目的:在不修改源代码的情况下,实现添加额外功能的技术。

​ 个人理解:源代码为一颗笔直的树,需要在这棵树上看到更多的种类,在树旁重新栽显然耗时费力,此时通过嫁接技术,在树的切面嫁 接即可实现目的。(AOP)

​ 4.2 AOP使用

具体使用可参考:https://blog.csdn.net/Cr1556648487/article/details/126777903

​ 4.3 AOP原理

​ SpringAOP底层采用动态代理,支持JDK动态代理以及Cglib动态代理。

​ JDK动态代理只能为接口创建动态代理实例。需要获得被代理类的接口信息,通过反射生成一个实现代理接口的动态代理类,然后通过构造方法生成动态代理类的实例对象,在调用具体方法前使用invokeHandler()处理。

​ Cglib动态代理以来asm包,把被代理类的字节码加载进来,生成其子类。

5. 动态代理(cglib与JDK)

JDK动态代理:

通过实现InvocationHandler接口的invoke()方法定义切面逻辑。

使用条件:

  • 1、业务目标对象只能为接口创建代理实例
  • 2、拦截器实现InvocationHandler
  • 3、通过Proxy.newProxyInstance()生成代理对象

Cglib动态代理:

基于ASM字节码生成库,允许在运行时对字节码修改和动态生成。

JDK动态代理与Cglib动态代理区别

  • JDK动态代理只针对接口实现类进行代理。也就是只面向接口

  • Cglib针对类实现代理,采用的是继承方法。

6. Spring事务实现方式

  1. 编程式事务

    概念:在业务代码中精确定义事务边界

    代码块中调用:beginTransaction()、commit()、rollback()等相关方法

  2. 声明式事务

    有助于用户将操作与事务规则进行解耦。简单地说,编程式事务侵入到了业务代码里面,但是提供了更加详细的事务管理;而声明式事务由于基于AOP,所以既能起到事务管理的作用,又可以不影响业务代码的具体实现。

​ 使用:

@EnableTransactionManagement:开启事务管理

@Transactional:开启事务

@Transactional事务注解失效原因:

  • 方法修饰符不为public
  • 方法内部调用事务
  • 事务内捕获异常,未抛出新异常
  • rollbackFor属性配置错误

7. Spring事务的底层原理

使用事务步骤:

  • 获取数据库连接
  • 开启事务
  • 执行数据操作
  • 提交事务/回滚事务
  • 关闭连接

Spring在框架中做了开启事务、提交事务、回滚事务的操作,使得业务代码和事务代码解耦。这一功能是基于AOP实现的。

8. 自定义注解实现功能

参考:https://www.jianshu.com/p/7c2948f64b1c

9. SpringMVC运行流程

在这里插入图片描述

核心代码:DispatcherServlet.java -> doDispatch()

  1. 用户请求
  2. DispatcherServlet中央调度器通过请求查找HandlerMapping获取Handler
  3. DispatcherServlet中央调度器通过Handler查找HandlerAdapeter
  4. 处理器适配器调用用户编写的controller,返回ModelAndView(基于JSON交互的,返回ModelAndView为空,此时前端已能接收到返回值)
  5. DispatcherServlet中央调度器通过ModelAndView查找对应ViewResolver,返回View
  6. 渲染View
  7. 返回渲染后的View

10. SpringMVC启动流程

详情查看:https://blog.51cto.com/u_9587581/2398187

11. Spring的单例实现

Spring的单例模式是采用:单例注册表实现的。

private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<String, Object>(16);
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);

  
//Spring获取单例模式方法
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    
    
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
    
    
			singletonObject = this.earlySingletonObjects.get(beanName);
			if (singletonObject == null && allowEarlyReference) {
    
    
				synchronized (this.singletonObjects) {
    
    
					singletonObject = this.singletonObjects.get(beanName);
					if (singletonObject == null) {
    
    
						singletonObject = this.earlySingletonObjects.get(beanName);
						if (singletonObject == null) {
    
    
							ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
							if (singletonFactory != null) {
    
    
								singletonObject = singletonFactory.getObject();
								this.earlySingletonObjects.put(beanName, singletonObject);
								this.singletonFactories.remove(beanName);
							}
						}
					}
				}
			}
		}
		return singletonObject;
	}

这里有3个Map集合:singletonObjects、earlySingletonObjects、singletonFactories

单例获取顺序为:singletonObjects -> earlySingletonObjects -> singletonFactories

  • singleonObjects:单例对象的cache
  • earlySingletonObjects:提前曝光的单例对象的cache
  • singletonFactories:单例对象工厂的cache

12. Spring中使用了哪些设计模式

1、工厂模式:BeanFactory、ApplicationContext

2、单例模式:Bean默认为单例模式

3、代理模式:AOP功能用到了JDK动态代理和Cglib动态代理

4、适配器模式:Spring AOP 的拦截器使用到了适配器模式

猜你喜欢

转载自blog.csdn.net/qq_36986510/article/details/129205978