Spring知识点小结

目录

一、Spring简介

二、Spring框架的优点有哪些?

三、IoC容器的特点

四、什么是 DI ?

五、Spring框架中的 BeanFactory 接口和 ApplicationContext 接口有什么区别?

六、Spring中Bean的实例化的三种方式

七、对 Spring 容器中 Bean 标签的理解

八、Spring 框架中属性注入有哪几种注入方式?

九、bean 的生命周期

十、bean 的作用域

十一、用注解将对象注册到Spring容器当中,有几种注解方式?它们有什么区别吗?

十二、Spring AOP 基本概念

十三、Spring AOP术语

十四、Spring 实现 AOP 的原理


一、Spring简介

Spring 是一个开源框架,是为了解决企业应用程序开发复杂性而创建的。主要有三大特点:容器、IoC(控制反转)、AOP(面向切面编程)。同时,Spring 也是一个“一站式”框架,即 Spring 在 JavaEE 的三层架构[表现层(Web层)、业务逻辑层(Service层)、数据访问层(DAO层)]中,每一层均提供了不同的解决技术。

二、Spring框架的优点有哪些?

Spring框架主要有以下三个优点:

  1. 容器:Spring 框架是一个容器,可以管理项目中的所有对象;
  2. IoC(Inversion of Control,控制反转):Spring 将创建对象的方式反转了,从程序员自己创建对象反转给了程序;
  3. AOP(Aspect Oriented Programming,面相切面编程):简而言之就是将纵向重复代码横向提取出来。Spring 框架应用了面相切面的思想,主要体现在为容器中管理的对象生成动态代理对象。 

三、IoC容器的特点

  • 无需主动 new 对象,而是描述对象应该如何被创建即可,IoC 容器帮你创建,即被动实例化;
  • 不需要主动装配对象之间的依赖关系,而是描述需要哪个服务(组件),IoC 容器会帮你装配(即负责将它们关联在一起),被动接受装配;
  • 迪米特原则(最少知识原则):不知道依赖的具体实现,只知道需要提供某类服务的对象(面向抽象编程),松散耦合,一个对象应当对其他对象有尽可能少的了解,不和陌生人(实现)说话。
  • IoC是一种让服务消费者不直接依赖于服务提供者的组件设计方式,是一种减少类与类之间依赖的设计原则。

四、什么是 DI ?

DI(Dependency Injection,依赖注入):需要有 IoC 环境,在 Spring 创建 Bean 对象时,动态的将依赖对象注入到 Bean 对象中去。依赖注入最大的好处就是解耦合。

五、Spring框架中的 BeanFactory 接口和 ApplicationContext 接口有什么区别?

  • BeanFactory 接口是 Spring 框架的顶层接口,是最原始的接口,通过new (BeanFactory 的实现类)来启动 Spring 容器时,并不会创建 Spring 容器里面的对象,只有在每次通过 getBean() 获得对象时才会创建。
  • ApplicationContext 接口是用来替代 BeanFactory 接口的,通过 new (ApplicationContext 接口的实现类)ClassPathXmlApplicationContext 来启动 Spring 容器时,就会创建容器中配置的所有对象。

六、Spring中Bean的实例化的三种方式

       一、构造方法实例化:



       上面就是通过构造方法的方式实例化Bean,默认这个类是需要一个无参的构造方法。其中id和name都是Bean配置的属性,用来标识一个Bean。

         二、静态工厂方法实例化:

         静态工厂方法顾名思义:就是通过一个类的静态(工厂)方法来创建Bean

public class ClientService {
    private static ClientService clientService = new ClientService();

    private ClientService() {}

    public static ClientService createInstance() {
        return clientService;
    }
}

         从上面的静态方法中我们就可以在对象返回之前来设置其属性,这样就完成了对象的创建。
         三、实例工厂方法实例化

         实例工厂方法和静态工厂方法比较相似,区别在于实例工厂方法是通过已经在容器中的Bean通过其方法实例化一个新的  Bean。





public class DefaultServiceLocator {
    private static ClientService clientService = new ClientServiceImpl();
    
    public ClientService createClientServiceInstance() {
        return clientService;
    }
}

当然一个实例中可以有多个实例工厂方法的,我们可以在XML中以同样的方式配置更多的Bean。

七、对 Spring 容器中 Bean 标签的理解

Bean 标签用来描述 Spring 容器管理的对象。

