Spring总结
列举一些Spring的重要模块
Spring Core: 核心类库,Spring 其他所有的功能都需要依赖于该类库。主要提供 IoC 依赖注⼊功能。
Spring AOP: 提供了⾯向切⾯的编程实现。
Spring DAO:对JDBC进行了抽象,简化了数据访问异常等处理。
Spring ORM: ⽤于⽀持Hibernate等ORM⼯具,对现有的ORM持久层框架进行了支持。
Spring MVC:提供面向Web应用的Model-View-Controller实现。
Spring Web:提供了基本的面向Web的综合特性。
Spring JMS: Java消息服务。
Spring Aspects: 为与AspectJ的集成提供⽀持。
Spring JDBC: Java数据库连接。
Spring Test: 提供了对 JUnit 和 TestNG 测试的⽀持。
@Controller vs @RestController
@Controller 返回一个页面
单独使⽤ @Controller 不加 @ResponseBody 的话⼀般使⽤在要返回⼀个视图的情况,
这种情况属于传统的 Spring MVC 的应⽤,对应于前后端不分离的情况。
@Controller + @ResponseBody,返回 JSON 或 XML 数据
在Spring4之前开发 RESTful Web 服务的话,需要使⽤ @Controller 并结合 @ResponseBody 注解,
即, @Controller + @ResponseBody = @RestController (Spring 4 之后新加的注解)。
@RestController,返回 JSON 或 XML 数据
@RestController 只返回对象,对象数据直接以 JSON 或 XML 形式写⼊ HTTP 响应(Response)中,
这种情况属于 RESTful Web服务,这也是⽬前⽇常开发最常⽤的情况(前后端分离)。
Spring IOC & AOP
IOC
IoC(Inverse of Control, 控制反转)是⼀种设计思想,将原本在程序中⼿动创建对象的控制权,交由Spring框架来管理。 IoC 在其他语⾔中也有应⽤,并⾮ Spring 特有。
IoC 容器是 Spring ⽤来实现 IoC 的载体,IoC 容器实际上就是个 Map(key,value),Map 中存放的是各种对象。
将对象之间的相互依赖关系交给 IoC 容器来管理,并由 IoC 容器完成对象的注入
这样可以很⼤程度上简化应⽤的开发,把应⽤从复杂的依赖关系中解放出来。
IoC 容器就像是⼀个⼯⼚⼀样,当我们需要创建⼀个对象的时候,只需要配置好配置⽂件/注解即可,完全不⽤考虑对象是如何被创建出来的。
在实际项⽬中⼀个 Service 类可能有⼏百甚⾄上千个类作为它的底层,假如我们需要实例化这个Service,你可能要每次都要搞清这个 Service 所有底层类的构造函数,这可能会把⼈逼疯。如果利⽤IoC 的话,你只需要配置好,然后在需要的地⽅引⽤就⾏了,这大大增加了项⽬的可维护性,降低了开发难度。
Spring 时代我们⼀般通过 XML ⽂件来配置 Bean,后来开发⼈员觉得 XML ⽂件来配置不太好,于是 SpringBoot 注解配置就慢慢开始流⾏起来。
IOC 的好处
https://www.zhihu.com/question/23277575/answer/169698662
IOC 源码阅读
https://javadoop.com/post/spring-ioc
AOP
AOP(Aspect-Oriented Programming, ⾯向切⾯编程)将那些与业务⽆关,被业务模块所共同调⽤的逻辑(如事务处理、⽇志管理、权限控制等)封装起来,便于减少系统的重复代码,降低模块间的耦合度,有利于未来的可拓展性和可维护性。
Spring AOP就是基于动态代理的,如果要代理的对象,实现了某个接⼝,那么 Spring AOP会使⽤ JDK Proxy,去创建代理对象;对于没有实现接⼝的对象,就⽆法使⽤ JDK Proxy 去进⾏代理了,这时候 Spring AOP 会使⽤ Cglib ,这时候Spring AOP会使⽤ Cglib ⽣成⼀个被代理对象的⼦类来作为代理。
也可以使⽤ AspectJ,Spring AOP 已经集成了 AspectJ,AspectJ 应该算的上是 Java ⽣态系统中最完整的 AOP 框架了。使⽤ AOP 之后我们可以把⼀些通⽤功能抽象出来,在需要⽤到的地⽅直接使⽤即可,这样⼤⼤简化了代码量。我们需要增加新功能时也⽅便,这样也提⾼了系统扩展性。⽇志功能、事务管理等场景都⽤到了 AOP。
Spring AOP 和 AspectJ AOP 的区别
Spring AOP 属于运⾏时增强,而 AspectJ 是编译时增强。
Spring AOP 基于代理(Proxying),而 AspectJ 基于字节码操作(Bytecode Manipulation)。
AspectJ 相⽐于 Spring AOP 功能更加强⼤,但是 Spring AOP 相对来说更简单,如果切面比较少,那么两者性能差异不⼤。但是,当切⾯太多的话,最好选择 AspectJ ,它⽐Spring AOP 快很多。
Spring bean
Spring bean 是什么
Bean 是 Spring 框架中最核心的两个概念之一(另一个是面向切面编程AOP)。
概念:
Spring 中,构成应用程序主干并由 Spring IoC 容器管理的对象称为 bean。
bean 是一个由Spring IoC 容器实例化、组装和管理的对象。
提取关键的信息:
(1)bean 是对象,一个或者多个
(2)bean 由 Spring 中 IoC 的容器管理
(3)应用程序由多个 bean 构成
Spring 中 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 都有不同的会话。
Spring 中的单例 bean 的线程安全问题
单例 bean 存在线程问题,主要是因为当多个线程操作同⼀个对象的时候,对这个对象的⾮静态成员变量的写操作会存在线程安全问题。
常见的解决方法:
(1)在Bean对象中尽量避免定义可变的成员变量(不太现实)。
(2)在类中定义⼀个 ThreadLocal 成员变量,将需要的可变成员变量保存在 ThreadLocal 中(推荐的⼀种方式)。
@Component 和 @Bean 的区别
(1)作⽤对象不同: @Component 注解作⽤于类,⽽ @Bean 注解作⽤于⽅法。
(2)@Component 通过类路径扫描来⾃动侦测以及⾃动装配到Spring容器中。@Bean 在标有该注解的⽅法中定义产⽣这个 bean, @Bean 告诉了Spring这是某个类的示例,当我需要⽤它的时候还给我。
(3)@Bean 注解比 Component 注解的⾃定义性更强,很多地方我们只能通过 @Bean 注解来注册bean。如引⽤第三⽅库中的类装配到 Spring 容器时,则只能通过@Bean来实现。
将⼀个类声明为 Spring 中 bean 的注解
@Autowired 注解自动装配 bean,把类标识成可⽤于 @Autowired 注解⾃动装配的 bean 的类,采⽤以下注解可实现:
@Component:通⽤的注解,可标注任意类为 Spring 组件。如果⼀个Bean不知道属于哪个层,可以使⽤ @Component 注解标注。
@Repository: 对应持久层即 Dao 层,主要⽤于数据库相关操作。
@Service: 对应服务层,主要涉及⼀些复杂的逻辑,需要⽤到 Dao层。
@Controller: 对应 Spring MVC 控制层,主要⽤户接受⽤户请求并调⽤ Service 层返回数据给前端⻚⾯。
Spring 中 bean 的⽣命周期
https://yemengying.com/2016/07/14/spring-bean-life-cycle/
https://www.cnblogs.com/zrtqsk/p/3735273.html