spring面试题
2024-06-12 22:14:09 0 举报
AI智能生成
Spring是一个强大的Java企业级应用程序开发框架,它提供了IoC容器、AOP(面向切面编程)、事务管理、Web MVC等各种功能。在面试中,面试官可能会问到Spring的核心概念、特性、以及如何实现某些功能等。以下是一些示例问题: 1. 描述Spring IoC容器的工作原理。 2. 说出Spring AOP中的几个重要概念,如切面、连接点、增强等,并解释它们的作用。 3. 如何在Spring中实现事务管理,以及事务传播属性有哪些? 4. 请描述Spring MVC的工作流程,以及如何进行参数绑定和解析。 5. 什么是Spring Boot?它有哪些优点? 6. 请描述Spring Cloud的主要组件,如Eureka、Config Server等,并解释它们的功能。 7. 如何在Spring项目中实现异常处理和日志记录? 这些问题旨在考察候选人对Spring框架的理解程度、实际应用能力以及解决问题的能力。
作者其他创作
大纲/内容
Spring IOC原理<br>
概念
Spring 通过一个配置文件描述 Bean 及 Bean 之间的依赖关系,利用 Java 语言的反射功能实例化
Bean 并建立 Bean 之间的依赖关系。 Spring 的 IoC 容器在完成这些底层工作的基础上,还提供
了 Bean 实例缓存、生命周期管理、 Bean 实例代理、事件发布、资源装载等高级服务。
Spring 容器高层视图
Spring 启动时读取应用程序提供的 Bean 配置信息,并在 Spring 容器中生成一份相应的 Bean 配
置注册表,然后根据这张注册表实例化 Bean,装配好 Bean 之间的依赖关系,为上层应用提供准
备就绪的运行环境。其中 Bean 缓存池为 HashMap 实现
IOC 容器实现
BeanFactory-框架基础设施<br>BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身;ApplicationContext 面向使用<br>Spring 框架的开发者,几乎所有的应用场合我们都直接使用 ApplicationContext 而非底层<br>的 BeanFactory。<br>
BeanDefinitionRegistry 注册表<br>Spring 配置文件中每一个节点元素在 Spring 容器里都通过一个 BeanDefinition 对象表示,<br>它描述了 Bean 的配置信息。而 BeanDefinitionRegistry 接口提供了向容器手工注册<br>BeanDefinition 对象的方法。<br>
BeanFactory 顶层接口<br>位于类结构树的顶端 ,它最主要的方法就是 getBean(String beanName),该方法从容器中<br>返回特定名称的 Bean,BeanFactory 的功能通过其他的接口得到不断扩展<br>
ListableBeanFactory<br>该接口定义了访问容器中 Bean 基本信息的若干方法,如查看 Bean 的个数、获取某一类型<br>Bean 的配置名、查看容器中是否包括某一 Bean 等方法;<br>
HierarchicalBeanFactory 父子级联<br>父子级联 IoC 容器的接口,子容器可以通过接口方法访问父容器; 通过<br>HierarchicalBeanFactory 接口, Spring 的 IoC 容器可以建立父子层级关联的容器体系,子<br>容器可以访问父容器中的 Bean,但父容器不能访问子容器的 Bean。Spring 使用父子容器实<br>现了很多功能,比如在 Spring MVC 中,展现层 Bean 位于一个子容器中,而业务层和持久<br>层的 Bean 位于父容器中。这样,展现层 Bean 就可以引用业务层和持久层的 Bean,而业务<br>层和持久层的 Bean 则看不到展现层的 Bean。<br>
ConfigurableBeanFactory<br>是一个重要的接口,增强了 IoC 容器的可定制性,它定义了设置类装载器、属性编辑器、容<br>器初始化后置处理器等方法;<br>
AutowireCapableBeanFactory 自动装配<br>定义了将容器中的 Bean 按某种规则(如按名字匹配、按类型匹配等)进行自动装配的方法;<br>
SingletonBeanRegistry 运行期间注册单例 Bean<br>定义了允许在运行期间向容器注册单实例 Bean 的方法;对于单实例( singleton)的 Bean <br>来说,BeanFactory 会缓存 Bean 实例,所以第二次使用 getBean() 获取 Bean 时将直接从<br>IoC 容器的缓存中获取 Bean 实例。Spring 在 DefaultSingletonBeanRegistry 类中提供了一<br>个用于缓存单实例 Bean 的缓存器,它是一个用 HashMap 实现的缓存器,单实例的 Bean 以<br>beanName 为键保存在这个 HashMap 中。<br>
依赖日志框架<br>在初始化 BeanFactory 时,必须为其提供一种日志框架,比如使用 Log4J, 即在类路径下提<br>供 Log4J 配置文件,这样启动 Spring 容器才不会报错。<br>
ApplicationContext 面向开发应用<br>ApplicationContext 由 BeanFactory 派 生 而 来 , 提 供 了 更 多 面 向 实 际 应 用 的 功 能 。<br>ApplicationContext 继承了 HierarchicalBeanFactory 和 ListableBeanFactory 接口,在此基础<br>上,还通过多个其他的接口扩展了 BeanFactory 的功能<br>
ClassPathXmlApplicationContext:默认从类路径加载配置文件
FileSystemXmlApplicationContext:默认从文件系统中装载配置文件
ApplicationEventPublisher:让容器拥有发布应用上下文事件的功能,包括容器启动事
件、关闭事件等。
MessageSource:为应用提供 i18n 国际化消息访问的功能;
ResourcePatternResolver : 所 有 ApplicationContext 实现类都实现了类似于
PathMatchingResourcePatternResolver 的功能,可以通过带前缀的 Ant 风格的资源文
件路径装载 Spring 的配置文件。
LifeCycle:该接口是 Spring 2.0 加入的,该接口提供了 start()和 stop()两个方法,主要
用于控制异步处理过程。在具体使用时,该接口同时被 ApplicationContext 实现及具体
Bean 实现, ApplicationContext 会将 start/stop 的信息传递给容器中所有实现了该接
口的 Bean,以达到管理和控制 JMX、任务调度等目的
ConfigurableApplicationContext 扩展于 ApplicationContext,它新增加了两个主要
的方法: refresh()和 close(),让 ApplicationContext 具有启动、刷新和关闭应用上下
文的能力。在应用上下文关闭的情况下调用 refresh()即可启动应用上下文,在已经启动
的状态下,调用 refresh()则清除缓存并重新装载配置信息,而调用 close()则可关闭应用
上下文。
WebApplication 体系架构<br>WebApplicationContext 是专门为 Web 应用准备的,它允许从相对于 Web 根目录的<br>路径中装载配置文件完成初始化工作。从 WebApplicationContext 中可以获得<br>ServletContext 的引用,整个 Web 应用上下文对象将作为属性放置到 ServletContext <br>中,以便 Web 应用环境可以访问 Spring 应用上下文。<br>
Spring Bean 作用域<br>Spring 3 中为 Bean 定义了 5 中作用域,分别为 singleton(单例)、prototype(原型)、<br>request、session 和 global session<br>
singleton:单例模式(多线程下不安全)<br>singleton:单例模式,Spring IoC 容器中只会存在一个共享的 Bean 实例,无论有多少个<br>Bean 引用它,始终指向同一对象。该模式在多线程下是不安全的。Singleton 作用域是<br>Spring 中的缺省作用域,也可以显示的将 Bean 定义为 singleton 模式,配置为:<br><bean id="userDao" class="com.ioc.UserDaoImpl" scope="singleton"/><br>
prototype:原型模式每次使用时创建<br>prototype:原型模式,每次通过 Spring 容器获取 prototype 定义的 bean 时,容器都将创建<br>一个新的 Bean 实例,每个 Bean 实例都有自己的属性和状态,而 singleton 全局只有一个对<br>象。根据经验,对有状态的bean使用prototype作用域,而对无状态的bean使用singleton<br>作用域。<br>
Request:一次 request 一个实例<br>request:在一次 Http 请求中,容器会返回该 Bean 的同一实例。而对不同的 Http 请求则会<br>产生新的 Bean,而且该 bean 仅在当前 Http Request 内有效,当前 Http 请求结束,该 bean<br>实例也将会被销毁。<br><bean id="loginAction" class="com.cnblogs.Login" scope="request"/><br>
session<br>session:在一次 Http Session 中,容器会返回该 Bean 的同一实例。而对不同的 Session 请<br>求则会创建新的实例,该 bean 实例仅在当前 Session 内有效。同 Http 请求相同,每一次<br>session 请求创建新的实例,而不同的实例之间不共享属性,且实例仅在自己的 session 请求<br>内有效,请求结束,则实例将被销毁。<br><bean id="userPreference" class="com.ioc.UserPreference" scope="session"/><br>
global Session<br>global Session:在一个全局的 Http Session 中,容器会返回该 Bean 的同一个实例,仅在<br>使用 portlet context 时有效。<br>
Spring Bean 生命周期
实例化<br>实例化一个 Bean,也就是我们常说的 new。<br>
IOC 依赖注入<br>按照 Spring 上下文对实例化的 Bean 进行配置,也就是 IOC 注入。<br>
setBeanName实现<br>如果这个Bean已经实现了BeanNameAware接口,会调用它实现的setBeanName(String)<br>方法,此处传递的就是Spring配置文件中Bean的id值。<br>
BeanFactoryAware实现<br>如果这个Bean已经实现了BeanFactoryAware接口,会调用它实现的setBeanFactory,<br>setBeanFactory(BeanFactory)传递的是Spring工厂自身(可以用这个方式来获取其它Bean,<br>只需在Spring配置文件中配置一个普通的Bean就可以)。<br>
ApplicationContextAware实现<br>如果这个Bean已经实现了ApplicationContextAware接口,会调用setApplicationContext(ApplicationContext)方法,<br>传入Spring上下文(同样这个方式也可以实现步骤4的内容,但比4更好,因为ApplicationContext是BeanFactory的子接<br>口,有更多的实现方法)<br>
postProcessBeforeInitialization接口实现-初始化预处理<br>如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessBeforeInitialization(Object obj, String s)方法,<br>BeanPostProcessor经常被用作是Bean内容的更改,并且由于这个是在Bean初始化结束时调用那个的方法,也可以被应<br>用于内存或缓存技术。<br>
init-method<br>如果Bean在Spring配置文件中配置了init-method属性会自动调用其配置的初始化方法。
postProcessAfterInitialization<br>如果这个Bean关联了BeanPostProcessor接口,将会调用postProcessAfterInitialization(Object obj, String s)方法。<br>注:以上工作完成以后就可以应用这个Bean了,那这个Bean是一个Singleton的,所以一<br>般情况下我们调用同一个id的Bean会是在内容地址相同的实例,当然在Spring配置文件中<br>也可以配置非Singleton。
Destroy过期自动清理阶段<br>当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用那个其实现的destroy()方法;
destroy-method自配置清理<br>最后,如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的销毁方法。
bean 标签有两个重要的属性(init-method和destroy-method)。用它们你可以自己定制初始化和注销方法。它们也有相应的注解(@PostConstruct和@PreDestroy)。<bean id="" class="" init-method="初始化方法" destroy-method="销毁方法">
Spring 依赖注入四种方式
构造器注入<br>/*带参数,方便利用构造器进行注入*/<br>public CatDaoImpl(String message){<br>this. message = message;<br>} <br><bean id="CatDaoImpl" class="com.CatDaoImpl"><br><constructor-arg value="message"></constructor-arg> <br></bean><br>
setter方法注入<br>public class Id {<br>private int id; <br>public int getId() { return id; }<br>}<br><bean id="id" class="com.id "> <property name="id" value="123"></property></bean><br>
静态工厂注入<br>静态工厂顾名思义,就是通过调用静态工厂的方法来获取自己需要的对象,为了让spring管理所有对象,我们不能直接通过"工程类.静态方法()"来获取对象,而是依然通过spring注入的形式获取。
实例工厂<br>实例工厂的意思是获取对象实例的方法不是静态的,所以你需要首先 new 工厂类,再调用普通的实例方法
5 种不同方式的自动装配<br>Spring 装配包括手动装配和自动装配,手动装配是有基于 xml 装配、构造方法、setter 方法等<br>自动装配有五种自动装配的方式,可以用来指导 Spring 容器用自动装配方式来进行依赖注入。<br>
no:默认的方式是不进行自动装配,通过显式设置 ref 属性来进行装配。
byName:通过参数名 自动装配,Spring 容器在配置文件中发现 bean 的 autowire 属性被设
置成 byname,之后容器试图匹配、装配和该 bean 的属性具有相同名字的 bean。
byType:通过参数类型自动装配,Spring 容器在配置文件中发现 bean 的 autowire 属性被
设置成 byType,之后容器试图匹配、装配和该 bean 的属性具有相同类型的 bean。如果有多
个 bean 符合条件,则抛出错误。
constructor:这个方式类似于 byType, 但是要提供给构造器参数,如果没有确定的带参数
的构造器参数类型,将会抛出异常。
autodetect:首先尝试使用 constructor 来自动装配,如果无法工作,则使用 byType 方式。
Spring 特点
轻量
从大小与开销两方面而言spring都是轻量的。完整的spring框架可以在一个大小只有1M多的JAR文件里发布,并且spring所需的处理开销也是微不足道的。
spring是非侵入式的:典型的,spring应用中的对象不依赖于spring的特定类。
控制反转
spring通过一种称作控制反转IOC的技术促进了低耦合。
当应用IOC,一个对象依赖的其他对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。
面向切面
spring支持面向切面的编程,并且把应用业务逻辑和系统服务分开。
容器
spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建---基于一个可配置原型,你得bean可以创建一个单独的实例或者每次需要时都生成一个新的实例---以及它们是如何相互关联的。
框架
spring可以将简单的组件配置、组合成为复杂的应用。
在spring中,应用对象被声明式的组合,典型的是在一个XML文件里。
spring也提供了很多基础功能(事务管理、持久化框架集成等),将应用逻辑的开发留给开发者。
Spring 核心组件
Spring 常用模块
核心容器
核心容器提供spring框架的基础功能。核心容器的主要组件时BeanFactory,它是工厂模式的实现。BeanFactory使用控制反转(IOC)模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
Spring 上下文
Spring 上下文是一个配置文件,向Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如JNDI 、EJB、电子邮件、国际化、校验和调度功能。
Spring AOP
通过配置管理特性,Spring AOP模块直接将面向切面的编程功能集成到了Spring框架中。可以将一些通用任务,如安全、事务、日志等集中进行管理,提高了复用性和管理的便捷性。
Spring DAO
为JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO的面向JDBC的异常遵从通用的DAO异常层次结构。
Spring ORM
Spring框架插入了若干个ORM框架,从而提供了ORM的对象关系工具,其中包括JDO、Hibernate和iBatis SQL Map。所有这些都遵从Spring的通用事务和DAO异常层次结构。
Spring Web模块
Web上下文模块建立在应用程序上下文模块上,为基于Web的应用程序提供了上下文。所以,Spring框架支持与Jakarta Struts的集成。Web模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
Spring MVC框架
MVC框架是一个全功能的构建Web应用程序的MVC实现。通过策略接口,MVC框架变成高度可配置的,MVC容纳了大量视图技术,其中包括JSP、Velocity、Tiles、iText和POI。
Spring 主要包
包
Spring 常用注解
1
@Controller
用于标注控制层组件。
@Controller 用于标记在一个类上,使用它标记的类就是一个SpringMVC Controller对象。
分发处理器将会扫描使用了该注解的类的方法,并检测该方法是否使用了@RequestMapping注解。
可以把Request请求header部分的值绑定到方法的参数上。
@RestController
相当于@Controller和@ResponseBody的组合效果。
@Component
泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
@Repository
用于注解dao层,在daoImpl类上面注解。
@Service
用于标注业务层组件。
2
@ResponseBody
异常请求
该注解用于将Controller的方法返回的对象,通过适当的HttpMessageConverter转换为指定格式后,写入到Response对象的body数据区。
返回的数据不是html标签的页面,而是其他某种格式的数据时(如json、xml等)使用
@RequestMapping
一个用来处理请求地址映射的注解,可用于类或方法上。用于类上,表示类中的所有响应请求的方法都是以该地址作为父路径。
@Autowired
它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。通过@Autowired的使用来消除set,get方法。
@PathVariable
用于将请求URL中的模板变量映射到功能处理方法的参数上,即取出url模板中的变量作为参数。
@RequestParam
主要用于在SpringMVC的后台控制层获取参数,类似一种是request.getParameter("name")
@RequestHeader
可以把Request请求header部分的值绑定到方法的参数上
3
@ModelAttribute
该Controller的所有方法在调用前,先执行此@ModelAttribute方法,可用于注解和方法参数中,可以把这个@ModelAttribute特性,应用在BaseController当中,所有的Controller继承BaseController,即可实现在调用Controller时,先执行@ModelAttribute方法。
@SessionAttributes
即将值放到session作用域中,写到class上面。
@Valid
实体数据校验,可以结合hibernate validator一起使用。
@CookieValue
用来获取Cookie中的值
spring第三方结合
权限
shiro
java的一个安全框架
认证、授权、加密、会话管理、与Web集成、缓存
缓存
Ehcache
是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernate中默认的CacheProvider
redis
一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Vlue数据库
持久层框架
Hibernate
一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,它将POJO与数据库建立映射关系,是一个全自动的orm框架。
Mybatis
是支持普通SQL查询,存储过程和高级映射的优秀持久层框架。
定时任务
quartz
一个开源的作业调度框架,由java编写,在.NET平台为Quartz.NET,通过Quartz可以快速完成任务调度的工作。
Spring-Task
可以把它比作一个轻量级的Quartz,而且使用起来很简单,除Spring相关包外不需要额外的包,而且支持注解和配置文件两种形式。
校验框架
Hibernate validator
Hibernate Validator经常用来验证bean的字段,基于注解,方便快捷高效。
OVal
OVal是一个可扩展的Java对象数据验证框架,验证的规则可以通过配置文件、Annotation、POJOs进行设定。可以使用纯Java语言,JavaScript、Groovy、BeanShell等进行规则的编写。
Spring AOP 原理
概念
"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,<br>并将其命名为"Aspect",即切面。所谓"切面",简单说就是那些与业务无关,却为业务模块所共<br>同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未<br>来的可操作性和可维护性。
使用"横切"技术,AOP 把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流
程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生
在核心关注点的多处,而各处基本相似,比如权限认证、日志、事物。AOP 的作用在于分离系统
中的各种关注点,将核心关注点和横切关注点分离开来。
AOP 主要应用场景有:<br>1. Authentication 权限<br>2. Caching 缓存<br>3. Context passing 内容传递<br>4. Error handling 错误处理<br>5. Lazy loading 懒加载<br>6. Debugging 调试<br>7. logging, tracing, profiling and monitoring 记录跟踪 优化 校准<br>8. Performance optimization 性能优化<br>9. Persistence 持久化<br>10. Resource pooling 资源池<br>11. Synchronization 同步<br>12. Transactions 事务<br>
AOP 核心概念
切面(aspect):类是对物体特征的抽象,切面就是对横切关注点的抽象
横切关注点:对哪些方法进行拦截,拦截后怎么处理,这些关注点称之为横切关注点。
连接点(joinpoint):被拦截到的点,因为 Spring 只支持方法类型的连接点,所以在 Spring
中连接点指的就是被拦截到的方法,实际上连接点还可以是字段或者构造器。
切入点(pointcut):对连接点进行拦截的定义
通知(advice):所谓通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、
异常、最终、环绕通知五类。
目标对象:代理的目标对象
织入(weave):将切面应用到目标对象并导致代理对象创建的过程
引入(introduction):在不修改代码的前提下,引入可以在运行期为类动态地添加一些方法
或字段。
AOP 两种代理方式
Spring 提供了两种方式来生成代理对象: JDKProxy 和 Cglib,具体使用哪种方式生成由
AopProxyFactory 根据 AdvisedSupport 对象的配置来决定。默认的策略是如果目标类是接口,
则使用 JDK 动态代理技术,否则使用 Cglib 来生成代理。
JDK 动态接口代理<br>JDK 动态代理主要涉及到 java.lang.reflect 包中的两个类:Proxy 和 InvocationHandler。<br>InvocationHandler是一个接口,通过实现该接口定义横切逻辑,并通过反射机制调用目标类<br>的代码,动态将横切逻辑和业务逻辑编制在一起。Proxy 利用 InvocationHandler 动态创建<br>一个符合某一接口的实例,生成目标类的代理对象。
CGLib 动态代理<br>CGLib 全称为 Code Generation Library,是一个强大的高性能,高质量的代码生成类库,<br>可以在运行期扩展 Java 类与实现 Java 接口,CGLib 封装了 asm,可以再运行期动态生成新<br>的 class。和 JDK 动态代理相比较:JDK 创建代理有一个限制,就是只能为接口创建代理实例,<br>而对于没有通过接口定义业务方法的类,则可以通过 CGLib 创建动态代理。
切面
0 条评论
下一页