首页 > 技术文章 > Spring框架详解

xiaofengshan 2020-03-30 20:21 原文

简介

Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。Spring的核心是控制反转(IoC)和面向切面(AOP)。简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架。

常用注解

@Component:把资源让 spring 来管理。相当于在 xml 中配置一个 bean。

  • 属性: value:指定 bean 的 id。如果不指定 value 属性,默认 bean 的 id 是当前类的类名。首字母小写。

@Controller: 一般用于表现层的注解。其余同 @Component
@Service: 一般用于业务层的注解。其余同 @Component
@Repository: 一般用于持久层的注解。其余同 @Component
@Autowired:自动按照类型注入,使用要注入的对象变量名称作为 bean 的 id。
@Qualifier:在自动按照类型注入的基础之上,再按照 Bean 的 id 注入。它在给字段注入时不能独立使用,必须和@Autowire 一起使用;但是给方法参数注入时,可以独立使用。
@Autowire:一起使用;但是给方法参数注入时,可以独立使用。

  • 属性:value:指定 bean 的 id。

@Resource:直接按照 Bean 的 id 注入。它也只能注入其他 bean 类型。

  • 属性:name:指定 bean 的 id。

@Value:注入基本数据类型和 String 类型数据的。

  • 属性:value:用于指定值。

@PostConstruct:用于指定初始化方法。
@PreDestroy:用于指定销毁方法。
@Configuration:用于指定当前类是一个 spring 配置类。

  • 属性: value:用于指定配置类的字节码

@Bean:该注解只能写在方法上,表明使用此方法创建一个对象,并且放入 spring 容器。

  • 属性: 给当前@Bean 注解方法创建的对象指定一个名称(即 bean 的 id)。
  • 参数校验
    • @Validated:加在请求体上。
    • @NotBlank:只用在String上,表示传进来的值不能为null,而且调用trim()后,长度必须大于0。
    • @NotNull:不能为null,但可以为empty(分配了内存空间,但值为空)。
    • @NotEmpty:不能为null,而且长度必须大于0。

IOC

基本概念

  • 什么是Spring IOC 容器?
    控制反转即IoC (Inversion of Control),它把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转移,从程序代码本身转移到了外部容器。Spring IOC 负责创建对象,管理对象(通过依赖注入(DI),装配对象,配置对象,并且管理这些对象的整个生命周期。
  • 依赖查找
    依赖查找(Dependency Lookup,简称 DL),它是控制反转设计原则的一种实现方式。它的大体思路是:容器中的受控对象通过容器的 API 来查找自己所依赖的资源和协作对象。这种方式虽然降低了对象间的依赖,但是同时也使用到了容器的 API,造成了我们无法在容器外使用和测试对象。依赖查找是一种更加传统的 IOC 实现方式。
  • 依赖注入
    依赖注入的基本原则是:应用组件不应该负责查找资源或者其他依赖的协作对象。配置对象的工作应该由IoC容器负责,“查找资源”的逻辑应该从应用组件的代码中抽取出来,交给IoC容器负责。容器全权负责组件的装配,它会把符合依赖关系的对象通过属性(JavaBean中的setter)或者是构造器传递给需要的对象。

依赖注入的优势:查找定位操作与应用代码完全无关;不依赖于容器的API,可以很容易地在任何容器以外使用应用对象;不需要特殊的接口,绝大多数对象可以做到完全不必依赖容器。

Spring支持的几种bean的作用域

Spring框架支持以下五种bean的作用域:

  • singleton : bean在每个Spring ioc 容器中只有一个实例。
  • prototype:
    prototype作用域部署的bean,每一次请求都会产生一个新的bean实例,相当与一个new的操作,对于prototype作用域的bean,有一点非常重要,那就是Spring不能对一个prototype bean的整个生命周期负责,容器在初始化、配置、装饰或者是装配完一个prototype实例后,将它交给客户端,随后就对该prototype实例不闻不问了。不管何种作用域,容器都会调用所有对象的初始化生命周期回调方法,而对prototype而言,任何配置好的析构生命周期回调方法都将不会被调用。清除prototype作用域的对象并释放任何prototype bean所持有的昂贵资源,都是客户端代码的职责。
  • request:每次http请求都会创建一个bean,该作用域仅在基于web的SpringApplicationContext情形下有效。
  • session:在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
  • global-session:在一个全局的HTTP Session中,一个bean定义对应一个。

缺省的Spring bean 的作用域是Singleton。使用 prototype 作用域需要慎重的思考,因为频繁创建和销毁 bean 会带来很大的性能开销。

Spring框架中的单例bean线程安全问题

Spring框架中的单例bean不是线程安全的。
spring 中的 bean 默认是单例模式,spring 框架并没有对单例 bean 进行多线程的封装处理。实际上大部分时候 spring bean 无状态的(比如 dao 类),所有某种程度上来说 bean 也是安全的,但如果 bean 有状态的话(比如 view model 对象),那就要开发者自己去保证线程安全了,最简单的就是改变 bean 的作用域,把“singleton”变更为“prototype”,这样请求 bean 相当于 new Bean() 了,所以就可以保证线程安全了(在类中定义静态变量除外)。

  • 有状态
    可以在不同的方法调用间保持针对各个客户端的状态,与客户端的联系必需被维持;通常开销较大。有状态会话Bean会保存客户端的状态。
    你对ENTITY BEAN的数据操作会被容器维护起来,当其他的用户要用你正在使用的ENTITY BEAN时,里面的数据会被钝化到服务器的磁盘上,例如网上的购物车。
  • 无状态
    无状态Bean不会"专门"保存客户端的状态----(需要强调“专门”是因为无状态会话Bean也会有成员变量,有成员变量就可以保存状态,但它不会专门为特定的客户端保存状态。)。
    你对ENTITY BEAN的数据操作不会被容器维护,当其他的用户要用ENTITY BEAN时,里面的数据不会被钝化到服务器的磁盘上。也就是被保存起来。

AOP

事务控制

推荐阅读