1.Spring
1.1什么是Spring框架?
Spring 是⼀种轻量级开发框架,旨在提⾼开发⼈员的开发效率以及系统的可维护性。
Spring 的 6 个特征:核⼼技术,测试,数据访问,Web⽀持,集成,语⾔
1.2列举⼀些重要的Spring模块?
Spring Core : 基础 , 可以说 Spring 其他所有的功能都需要依赖于该类库。主要提供 IoC 依
赖注⼊功能。
Spring Aspects : 该模块为与 AspectJ 的集成提供⽀持。
Spring AOP :提供了⾯向切⾯的编程实现。
Spring JDBC : Java 数据库连接。
Spring JMS : Java 消息服务。
Spring ORM : ⽤于⽀持 Hibernate 等 ORM ⼯具。
Spring Web : 为创建 Web 应⽤程序提供⽀持。
Spring Test : 提供了对 JUnit 和 TestNG 测试的⽀持
1.3@RestController vs @Controller
Controller 返回⼀个⻚⾯
单独使⽤ @Controller 不加 @ResponseBody 的话⼀般使⽤在要返回⼀个视图的情况,这种情况
属于⽐传统的 Spring MVC 的应⽤,对应于前后端不分离的情况。
@RestController 返回 JSON 或 XML 形式数据
但 @RestController 只返回对象,对象数据直接以 JSON 或 XML 形式写⼊ HTTP 响应
(Response) 中,这种情况属于 RESTful Web 服务,这也是⽬前⽇常开发所接触的最常⽤的情况
(前后端分离)。
@Controller +@ResponseBody 返回 JSON 或 XML 形式数据
如果你需要在 Spring4 之前开发 RESTful Web 服务的话,你需要使⽤ @Controller 并结
合 @ResponseBody 注解,也就是说 @Controller + @ResponseBody = @RestController ( Spring 4
之后新加的注解)。
@ResponseBody将对象转换成JSON 或者XML形式
@ResponseBody 注解的作⽤是将 Controller 的⽅法返回的对象通过适当的转换器转换为指
定的格式之后,写⼊到 HTTP 响应 (Response) 对象的 body 中,通常⽤来返回 JSON 或者
XML 数据,返回 JSON 数据的情况⽐较多。
1.4Spring IOC & AOP
IOC
IoC( Inverse of Control: 控制反转)是⼀种 设计思想 ,就是 将原本在程序中⼿动创建对象的控制 权,交由 Spring 框架来管理。 IoC 容器是 Spring ⽤来实现 IoC 的载体, IoC 容器实际上就是个 Map ( key , value ) ,Map 中存放的是各 种对象。
将对象之间的相互依赖关系交给 IoC 容器来管理,并由 IoC 容器完成对象的注⼊。 IoC 容器就像是⼀个⼯⼚⼀ 样,当我们需要创建⼀个对象的时候,只需要配置好配置⽂件 / 注解即可,完全不⽤考虑对象是如 何被创建出来的。
AOP
AOP(Aspect-Oriented Programming:⾯向切⾯编程 ) 能够将那些与业务⽆关, 却为业务模块所共 同调⽤的逻辑或责任(例如事务处理、⽇志管理、权限控制等)封装起来 ,便于 减少系统的重复
代码 , 降低模块间的耦合度 ,并 有利于未来的可拓展性和可维护性 。
Spring AOP就是基于动态代理的 ,如果要代理的对象,实现了某个接⼝,那么 Spring AOP 会使⽤JDK Proxy ,去创建代理对象,⽽对于没有实现接⼝的对象, 这时候 Spring AOP 会使⽤ Cglib ⽣成⼀个被代理对象的⼦类来作为代理
1.5Spring AOP 和 AspectJ AOP 有什么区别?
Spring AOP 属于运⾏时增强,⽽ AspectJ 是编译时增强。 Spring AOP 基于代理 (Proxying) ,⽽ AspectJ 基于字节码操作 (Bytecode Manipulation) 。
Spring AOP 已经集成了 AspectJ , AspectJ 应该算的上是 Java ⽣态系统中最完整的 AOP 框
架了。 AspectJ 相⽐于 Spring AOP 功能更加强⼤,但是 Spring AOP 相对来说更简单,如果我们的切⾯⽐较少,那么两者性能差异不⼤。但是,当切⾯太多的话,最好选择 AspectJ ,它⽐Spring AOP 快很多。
1.6Spring 中的 bean 的作⽤域有哪些?
singleton : 唯⼀ bean 实例, Spring 中的 bean 默认都是单例的。
prototype : 每次请求都会创建⼀个新的 bean 实例。
request : 每⼀次 HTTP 请求都会产⽣⼀个新的 bean ,该 bean 仅在当前 HTTP request 内有
效。
session : 每⼀次 HTTP 请求都会产⽣⼀个新的 bean ,该 bean 仅在当前 HTTP session 内有
效。
global-session : 全局 session 作⽤域,仅仅在基于 portlet 的 web 应⽤中才有意义, Spring5 已
经没有了。 Portlet 是能够⽣成语义代码 ( 例如: HTML) ⽚段的⼩型 Java Web 插件。它们基于
portlet 容器,可以像 servlet ⼀样处理 HTTP 请求。但是,与 servlet 不同,每个 portlet 都有不
同的会话
1.7Spring 中的单例 bean 的线程安全问题了解吗?
单例 bean 存在线程问题,主要是因为当多个线程操作同⼀个对象的时候,对这个对象的⾮静态成员变量的写操作会存在线程安全问题。
常⻅的有两种解决办法:
1. 在 Bean 对象中尽量避免定义可变的成员变量(不太现实)。
2. 在类中定义⼀个 ThreadLocal 成员变量,将需要的可变成员变量保存在 ThreadLocal 中(推
荐的⼀种⽅式)。
1.8@Component 和 @Bean 的区别是什么?
1. 作⽤对象不同 : @Component 注解作⽤于类,⽽ @Bean 注解作⽤于⽅法。
2. @Component 通常是通过类路径扫描来⾃动侦测以及⾃动装配到 Spring 容器中(我们可以使
⽤ @ComponentScan 注解定义要扫描的路径从中找出标识了需要装配的类⾃动装配到
Spring 的 bean 容器中)。 @Bean 注解通常是我们在标有该注解的⽅法中定义产⽣这个
bean, @Bean 告诉了 Spring 这是某个类的示例,当我需要⽤它的时候还给我。
3. @Bean 注解⽐ Component 注解的⾃定义性更强,⽽且很多地⽅我们只能通过 @Bean 注
解来注册 bean 。⽐如当我们引⽤第三⽅库中的类需要装配到 Spring 容器时,则只能通过
@Bean 来实现。
1.9将⼀个类声明为Spring的 bean 的注解有哪些?
我们⼀般使⽤ @Autowired 注解⾃动装配 bean ,要想把类标识成可⽤于 @Autowired 注解⾃动
装配的 bean 的类 , 采⽤以下注解可实现:
@Component :通⽤的注解,可标注任意类为 Spring 组件。如果⼀个 Bean 不知道属于哪
个层,可以使⽤ @Component 注解标注。
@Repository : 对应持久层即 Dao 层,主要⽤于数据库相关操作。
@Service : 对应服务层,主要涉及⼀些复杂的逻辑,需要⽤到 Dao 层。
@Controller : 对应 Spring MVC 控制层,主要⽤户接受⽤户请求并调⽤ Service 层返回数
据给前端⻚⾯。
1.10Spring 中的 bean ⽣命周期?
Bean 容器找到配置⽂件中 Spring Bean 的定义。
Bean 容器利⽤ Java Reflection API 创建⼀个 Bean 的实例。
如果涉及到⼀些属性值 利⽤ set() ⽅法设置⼀些属性值。
如果 Bean 实现了 BeanNameAware 接⼝,调⽤ setBeanName() ⽅法,传⼊ Bean 的名字。
如果 Bean 实现了 BeanClassLoaderAware 接⼝,调⽤ setBeanClassLoader() ⽅法,传⼊
ClassLoader 对象的实例。
与上⾯的类似,如果实现了其他 *.Aware 接⼝,就调⽤相应的⽅法。
如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执
⾏ postProcessBeforeInitialization() ⽅法
如果 Bean 实现了 InitializingBean 接⼝,执⾏ afterPropertiesSet() ⽅法。
如果 Bean 在配置⽂件中的定义包含 init-method 属性,执⾏指定的⽅法。
} 如果有和加载这个 Bean 的 Spring 容器相关的 BeanPostProcessor 对象,执⾏ postProcessAfterInitialization() ⽅法
当要销毁 Bean 的时候,如果 Bean 实现了 DisposableBean 接⼝,执⾏ destroy() ⽅法。
当要销毁 Bean 的时候,如果 Bean 在配置⽂件中的定义包含 destroy-method 属性,执⾏指
定的⽅法。