假如有一个 User 对象,需要交给 Spring 容器来管理,这样就需要在 Spring 容器的主配置文件中通过 Bean 标签来描述该对象。Bean 标签常见的属性有以下几个:

name 属性:给被管理的对象起个名称,获得对象时要根据该名称来获得;

class 属性:被管理对象的完整类名;

scope 属性:scope 属性常见的有两个属性值,singleton 和 portotype,这两个属性值用来指定创建对象时是单例还是多例,默认为 singleton(单例),但是在整合 struts2 时,ActionBean 必须配置为多例。

八、Spring 框架中属性注入有哪几种注入方式?

Spring 中属性注入的方式包括 set 方法注入、构造函数注入、p名称空间注入、spel 注入,除此之外,还包括复杂方法注入,如数组、List、Map、Properties 等属性的注入。

九、bean 的生命周期

Bean 的生命周期包括 bean 的定义、bean 的初始化、bean 的调用和 bean 的销毁。

在配置文件中通过 来完成,通过配置 init-method 属性来完成 bean 的初始化,通过得到 bean 的实例对象来完成 bean 的调用,通过配置 destory-method 属性来完成 bean 的销毁。

十、bean 的作用域

bean 有5种作用域,分别是 singleton(单例,默认)、prototype(默认)、request、session、globalSession。

singleton:当一个 bean 的作用域为 singleton, 那么Spring IoC容器中只会存在一个共享的bean实例,并且所有对 bean 的请求,只要 id 与该 bean 定义相匹配,则只会返回 bean 的同一实例。Spring 默认选择该作用域。

prototype:prototype 作用域的 bean 会导致在每次对该 bean 请求(将其注入到另一个 bean 中,或者以程序的方式调用容器的 getBean() 方法)时都会创建一个新的 bean 实例。对所有有状态的 bean 应该使用 prototype 作用域,而对无状态的 bean 则应该使用 singleton 作用域。

request:在一次 HTTP 请求中,一个 bean 定义对应一个实例;即每次 HTTP 请求将会有各自的 bean 实例, 它们依据某个bean 定义创建而成。该作用域仅在基于 web 的 Spring ApplicationContext 情形下有效(限定 Spring MVC 中使用)。

session:在一个 HTTP Session 中,一个 bean 定义对应一个实例。该作用域仅在基于 web 的 Spring ApplicationContext 情形下有效(限定 Spring MVC 中使用)。

global session:在一个全局的 HTTP Session 中,一个 bean 定义对应一个实例。典型情况下,仅在使用 portlet context 的时候有效。该作用域仅在基于 web 的 Spring ApplicationContext 情形下有效。

十一、用注解将对象注册到Spring容器当中,有几种注解方式?它们有什么区别吗?

4种。分别是:@Component()、@Service()、@Controller()、@Respository()。

Spring 框架最早出现的只有 @Component() 注解,但如果所有的对象都使用同一个注解,很难区分对象究竟属于哪一层架构。基于此,Spring又推出了 @Service()、@Controller()、@Respository() 三种注解,用于区分对象属于哪一层架构。但4种注解方式从功能上来说没有任何区别。

十二、Spring AOP 基本概念

AOP是 Aspect Oriented Programming 的简称,中文翻译为“面向切面编程”。可以说是 OOP(Object-Oriented Programming,面向对象编程)的补充和完善。OOP 引入封装、继承和多态等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能,日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理也是如此。这种散布在各处的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。

Spring知识点小结_第1张图片

而AOP技术则恰恰相反,它利用一种称为“横切”的技术,解剖开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为“Aspect”,即方面。

所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。AOP代表的是一个横向的关系,如果说“对象”是一个空心的圆柱体,其中封装的是对象的属性和行为;那么面向方面编程的方法,就仿佛一把利刃,将这些空心圆柱体剖开,以获得其内部的消息。而剖开的切面,也就是所谓的“方面”了。然后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹。

使用“横切”技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,它们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理。AOP的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。

AOP的核心思想就是“将应用程序中的商业逻辑同对其提供支持的通用服务进行分离”。
Spring知识点小结_第2张图片

 实现AOP的技术,主要分为两大类:

  • 一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;
  • 二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。

十三、Spring AOP术语

和大多数技术一样,AOP已经形成了自己的术语。描述切面的常用术语有通知(advice),切点(pointcut)和连接点(joinpoint)。下图展示了这些概念是如何关联在一起的:

