Spring
1.说说你对Spring的_IOC_机制的理解可以吗?
程序的耦合和解耦 IOC叫控制反转其目的就是为了降低程序的耦合性,使类与类之间彻底的解耦合(现在这套比较高大上的一点系统里,有几十个类都使用了@Resource或者@Autowired这个注解去标注MyService myService, 几十个地方都依赖了这个类,如果要修改实现类为NewServiceManagerlmpl,此时只需要将MyService中注解@Service加到NewServiceManagerlmpl中即可 ),不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。比如,某个实现类注解@Service 而控制层代码
@Autowired
private IAccountCustomerService accountCustomerService;
此时就会把service注入到控制层中。


依赖注入(Dependency Injection,DI),是组件之间依赖关系由容器在运行期决定,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。
依赖注入的常见实现方式
- setter 注入
- 构造方法注入
- 注解注入
1.setter 注入
Java代码:
public class UserController {
// 注入 UserService 对象
private UserService userService;
public void setUserService(UserService userService){
this.userService = userService;
}
}
XML配置:
<bean name="userController" class="com.learning.controller.UserController">
<!-- 依赖注入 -->
<property name="userService" ref="userService"></property>
</bean>
<bean name="userService" class="com.learning.dao.impl.UserServiceImpl"></bean>
Bean 标签的常用属性说明:
id:为实例化对象起名称,根据 id 值可以得到我们配置的实例化对象,id 属性的名称原则上可以任意命名,但是能包含任何特殊符号; class:创建对象所在类的全路径; name:功能和 id 属性一样,但是现在一般不用;与 id 的区别在于:name 属性值里可以包含特殊符号,但是 id 不可以; scope:一般最常用的有两个值: Singleton:单例模式,整个应用程序,只创建 bean 的一个实例;Prototype:原型模式,每次注入都会创建一个新的 bean 实例,Spring 默认的是单例模式。
2.构造方法注入
Java 代码:
public class UserController {
private UserService userService;
public UserController(UserService userService){
this.userService = userService;
}
}
XML配置:
<bean name="userController" class="com.learning.controller.UserController">
<!-- 依赖注入 -->
<constructor-arg ref="userService"></constructor-arg>
</bean>
<bean name="userService" class="com.learning.dao.impl.UserServiceImpl"></bean>
3.注解注入
@Controller
public class UserController {
// 使用注解自动注入
@Autowired()
private UserService userService;
// do something
}
// 创建依赖对象
@Service
public class UserService {
// do something
}
创建依赖对象的常见注解:@Component、@Controller、@Service、@Repository。
总结:可以看出注解的方式要比传统的 XML(setter 和构造器注入)实现注入更为方便,同时注解方式也是官方力推的依赖注入最佳使用方式。

2.说说你对Spring的AOP机制的理解?
Spring 核心框架里面,最关键的两个机制,就是ioc和aop。根据xml配置或者注解,去实例化我们所有的bean,管理bean之间的依赖注入,让类与类之间的耦合性降低,维护代码的时候更加方便轻松。
AOP是面向切面编程,简单的说就是把我们重复的代码抽取出来,在需要执行的时候,使用动态代理技术,在不修改源码的基础上,对我们已有的方法进行增强。
AOP的作用和优势
作用:在程序运行期间,不修改源码对已有方法进行增强。
优势:减少重复代码,提高开发效率,维护方便
AOP的实现方式:使用动态代理技术
3.了解过cglib动态代理吗?他跟jdk动态代理的区别是什么?
Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理:
- JDK动态代理只提供接口的代理,不支持类的代理。核心InvocationHandler接口和Proxy类,InvocationHandler 通过invoke()方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起;接着,Proxy利用 InvocationHandler动态创建一个符合某一接口的的实例, 生成目标类的代理对象。
- 如果代理类没有实现 InvocationHandler 接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库,可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现AOP。CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。
4.能说说Spring中的Bean是线程安全的吗?
Spring容器中的Bean是否线程安全,容器本身并没有提供Bean的线程安全策略,因此可以说Spring容器中的Bean本身不具备线程安全的特性,但是具体还是要结合具体作用域(scope)的Bean去研究。
Spring中的bean的作用域(scope)有哪些?
- singleton : 单例,默认作用域。
- prototype : 原型,原型每次请求都会创建一个 新的bean实例。
- request : 请求,每一次HTTP请求都会产生一个新的bean,该bean仅 在当前HTTP request内有效。
- session : 会话,每一次HTTP请求都会产生一个新的bean, 该bean仅在当前HTTP session内有效。
- global-session : 全局session作用域,仅仅在基于portlet的web应用中才有意义,Spring5已经没有了。
Portlet是 能够生成语义代码(例如: HTML)片段的小型ava Web插件。它们基于portlet容器,可以像servlet一样处理HTTP请求。但是,与servlet不同,每个portlet都有不同的会话。
大部分时候我们并没有在系统中使用多线程,所以很少有人会关注这个问题。单例bean存在线程问题,主要是因为当多个线程操作同一个对象的时候,对这个对象的非静态成员变量的写操作会存在线程安全问题。常见的有两种解决办法: 1.在Bean对象中尽量避免定义可变的成员变量(不太现实)。2.在类中定义一个ThreadLocal成员变量,将需要的可变成员变量保存在 ThreadLocal中(推荐的一种方式)


