Spring
01.@Value 注解的作用是什么?
基于 @Value 的注解可以读取 properties 或者是yml 配置文件, 使用如下 :
02.Spring AOP 通知类型有哪些?
Spring通知总共有五种: 前置通知, 环绕通知, 异常通知, 后置通知, 最终通知.
- 前置通知(Before advice): 在目标方法执行之前执行的通知. 在某连接点(join point)之前执行的通知, 但这个通知不能阻止连接点前的执行(除非它抛出一个异常).
- 环绕通知(Around Advice): 在目标方法执行之前和之后都可以执行额外代码的通知, 也可以选择是否继续执行连接点或直接返回它们自己的返回值或抛出异常来结束执行
- 后置通知(After(finally) advice): 目标方法执行之后(某连接点退出的时候)执行的通知(不论是正常返回还是异常退出).
- 异常后通知(After throwing advice): 在方法抛出异常退出时执行的通知.
- 最终通知(After returning advice): 在某连接点(join point)正常完成后执行的通知, 例如, 一个方法没有抛出任何异常, 正常返回.
03.怎么理解Spring中的IOC容器?
Spring IOC 就是把创建对象的权利交给框架去控制, 而不需要人为的去创建, 这样就实现了可插拔式的接口编程, 有效地降低代码的耦合度, 降低了扩展和维护的成本.
比如, 去某地旅游不用自己亲自订购A酒店还是B酒店而发愁了, 只需要把住店的需求告诉给某个托管平台, 这个托管平台就会帮你订购一个既便宜又舒适的酒店, 而这个帮你订购酒店的行为就可以称之为控制反转.
04.怎么理解Spring中的依赖注入?(DI, dependency injection)
依赖注入是指组件之间的依赖关系由容器在运行期决定, 即由容器动态的将某个依赖关系注入到组件之中, 依赖注入的目的并非为软件系统带来更多功能, 而是为了提升组件重用的频率, 并为系统搭建一个灵活, 可扩展的平台. 通过依赖注入机制, 我们只需要通过简单的配置, 而无需任何代码就可指定目标需要的资源, 完成自身的业务逻辑, 而不需要关心具体的资源来自何处, 由谁实现.
05.IOC和DI有什么关系?
IoC是Spring中一个极为重要的概念, 提供了对象管理的功能, 从而省去了人为创建麻烦, 而DI正是实现IoC的方法和手段
06.@Component和@Bean有什么区别?
答: 它们的作用对象不同:
- @Component作用于类;
- @Bean 注解作用于方法;
@Component 通常是通过类路径扫描来自动侦测和装配对象到Spring容器中, 比如@ComponentScan注解就是定义扫描路径中的类装配到Spring的Bean容器中;
@Bean 注解是告诉Spring这是某个类的实例, 当我需要用它的时候把它给我, @Bean注解比@Component注解自定义性更强, 很多地方我们只能通过@Bean注解来注册Bean, 比如当我们引用第三方库中的类需要装配到Spring容器中时, 则只能通过@Bean来实现, 比如以下示例, 只能通过@Bean注解来实现
public class SpringConfig{
@Bean
public ThirdLibClass getThirdLibClass(){
return new ThirdLibClass();
}
}
07.Spring中bean的作用域有几种类型?
Spring中bean的作用域有四种类型, 如下列表:
- 单例(Singleton): 整个应用程序, 只创建bean的一个实例;
- 原型(Prototype): 每次注入都会创建一个新的bean实例;
- 会话(Session): 每个会话创建一个bean实例, 只在Web系统中有效;
- 请求(Request): 每个请求创建一个bean实例, 只在Web系统中有效;
Spring 中默认的是单例模式, 并且除非特殊情况, 一般不会使用其他的bean作用域, 至今,笔者从未使用
08.什么是Spring的内部bean?
当一个bean仅被用作另一个bean的属性时, 它能被声明为一个内部bean, 为了定义inner Bean, 在Spring的基于XML的配置元数据中, 可以在<property/>或<constructor-arg/>元素内使用<bean/>元素, 内部bean通常是匿名的, 它们的Scope一般是prototype原型模式.
09.Spring注入方式有哪些?
Spring的注入方式包含以下五种:
- setter注入
- 构造方法注入
- 注解注入
- 静态工厂注入
- 实例工厂注入
其中最常用的是前三种, 官方推荐使用的是注解注入, 相对使用更简单, 维护成本更低, 更直观.
10.在Spring中如何操作数据库?
不谈三方框架Mybatis, Hibernate, 以及SpringData, 在Spring中操作数据库, 可以使用Spring提供的JdbcTemplate对象, JdbcTemplate类提供了很多便利的方法, 比如把数据库数据转变成基本数据类型或对象, 执行自定义的SQL语句, 提供了自定义的数据错误处理等, JdbcTemplate使用示例如下:
此处缺少一个示例
11.Spring的JdbcTemplate对象和JDBC有什么区别?
Spring的JdbcTemplate是对JDBC API的封装, 提供更多的功能和更便利的操作, 比如JdbcTemplate拥有:
- JdbcTempalte是线程安全的;
- 实例化操作比较简单, 仅需要传递DataSource;
- 自动完成资源的创建和释放工作;
- 创建一次JdbcTemplate, 到处可用, 避免重复开发;
12.Spring有几种实现事务的方式?
Spring实现事务有两种方式: 编程式事务和声明式事务 \
- 编程式事务, 使用TransactionTemplate或PlatformTransactionManager实现, 示例代码如下 :
private final TransactionTemplate transactionTemplate;
public void add(User user) throws Exception{
// Spring编程式事务, 回调机制
transactionTemplate.execute(new TransactionCallback<Object>(){
@Override
public Object doInTransaction(TransactionStatus status){
try {
userMapper.insertSelective(user);
} catch(Exception e) {
// 异常, 设置为回滚
status.setRollbackOnly();
throw e;
}
return null;
}
});
}
如果有异常, 调用status.setRollbackOnly()回滚事务, 否则正常执行doInTransaction()方法, 正常提交事务.
如果事务控制的方法不需要返回值, 就可以使用TransactionCallbackWithoutResult(TransactionCallback接口的抽象实现类), 只需将上述内部实现类, 变为该类, 并且不返回值即可.
- 声明式事务
底层是建立在Spring AOP的基础上, 在方法执行前后进行拦截, 并在目标方法开始执行前创建或加入一个已存在事务, 最后在目标方法执行完成后根据情况提交或者回滚事务.
声明式事务的优点: 不需要编程, 减少了代码的耦合, 在配置文件中配置并在目标方法上添加@Transactional注解来实现, 示例代码如下:
@Transactional
public void save() {
User user = new User("hello");
userMapper.insertSelective(user);
if (true) {
throw new RuntimeException("手动抛出异常, 预测数据插入失败")
}
}
抛出异常, 事务会自动回滚, 如果方法正常执行, 则会自动提交事务.
13. Spring事务隔离级别有哪些?
Spring的注入方式包含以下五种:
- ISOLATION_DEFAULT: 用底层数据库的设置隔离级别, 数据库设置的是什么我就用什么;
- ISOLATIONREADUNCOMMITED: 未提交读, 最低的隔离级别, 事务未提交前, 就可被其他事务读取 (会出现幻读, 脏读, 不可重复读)
- ISOLATIONREADCOMMITTED:读已提交, 一个事务提交后才能被其他事务读取到(解决了幻读, 不可重复读), SQL server的默认级别
- ISOLATIONREPEATABLEREAD:可重复读, 保证多次读取同一个数据时, 其值都和事务开始时候的内容是一致,禁止读取到别的事务未提交的数据(会造成幻读), MySQL的默认级别;
- ISOLATION_SERIALIZABLE: 序列化, 代价最高最可靠的隔离级别, 该隔离级别能防止脏读, 不可重复读, 幻读
默认值为ISOLATION_DEFAULT遵循数据库的事务隔离级别设置
14.Spring声明式事务无效可能的原因有哪些?
可能的原因如下:
- MySQL使用的是MyISAM引擎, 而MyISAM就不支持事务的;
- @Transactional使用在非方法上, @Transactional注解只能支持public级别, 其他类型声明的事务不会生效;
- @Transactional在同一个类中无事务方法A()内部调用有事务方法B(), 那么此时B()事务不会生效
15.Spring中的AOP底层实现原理是什么?
Spring AOP的底层实现原理就是动态代理
Spring AOP的动态代理有两种实现方式, 对于接口使用的是JDK自带的动态代理来实现的, 而对于非接口使用的是CGLIB来实现的
16. Spring中的Bean是线程安全的吗?
Spring中的Bean默认是单例模式, Spring框架并没有对单例模式bean进行多线程的封装处理, 因此默认的情况Bean并非是安全的, 最简单保证Bean安全的举措就是设置Bean的作用域越来越Prototype模式, 这样每次请求都会创建一个bean
17.Spring中bean的生命周期:
Spring中bean的生命周期如下:
- 实例化Bean: 对于BeanFactory容器, 当客户向容器请求一个尚未初始化的Bean时, 或初始化Bean的时候需要注入另一个尚未初始化的依赖时, 容器就会调用createBean进行实例化, 对于ApplicationContext容器,
当容器启动结束后, 通过获取BeanDefinition对象中的信息, 实例化所有的bean - 设置对象属性(依赖注入):实例化后的对象被封装在BeanWrapper对象中, 紧接着Spring根据BeanDefinition中的信息以及通过BeanWrapper提供的设置属性的接口完成依赖注入;
- 处理Aware接口:Spring会检测该对象是否实现了xxxAware接口, 并将相关的xxxAware实例注入给Bean:
- 如果这个Bean已经实现了BeanNameAware接口, 会调用他是西安的setBeanName(String BeanId)方法, 此处传递的就是Spring配置文件中Bean的id值;
- 如过这个Bean已经实现了BeanFactoryAware接口, 会调用他实现的setBeanFactory()方法, 传递的时Spring工厂自身;
- 如果这个Bean已经实现了ApplicationContextAware接口, 会调用setApplicationContext(ApplicationContext)方法, 传入Spring上下文;
- BeanPostProcessor: 如果想对Bean进行一些自定义的处理, 那么可以让Bean实现了BeanPostProcessor接口, 那将会电泳postProcessBeforeInitialization(Object obj, String s)方法;
- InitializingBean与init-method:如果Bean在Spring配置文件中配置了init-method属性, 则会自动调用其配置的初始化方法;
- 如果这个Bean实现了BeanPostProcessor接口, 将会调用postProcessAfterInitialication(Object obj, String s)方法;由于这个方法实在Bean初始化结束时调用的, 因而可以被应用于内存或缓存技术;
18.Spring有哪些优点?
Spring优点如下:
- 开源免费的热门框架, 稳定性高, 解决问题成本低;
- 方便继承各种优秀的框架
- 降低了代码耦合性, 通过Spring提供的IoC容器, 我们可以将对象之间的依赖关系交由Spring进行控制, 避免硬编码所造成的过度程序耦合;
- 方便程序测试, 在Spring里, 测试变得非常简单, 例如:Spring对Junit的支持, 可以通过注解方便的测试Spring程序;
- 降低Java EE API的使用难度, Spring对很多难用的Java EE API(如JDBC, JavaMail, 远程调用等)提供了一层封装, 通过Spring的简易封装, 让这些Java EE API的使用难度大为降低。
19.Spring, SpringBoot, SpringCloud的区别就什么?
区别:
- Spring Framework简称Spring, 是整个Spring生态的基础。
- SpringBoot是一个快速开发框架, 让开发者可以迅速搭建一套基于Spring的应用程序, 并且将常用的Spring模块以及第三方模块, 如MyBatis, Hibernate等都作了很好的集成, 值需要简单的配置即可使用, 不需要任何的xml配置文件, 真正做到了开箱即用,
同时默认支持JSON格式的数据, 使用Spring Boot进行前后端分离开发也非常便捷。 - SpringCloud就一套整合了分布式应用常用模块
Spring MVC
01.简述一下Spring MVC的执行流程?
答: 前端控制器(DispatcherServlet)接收请求, 通过映射从IoC容器中获取对应的Controller对象和Method方法, 在方法中进行业务逻辑处理组装数据, 组装完数据把数据发给视图解析器, 视图解析器根据数据和页面信息生成最终的页面, 然后再返回给客户端
02.POJO和JavaBean有什么区别?
POJO和JavaBean的区别如下:
- POJO(Plain Ordinary Java Object)普通Java类, 具有getter/setter方法的普通类都可以称作POJO, 它是DO/DTO/BO/VO的统称, 禁止命名成xxxPOJO).
- JavaBean是Java语言中的一种可重用组件, JavaBean的构造函数和行为必须符合特定的约定: 这个类必须有一个公共的缺省构造函数; 这个类的属性使用getter/setter来访问, 其他方法遵从标准命名规范; 这个类就是可序列化的.)
简而言之, 当一个POJO可序列化, 有一个无参的构造函数, 它就是一个JavaBean
03.如何实现跨域访问?
常见的跨域的实现方式有两种: 使用Nginx代理或者在服务器设置运行跨域. 服务器运行跨域的代码如下:
@Configuration
public class MyConfiguration{
@Bean
public WebMvcConfigurer corsConfigurer(){
return new WebMvcConfigurer() {
public void addCorsMappings(CorsRegistry registry) {
registry.addMappint("/api/**");
}
}
}
}
04.以下代码描述正确的是?
@RequestMapping(value = "/list", params = {"age=10"})
public String list(){
//todo something
}
A: age参数不传递的时候, 默认值是10
B: age参数可以为空
C: age参数不能为空
D: 以上都不对.
答案:\
C, params={"age=10"}
表示必须包含age参数, 且值必须等于10.
05.@RequestMapping注解的常用属性有哪些?
@RequestMapping常用属性如下:
- value: 指定URL请求的实际地址, 用法: @RequestMapping(value="/index")
- method: 指定请求的method类型, 如GET/POST/PUT/DELETE等, 用法:
@RequestMapping(value="/list", method=RequestMethod.POST);
- params: 指定请求参数中必须包含的参数名称, 如果不存在该名称, 则无法调用此方法, 用法:@RequestMapping(value="/list", params={"name","age"}).
06.访问以下接口不传递任何参数的情况下, 执行的结果是?
@RequestMapping(value="/list")
@ResponseBody
public String list(int id) {
return "id="+id;
}
A: id=0
B: id=
C: 页面报错 500
D: id=null
答案:
C, 页面报错会提示:可选的参数id
不能转为null,因为基本类型不能赋值null,所以会报错。
07.访问页面时显示403代表的含义是?
A: 服务器繁忙
B: 找不到该页面
C: 禁止访问
D: 服务器跳转中
答案:
C, 常用HTTP状态码及对应的含义:
HTTP状态码 | 含义 |
---|---|
400 | 错误请求, 服务器不理解请求的语法 |
401 | 未授权, 请求要求身份验证 |
403 | 禁止访问, 服务器拒绝请求 |
500 | 服务器内部错误, 服务器遇到错误, 无法完成请求 |
502 | 错误网关, 服务器作为网关或代理, 从上游服务器收到无效响应 |
504 | 网关超时, 服务器作为网关或代理, 但是没有及时从上游服务器收到请求 |
08.forward和redirect有什么区别?
答案:forward和redirect区别如下:
- forward表示请求转发, 请求转发是服务器的行为; redirect表示重定向, 重定向是客户端行为;
- forward是服务器请求资源, 服务器直接访问把请求的资源转发给浏览器, 浏览器根本不知道服务器的内容是从哪来的, 因此它的地址栏还是的地址; redirect是服务端发送一个状态码告诉浏览器重新请求新的地址, 因此地址栏显示的是新的URL;
- forward转发页面和转发到的页面可以共享request里面的数据;redirect不能共享数据;
- 从效率来说, forward比redirect效率更高.
09.访问以下接口不传递任何参数的情况下, 执行的结果是?
@RequestMapping(value="/list")
@ResponseBody
public String list(Integer id) {
return "id="+id;
}
A: id=0
B: id=
C: 页面报错 500
D: id=null
答案:
D, 包装类可以赋值null, 不会报错.
10.Spring MVC中如何在后端代码中实现页面跳转?
答案:
在后端代码中可以使用forward:/index.jsp
或redirect:/index.jsp
完成页面跳转, 前者URL地址不会发生改变, 或者URL地址会发生改变, 完整跳转代码如下:
@RequestMapping("/redirect")
public String redirectTest(){
return "redirect:/index.jsp";
}
11.Spring MVC的常用注解有哪些?
常用注解 | 说明 |
---|---|
@Controller | 用于标记某个类为控制器 |
@ResponseBody | 标识返回的数据不是html标签的页面, 而是某种格式的数据, 如JSON, XML等 |
@RestController | 相当于@Controller加@ResponseBody的组合效果 |
@Component | 标识为Spring的组件 |
@Configuration | 用于定义配置类 |
@RequestMapping | 用于映射请求地址的注解 |
@Autowired | 自动装配对象 |
@RequestHeader | 可以把Request请求的header值绑定到方法的参数上 |
12.拦截器的使用场景有哪些?
答案:
- 日志记录: 可用于记录请求日志, 便于信息监控和信息统计;
- 权限检查: 可用于用户登录状态的检查;
- 统一安全处理: 可用于统一的安全校验或参数的加密/解密等.
13.Spring MVC如何排除拦截目录?
在Spring MVC的配置文件中, 添加, 用于排除拦截目录, 完整配置的示例代码如下:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<!-- 排除拦截地址 -->
<mvc:exclude-mapping path="/api/**" />
<bean class="com.example.MyInterceptor"></bean>
</mvc:interceptors>
14.@Validated和@Valid有什么区别?
@Validated和@Valid都用于参数的校验, 不同的是:
- @Valid是Hibernate提供的校验机制, Java的JSR 303声明了@Valid这个类接口, 而Hibernate-validator对其进行了实现; @Validated是Spring提供的校验机制, @Validated是对Hibernate中的@Valid进行了二次封装, 提供了分组功能, 可以在参数验证时, 根据不同的分组采用不同的验证机制;
- @Valid可用在成员对象的属性字段验证上, 而@Validated不能用于成员对象的属性字段验证上, 也就是说@Validated无法提供嵌套验证.
15.Spring MVC有几种获取request的方式?
Spring MVC获取request有以下三种方式:
- 从请求参数中获取:
示例代码:
@RequestMapping("/index")
public void index(HttpServletRequest request){
// todo something
}
该方法实现的原理是Controller开始处理请求时, Spring会将request对象赋值到方法参数中.
- 通过RequestContextHolder上下文获取request对象
示例代码:
@RequestMapping("/index")
public void index(){
ServletRequestAttributes attrbutes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
HttpServletRequest request = servletRequestAttributes.getRequest();
}
- 通过自动注入的方式
@Controller
public class HomeController{
@Autowired
private HttpServletRequest request; //自动注入request对象
// todo somethind
}
标签:事务,Spring,练习,bean,面试,Bean,注解,public
From: https://www.cnblogs.com/jtc-terrence/p/16769947.html