Spring知识点小结_第3张图片

1、通知(Advice)

切面也是有目标的——它必须完成的工作。在AOP术语中,切面的工作被称之为通知。

通知:定义了切面是什么,何时使用,其描述了切面要完成的工作,还解决了何时执行这个工作的问题。

Spring 切面可以应用 5 种类型的通知:

  • 前置通知(Before):在目标方法被调用之前调用通知功能;
  • 后置通知(After):在目标方法完成之后调用通知,此时不会关心方法的输出是什么;
  • 返回通知(After-returning):在目标方法成功执行之后调用通知;
  • 异常通知(After-throwing):在目标抛出异常后通知调用;
  • 环绕通知(Around):通知包裹了被通知方法,在被通知的方法通知之前和调用之后执行自定义的行为。

2、连接点(Join Point)

连接点:是在应用执行过程中能够插入切面的一个点,这个点可以是方法调用时,抛出异常时,甚至修改字段时。切面代码可以利用这些点插入到应用的正常流程之中,并添加新的行为。

3、切点(Pointcut)

切点:是缩小切面所通知的连接点的范围。如果说通知定义了切面是什么和何时的话,那么切点就定义了何处。

切点的定义会匹配通知所要织入的一个或者多个连接点。我们通常会使用明确的类和方法名称,或者利用正则表达式定义所匹配的类和方法名来指定这些切点。

4、切面(Aspect)

切面:是通知和切点的结合。通知和切点共同定义了切面的全部内容————它是什么,在何时,在何处完成其功能。

5、引入(Introduction)

引入:允许我们向现有的类添加新方法和属性。

例如:我们创建一个 Auditable 通知类,该类记录了对象最后一次修改时的状态,这很简单,只需要一个方法 setLastModified(Date) ,和一个实例变量来保存这个状态。然后,这个新方法和实例变量就可以被引入到现有的类中,从而可以在无需修改这些现有的类的情况下,让他们具有新方法的行为和状态。

6、织入(Weaving)
织入是把切面应用到目标对象并创建新的代理对象的过程。切面在指定的连接点被织入到目标对象中。

在目标对象的生命周期里有多个点可以进行织入:

  • 编译期:切面在目标类编译时被织入。这种方式需要特殊的编译器。AspectJ的织入编译器就是以这种方式织入切面的。
  • 类加载器:切面在目标类加载到JVM时被织入。这种方式需要特殊的类加载器(ClassLoader),它可以在目标类被引入应用之前增强该目标类的字节码。AspectJ5的加载时织入(load-time weaving. LTW)就支持以这种方式织入切面。
  • 运行期:切面在应用运行的某一时刻被织入。一般情况下,在织入切面时,AOP容器会为目标对象动态创建一个代理对象。SpringAOP就是以这种方式织入切面的。

7、目标对象(Target Object)

被一个或者多个切面所通知(Advice)的对象,也把它叫做被通知的对象(Advised)。既然SpringAOP是通过运行时代理实现的,那么这个对象永远是一个被代理(Proxied)对象。

十四、Spring 实现 AOP 的原理

JDK的动态代理和 cglib 代理。

JDK动态代理有缺陷,就是被代理对象必须实现接口才能产生代理对象,如果没有接口,就不能使用动态代理技术。我们用 spring 容器来实现动态代理,假如要管理的对象没有实现接口,那么就不能产生代理对象了。为了让所有的对象都能产生动态代理对象,Spring又融入了第三方代理技术cglib代理。Cglib可以对任何类生成代理对象,它的原理是对目标对象进行继承代理,如果目标对象被final修饰,那么该类无法被cglib代理。

那么Spring到底使用的是JDK代理,还是cglib代理呢?

答:混合使用。如果被代理对象实现了接口,就优先使用JDK代理,如果没有实现接口,就用用 cglib 代理。

Spring AOP的实现方式有哪些?

  1. 经典的基于代理的AOP:使用 Java 代码实现,编写 Advice、PointCut,然后提供给 Advisor 使用。开启自动代理后,即可在 applicationContext 中获得增强后的 bean。
  2. @AspectJ 注解驱动的切面:基于注解的开发(推荐使用),在项目中需要开启 AOP 自动代理
  3. XML Schema 方式:需要实现相应的增强接口,如BeforeAdvice、AfterAdvice等。

 

 

你可能感兴趣的:(Spring)