是线程不安全的。spring bean默认来说是单例的,是线程不安全的。但是java web系统中,一般来说很少在spring bean中放一些实例变量,通常都是多个组件互相调用,最终去访问数据库的,所以一般结果就是多个线程并发的访问数据库。
5.Spring的事务实现原理是什么?能聊聊你对事务传播机制的理解吗?
事务的实现原理:如果说你加了一个@Transactional注解,此时spring就会使用AOP的思想,对你的这个方法在执行之前去开启事务,执行完毕之后,根据你方法是否报错,来决定回滚还是提交事务。
事务传播机制的理解:事务传播机制的理解
事务传播机制
比如说,我们现在有一段业务逻辑,方法A调用方法B,我希望的是如果说方法A出错了,此时仅仅回滚方法A,不能回滚方法B,必须得用REQUIRES-NEW,传播机制,让他们两的事务是不同的。
方法A调用方法B,如果出错,方法B只能回滚他自己,方法A可以带着方法B一起回滚,NESTED嵌套事务。
6.能说说Spring中使用了哪些设计模式吗?
工厂设计模式 : Spring使用工厂模式通过 BeanFactory、ApplicationContext创建 bean 对象。
代理设计模式 : Spring AOP 功能的实现。
单例设计模式 : Spring 中的 Bean 默认都是单例的。
模板方法模式 : Spring 中 jdbcTemplate、hibernateTemplate等以 Template 结尾的对数据库操作的类,它们就使用到了模板模式。
包装器设计模式 : 我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。这种模式让我们可以根据客户的需求能够动态切换不同的数据源。
观察者模式: Spring 事件驱动模型就是观察者模式很经典的一个应用。
适配器模式 :Spring AOP 的增强或通知(Advice)使用到了适配器模式、spring MVC 中也是用到了适配器模式适配Controller。
7.能说一说springMvc的核心架构么?
MVC是一种设计模式,Spring MVC是一款很优秀的MVC框架。Spring MVC可以帮助我们进行更简洁的Web层的开发,并且它天生与Spring框架集成。Spring MVC下我们一般把后端项目分为Service层(业务层 处理业务)、Dao层(持久层 数据库操作)、Entity层 (实体层 数据库在项目中的类)、Controller层(控制层,返回数据给前台页面)。原理如下图:

流程说明(重要) :
-
客户端(浏览器)发送请求,直接请求到DispatcherServlet (前端控制器) (图demo图1)。
-
DispatcherServlet根据请求信息调用HandlerMapping (处理器映射)(配置文件如下图demo图2),解析url请求对应的Handler (Controller控制器 demo图3)。
-
解析到对应的Handler (也就是我们平常说的Controller控制器)后,开始由HandlerAdapter 适配器处理(去找Controller)。
-
HandlerAdapter会根据Handler(Controller控制器)来调用真正的处理器开处理请求,并处理相应的业务逻辑(demo中没有业务层)。
-
处理器处理完业务后,会返回一个ModeLAndView对象(给HandlerAdapter),Model是返回的数据对象,View是个逻辑_上的View。
-
HandlerAdapter将视图逻辑名或者模型传递给DispatcherServlet
-
DispatcherServlet 调用ViewResolver(视图解析器----1、作用获取ModeLAndView数据 2、解析ModelAndView的视图名字 3、拼接地址名字 4、将数据渲染到这个视图上)会根据逻辑View查找实际的View.
-
DispaterServlet把返回的Model传给View (视图渲染)。
-
把View返回给请求者(浏览器)
http://c.biancheng.net/view/4392.html
Spring Boot 的Demo:
第一步注册DispatcherServlet 拦截所有的客户访问。




浙公网安备 33010602011771号