IoC 容器是 Spring⽤来实现 IoC 的载体, IoC 容器实际上就是个Map(key,value),Map 中存放的是各种对象。将对象之间的相互依赖关系交给 IoC 容器来管理,并由 IoC 容器完成对象的注⼊。这样可以很⼤程度上简化应⽤的开发,把应⽤从复杂的依赖关系中解放出来。 IoC 容器就像是⼀个⼯⼚⼀样,当我们需要创建⼀个对象的时候,只需要配置好配置⽂件/注解即可,完全不⽤考虑对象是如何被创建出来的。
2、Spring AOP,动态代理
AOP(Aspect-Oriented Programming:⾯向切⾯编程)能够将那些与业务⽆关,却为业务模块所共同调⽤ 的逻辑或责任(例如事务处理、⽇志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模 块间的耦合度,并有利于未来的可拓展性和可维护性。
Spring AOP就是基于动态代理的,如果要代理的对象,实现了某个接⼝,那么Spring AOP会使⽤JDK Proxy,去创建代理对象,⽽对于没有实现接⼝的对象,就⽆法使⽤ JDK Proxy 去进⾏代理了,这时候 Spring AOP会使⽤Cglib ,这时候Spring AOP会使⽤ Cglib ⽣成⼀个被代理对象的⼦类来作为代理,
3、Bean生命周期
单例对象: singleton
出生:当容器创建时对象出生
活着:只要容器还在,对象一直或者
死亡:容器销毁,对象消亡
总结:单例对象的生命周期和容器相同
多例对象: prototype
出生: 使用对象时spring框架为我们创建
活着:对象只要是在使用过程中就一直活着
死亡:当对象长时间不用且没有其它对象引用时,由java的垃圾回收机制回收
4、Bean作用域?默认什么级别?是否线程安全?Spring如何保障线程安全的?
| 名称 | |
| — | — |
| singleton | 单例对象,默认值的作用域 |
| prototype | 每次获取都会创建⼀个新的 bean 实例 |
| request | 每⼀次HTTP请求都会产⽣⼀个新的bean,该bean仅在当前HTTP request内有效。 |
| session | 在一次 HTTP session 中,容器将返回同一个实例 |
global-session 将对象存入到web项目集群的session域中,若不存在集群,则global session相当于session
默认作用域是singleton,多个线程访问同一个bean时会存在线程不安全问题
保障线程安全方法:
在Bean对象中尽量避免定义可变的成员变量(不太现实)。
在类中定义⼀个ThreadLocal成员变量,将需要的可变成员变量保存在 ThreadLocal 中
ThreadLocal:
每个线程中都有一个自己的ThreadLocalMap类对象,可以将线程自己的对象保持到其中,各管各的,线程可以正确的访问到自己的对象。
将一个共用的ThreadLocal静态实例作为key,将不同对象的引用保存到不同线程的ThreadLocalMap中,然后在线程执行的各处通过这个静态ThreadLocal实例的get()方法取得自己线程保存的那个对象,避免了将这个对象作为参数传递的麻烦。
5、Spring事务隔离级别和事务传播属性
隔离级别:
-
DEFAULT (默认) 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别。另外四个与JDBC的隔离级别相对应。
-
READ_UNCOMMITTED (读未提交) 这是事务最低的隔离级别,它允许另外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。
-
READ_COMMITTED (读已提交) 保证一个事务修改的数据提交后才能被另外一个事务读取,另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。
-
REPEATABLE_READ (可重复读) 这种事务隔离级别可以防止脏读、不可重复读,但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了不可重复读。
-
SERIALIZABLE(串行化) 这是花费最高代价但是最可靠的事务隔离级别,事务被处理为顺序执行。除了防止脏读、不可重复读外,还避免了幻像读。
Spring事务传播属性(Propagation):
-
REQUIRED(默认属性) 如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。 被设置成这个级别时,会为每一个被调用的方法创建一个逻辑事务域。如果前面的方法已经创建了事务,那么后面的方法支持当前的事务,如果当前没有事务会重新建立事务。
-
MANDATORY 支持当前事务,如果当前没有事务,就抛出异常。
-
NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。
-
NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
-
REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。
-
SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。
-
NESTED 支持当前事务,新增Savepoint点,与当前事务同步提交或回滚。 嵌套事务一个非常重要的概念就是内层事务依赖于外层事务。外层事务失败时,会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚。
6、Spring以及Spring MVC常见注解
Spring部分:
声明bean的注解
@Component 通⽤的注解,可标注任意类为 Spring 组件
@Service 在业务逻辑层使用(service层)
@Repository 在数据访问层使用(dao层)
@Controller 在展现层使用,控制器的声明(controller层)
注入bean的注解
@Autowired:可以对类成员变量、方法、构造方法进行标注
默认按照类型注入,若要按照名称注入,需要搭配**@Qualifier**注解一起使用
@Resource:默认按照名称来装配注入
Spring MVC部分:
@Controller 声明该类为SpringMVC中的Controller
@RequestMapping 用于映射Web请求
@ResponseBody 支持将返回值放在response内,而不是一个页面,通常用户返回json数据
@RequestBody 允许request的参数在request体中,而不是在直接连接在地址后面。
@PathVariable 用于接收路径参数,比如@RequestMapping("/hello/{name}")申明的路径,将注解放在参数中前,即可获取该值,通常作为Restful的接口实现方法。
7、@autowired和@resource的区别?
@Autowired:可以对类成员变量、方法、构造方法进行标注
默认按照类型注入,若要按照名称注入,需要搭配**@Qualifier**注解一起使用
@Resource:默认按照名称来装配注入
8、mybatis如何防止sql注入?$和#的区别是什么?传入表名用哪个?
防止sql注入:
在编写mybatis的映射语句时,尽量采用“#{xxx}”这样的格式
#和$区别:
| # | $ |
| — | — |
| 相当于对数据加上双引号 | 相当于直接显示数据 |
| 很大程度上防止SQL注入 | 无法防止SQL注入 |
| #{xxx},使用的是PreparedStatement,会有类型转换,比较安全 | ${xxx},使用字符串拼接,容易SQL注入 |
简单的说就是#{}是经过预编译的,是安全的,${}是未经过预编译的,仅仅是取变量的值,是非安全的,存在SQL注入。
要实现动态传入表名、列名,需要做如下修改:
添加属性statementType=“STATEMENT”,同时sql里的属有变量取值都改成${xxxx}
9、Spring MVC工作原理
客户端(浏览器)发送请求,直接请求到 DispatcherServlet 。
DispatcherServlet 根据请求信息调⽤ HandlerMapping ,解析请求对应的 Handler 。
解析到对应的 Handler (也就是 Controller 控制器)后,开始由HandlerAdapter 适配器处理。
HandlerAdapter 会根据 Handler 来调⽤真正的处理器开处理请求,并处理相应的业务逻辑。
处理器处理完业务后,会返回⼀个 ModelAndView 对象, Model 是返回的数据对象
ViewResolver 会根据逻辑 View 查找实际的 View 。
DispaterServlet 把返回的 Model 传给 View (视图渲染)。
把 View 返回给请求者(浏览器)
最后
以上分享的全部分布式技术专题+面试解析+相关的手写和学习的笔记pdf,高清完整版戳这里免费领取
还有更多Java笔记分享如下:
andler 来调⽤真正的处理器开处理请求,并处理相应的业务逻辑。
处理器处理完业务后,会返回⼀个 ModelAndView 对象, Model 是返回的数据对象
ViewResolver 会根据逻辑 View 查找实际的 View 。
DispaterServlet 把返回的 Model 传给 View (视图渲染)。
把 View 返回给请求者(浏览器)
最后
以上分享的全部分布式技术专题+面试解析+相关的手写和学习的笔记pdf,高清完整版戳这里免费领取
还有更多Java笔记分享如下: