框架 —— Spring

目录

  • 什么是spring
      • spring体系结构
      • spring 依赖的jar包
  • IOC
      • BeanFactory
      • ApplicationContext
  • 依赖注入(Dependency Injection,DI)
  • Spring Bean
      • Spring Bean的配置及常用属性
      • Spring Bean的实例化
      • Spring Bean的作用域
      • Spring Bean的生命周期
      • Spring Bean的属性依赖注入
  • AOP
      • 什么是AOP
      • AOP术语
      • Spring Aop
        • 手动代理:JDK动态代理 与 CGLIB代理
        • 半自动代理:Spring 工厂Bean代理
        • 全自动代理:Spring Aop 编程
      • AspectJ
  • JdbcTemplate
  • 声明式事务


什么是spring

学习网址:
https://www.w3cschool.cn/wkspring/f8pc1hae.html
http://c.biancheng.net/view/4244.html
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(一站式) 轻量级开源框架。

spring 就是一个大工厂(容器),可以将所有对象和依赖关系的维护交给spring管理。spring 工厂用于生成 bean

轻量级概念
轻量级重量级某种程度上是以启动程序需要的资源来决定。比如,EJB启动的时候,需要消耗大量的资源,内存,CPU等,所以是重量级。而Spring则不,所以是轻量级框架。专业点说就是量级主要是看对容器的依赖性所决定的,依赖性越小,越轻量。轻量级是相对于重量级的一种对于组件的评判标准,它用来衡量组件对其环境的依赖程度。如果这个依赖越小,就越轻量;反之就越重量。

分层架构:三层架构 (一站式,每一层都提供了解决方案)
表现层(web层) struts,spring-MVC。MVC是表现层的一个设计模型。
业务层(service层) spring。
持久层(dao层) hibernate,mybatis,jdbcTemplate(spring)。

spring体系结构

Spring框架是一.个分层架构,,它包含一系列的功能要素并被分为大约20个模块。这些模块分为Core Container、Data Access /Integration、Web、AOP ( Aspect Oriented Programming)、Instrumentation 和测试部分,如下图所示:
框架 —— Spring_第1张图片
Core Container :核心容器。Spring 的核心容器是其他模块建立的基础,由 Beans 模块、Core 核心模块、Context 上下文模块和 Expression Language 表达式语言模块组成。

1、Beans 模块:提供了 BeanFactory,是工厂模式的经典实现,Spring 将管理对象称为 Bean。
2、Core 核心模块:提供了 Spring 框架的基本组成部分,包括 IoC 和 DI 功能。
3、Context 上下文模块:建立在核心和 Beans 模块的基础之上,它是访问定义和配置任何对象的媒介。ApplicationContext 接口是上下文模块的焦点。
4、Expression Language 模块:是运行时查询和操作对象图的强大的表达式语言。

框架 —— Spring_第2张图片

spring 依赖的jar包

4 + 1 : 4个核心jar包(beans、core、context、expression) + 1个依赖jar包(commons-loggins…jar)。http://c.biancheng.net/view/4242.html

下载解压 Spring 框架压缩包。
框架 —— Spring_第3张图片
Spring框架文件的目录介绍

名称 作用
docs 包含 Spring 的 API 文档和开发规范
libs 包含开发需要的 JAR 包和源码包
schema 包含开发所需要的 schema 文件,在这些文件中定义了 Spring 相关配置文件的约束

在 libs 目录中,包含了 Spring 框架提供的所有 JAR 文件,其中有四个 JAR 文件是 Spring 框架的基础包,分别对应 Spring 容器的四个模块。
Spring 核心 JAR 包介绍

名称 作用
spring-core-3.2.13.RELEASE.jar 包含 Spring 框架基本的核心工具类,Spring 其他组件都要用到这个包中的类,是其他组件的基本核心。
spring-beans-3.2.13.RELEASE.jar 所有应用都要用到的,它包含访问配置文件、创建和管理 bean 以及进行 Inversion of Control(IoC)或者 Dependency Injection(DI)操作相关的所有类。
spring-context-3.2.13.RELEASE.jar Spring 提供在基础 IoC 功能上的扩展服务,此外还提供许多企业级服务的支持,如邮件服务、任务调度、JNDI 定位、EJB 集成、远程访问、缓存以及各种视图层框架的封装等。
spring-expression-3.2.13.RELEASE.jar 定义了 Spring 的表达式语言。需要注意的是,在使用 Spring 开发时,除了 Spring 自带的 JAR 包以外,还需要一个第三方 JAR 包 commons.logging 处理日志信息。

下载 依赖 jar 包(commons-loggins…jar)


IOC

IoC 是指在程序开发中,实例的创建不再由调用者管理(即不是调用者使用new来创建),而是由 Spring 容器创建。Spring 容器会负责控制程序之间的关系,而不是由程序代码直接控制,因此,控制权由程序代码转移到了 Spring 容器中,控制权发生了反转,这就是 Spring 的 IoC 思想。

Spring 容器是 Spring 框架的核心。容器将创建对象,把它们连接在一起,配置它们,并管理他们的整个生命周期从创建到销毁。IOC 容器具有依赖注入功能的容器,它可以创建对象,IOC 容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。通常new一个实例,控制权由程序员控制,而"控制反转"是指new实例工作不由程序员来做而是交给Spring容器来做。

在配置文件中装配或者使用注解装配将对象的创建(IoC),引用对象(属性注入)等操作交给spring容器统一操作连接。通过 xml 或注解告诉 spring 可以去创建哪些对象以及哪些属性可以注入到对象中。

Spring 提供了两种 IoC 容器,分别为 BeanFactory 和 ApplicationContext。(核心API)

BeanFactory

BeanFactory 是基础类型的 IoC 容器,它由org.springframework.beans.facytory.BeanFactory 接口定义,并提供了完整的 IoC 服务支持。简单来说,BeanFactory 就是一个管理 Bean 的工厂,它主要负责初始化各种 Bean,并调用它们的生命周期方法。(采取延迟加载,第一次调用getBean方法时才会初始化Bean)。

BeanFactory 接口有多个实现类,最常见的是 org.springframework.beans.factory.xml.XmlBeanFactory,它是根据 XML 配置文件中的定义装配 Bean 的。

创建 BeanFactory 实例时,需要提供 Spring 所管理容器的详细配置信息,这些信息通常采用 XML 文件形式管理。其加载配置信息的代码具体如下所示:

BeanFactory beanFactory = new XmlBeanFactory(new FileSystemResource("D://applicationContext.xml"));

ApplicationContext

ApplicationContext 是 BeanFactory 的子接口,也被称为应用上下文。该接口的全路径为 org.springframework.context.ApplicationContext,它不仅提供了 BeanFactory 的所有功能,还添加了对 i18n(国际化)、资源访问、事件传播等方面的良好支持。(当配置文件被加载,就进行对象实例化。)

ApplicationContext 接口有两个常用的实现类,具体如下。

1)ClassPathXmlApplicationContext
该类从类路径 ClassPath 中寻找指定的 XML 配置文件,找到并装载完成 ApplicationContext 的实例化工作,具体如下所示。

ApplicationContext applicationContext = new ClassPathXmlApplicationContext(String configLocation);

在上述代码中,configLocation 参数用于指定 Spring 配置文件的名称和位置,如 applicationContext.xml。

2)FileSystemXmlApplicationContext
该类从指定的文件系统路径中寻找指定的 XML 配置文件,找到并装载完成 ApplicationContext 的实例化工作,具体如下所示。

ApplicationContext applicationContext = new FileSystemXmlApplicationContext(String configLocation);

它与 ClassPathXmlApplicationContext 的区别是:在读取 Spring 的配置文件时,FileSystemXmlApplicationContext 不再从类路径中读取配置文件,而是通过参数指定配置文件的位置,它可以获取类路径之外的资源,如“F:/workspaces/applicationContext.xml”。

二者的主要区别在于,如果 Bean 的某一个属性没有注入,则使用 BeanFacotry 加载后,在第一次调用 getBean() 方法时会抛出异常,而 ApplicationContext 则在初始化时自检,这样有利于检查所依赖的属性是否注入。ApplicationContext 容器包括 BeanFactory 容器的所有功能。

因此,在实际开发中,通常都选择使用 ApplicationContext,而只有在系统资源较少时,才考虑使用 BeanFactory。

具体使用详情及示例:
https://www.w3cschool.cn/wkspring/yqdx1mm5.htmll
http://c.biancheng.net/view/4251.html

操作顺序:定义接口 —> 实现接口的类 —> 在xml配置文件中的标签中配置实现类 —> 在调用处通过spring容器创建实现类的对象。

spring使用xsd约束,约束说明文件位置: spring framework 3.2.0RELEASEdocs\spring-framework-reference html\xsd-config .html


依赖注入(Dependency Injection,DI)

DI Dependancy Injection (DI),依赖注入。一个类的对象使用或依赖其他类的对象。
is a:是一个,继承关系
has a:有一个,成员变量,依赖关系

class B {
	private  A  a ;  // B 类依赖A类
}

依赖:一个对象A需要使用另一个对象B。A依赖B
注入:通过stter方法等进行另一个对象实例设置。即一个对象获得另一个对象的方式称为注入。

class BookServiceImpl{
    //之前开发:接口 = 实现类  (service和dao耦合)
    //private BookDao bookDao = new BookDaoImpl();
    //spring之后 (解耦:service实现类使用dao接口,不知道具体的实现类)
    private BookDao bookDao;
    setter方法
}
模拟spring执行过程
创建service实例:BookService bookService = new BookServiceImpl() //  -->IoC    
创建dao实例:BookDao bookDao = new BookDaoImple()     // -->IoC  
将dao设置给service:bookService.setBookDao(bookDao);    // -->DI   

Spring框架的核心功能之一就是通过依赖注入的方式来管理Bean之间的依赖关系。

当某个 Java 实例需要另一个 Java 实例时,传统的方法是由调用者创建被调用者的实例(例如,使用 new 关键字获得被调用者实例),而使用 Spring 框架后,被调用者的实例不再由调用者创建,而是由 Spring 容器创建,这称为控制反转。(对象)

Spring 容器在创建被调用者的实例时,会自动将调用者需要的被调用者对象实例注入给调用者,这样,调用者通过 Spring 容器获得被调用者实例,这称为依赖注入。(属性)

依赖注入主要有两种实现方式,分别是设值注入(Setter Injection)和构造方法注入(Constructor Injection)。

1)设值注入(setter 注入)
指 IoC 容器使用 setter 方法注入被依赖的实例。通过调用无参构造器或无参 static 工厂方法实例化 bean 后,调用该 bean 的 setter 方法,即可实现基于 setter 的 DI。
在xml配置文件中调用者的标签体中用标签中设置(注入)调用者依赖的属性。

2)构造方法注入(Constructor Injection)
指 IoC 容器使用构造方法注入被依赖的实例。基于构造器的 DI 通过调用带参数的构造方法实现,每个参数代表一个依赖。
在xml配置文件中调用者的标签体中用中设置(注入)调用者依赖的属性。


Spring Bean

Spring Bean的配置及常用属性

作为 Spring 核心机制的依赖注入,改变了传统的编程习惯,对组件的实例化不再由应用程序完成,转而交由 Spring 容器完成,在需要时注入应用程序中,从而对组件之间依赖关系进行了解耦。这一切都离不开 Spring 配置文件中使用的 元素。

Spring 容器可以被看作一个大工厂,而 Spring 容器中的 Bean 就相当于该工厂的产品。如果希望这个大工厂能够生产和管理 Bean,这时则需要告诉容器需要哪些 Bean,以及需要以何种方式将这些 Bean 装配到一起。

Spring 配置文件支持两种不同的格式,分别是 XML 文件格式和 Properties 文件格式。

通常情况下,Spring 会以 XML 文件格式作为 Spring 的配置文件,这种配置方式通过 XML 文件注册并管理 Bean 之间的依赖关系。

XML 格式配置文件的根元素是 ,该元素包含了多个 子元素,每一个 子元素定义了一个 Bean,并描述了该 Bean 如何被装配到 Spring 容器中。

元素的常用属性

属性名称 描述
id 是一个 Bean 的唯一标识符,Spring 容器对 Bean 的配置和管理都通过该属性完成
name Spring 容器同样可以通过此属性对容器中的 Bean 进行配置和管理,name 属性中可以为 Bean 指定多个名称,每个名称之间用逗号或分号隔开
class 该属性指定了 Bean 的具体实现类,它必须是一个完整的类名,使用类的全限定名
scope 用于设定 Bean 实例的作用域,其属性值有 singleton(单例)、prototype(原型)、request、session 和 global Session。其默认值是 singleton
constructor-arg 元素的子元素,可以使用此元素传入构造参数进行实例化。该元素的 index 属性指定构造参数的序号(从 0 开始),type 属性指定构造参数的类型
property 元素的子元素,用于调用 Bean 实例中的 Set 方法完成属性赋值,从而完成依赖注入。该元素的 name 属性指定 Bean 实例中的相应属性名
ref 等元素的子元索,该元素中的 bean 属性用于指定对 Bean 工厂中某个 Bean 实例的引用
value 等元素的子元素,用于直接指定一个常量值
list 用于封装 List 或数组类型的依赖注入
set 用于封装 Set 类型属性的依赖注入
map 用于封装 Map 类型属性的依赖注入
entry 元素的子元素,用于设置一个键值对。其 key 属性指定字符串类型的键值,ref 或 value 子元素指定其值

Spring Bean的实例化

在 Spring 中,实例化 Bean 有三种方式,分别是构造器实例化静态工厂方式实例化实例工厂方式实例化

构造器实例化:构造器实例化是指 Spring 容器通过 Bean 对应的类中默认的构造函数实例化 Bean。直接在xml配置文件中使用配置实现类来实例化。

<bean id="person1" class="com.mengma.instance.constructor.Person1" />

Spring 容器会通过实现类 Person1 中默认的无参构造函数对 Bean 进行实例化。

静态工厂方式实例化:此种方式需要提供一个静态工厂方法创建 Bean 的实例。(静态工厂中的所有方法都是静态方法,调用静态方法创建其他对象。)

<bean id="person2"  class="com.mengma.instance.static_factory.MyBeanFactory"  factory-method="createBean" />

定义了一个 id 为 person2 的 Bean,其中 class 属性指定了其对应的工厂实现类为 MyBeanFactory,而 factory-method 属性用于告诉 Spring 容器调用工厂类中的 createBean() 方法获取 Bean 的实例。

实例工厂方式实例化:在这种方式中,工厂类不再使用静态方法创建 Bean 的实例,而是直接在成员方法中创建 Bean 的实例。同时,在配置文件中,需要实例化的 Bean 也不是通过 class 属性直接指向其实例化的类,而是通过 factory-bean 属性配置一个实例工厂,然后使用 factory-method 属性确定使用工厂中的哪个方法。(先有工厂的实例对象,通过调用改对象的实例方法创建其他对象。)


<bean id="myBeanFactory" class="com.mengma.instance.factory.MyBeanFactory" />

<bean id="person3" factory-bean="myBeanFactory" factory-method="createBean" />

首先配置了一个实例工厂 Bean,然后配置了需要实例化的 Bean。在 id 为 person3 的 Bean 中,使用 factory-bean 属性指定一个实例工厂,该属性值就是实例工厂的 id 属性值。使用 factory-method 属性确定使用工厂中的 createBean() 方法。

Spring Bean的作用域

Spring 容器在初始化一个 Bean 的实例时,同时会指定该实例的作用域。Spring3 为 Bean 定义了五种作用域,具体如下。
1)singleton
单例模式,使用 singleton 定义的 Bean 在 Spring 容器中只有一个实例,这也是 Bean 默认的作用域。
2)prototype
原型模式,每次通过 Spring 容器获取 prototype 定义的 Bean 时,容器都将创建一个新的 Bean 实例。
3)request
在一次 HTTP 请求中,容器会返回该 Bean 的同一个实例。而对不同的 HTTP 请求,会返回不同的实例,该作用域仅在当前 HTTP Request 内有效。
4)session
在一次 HTTP Session 中,容器会返回该 Bean 的同一个实例。而对不同的 HTTP 请求,会返回不同的实例,该作用域仅在当前 HTTP Session 内有效。
5)global Session
在一个全局的 HTTP Session 中,容器会返回该 Bean 的同一个实例。该作用域仅在使用 portlet context 时有效。

在上述五种作用域中,singleton 和 prototype 是最常用的两种。

<bean id="person" class="com.mengma.scope.Person" scope="singleton"/>

Spring Bean的生命周期

Spring 容器可以管理 singleton 作用域 Bean 的生命周期,在此作用域下,Spring 能够精确地知道该 Bean 何时被创建,何时初始化完成,以及何时被销毁。

而对于 prototype 作用域的 Bean,Spring 只负责创建,当容器创建了 Bean 的实例后,Bean 的实例就交给客户端代码管理,Spring 容器将不再跟踪其生命周期。每次客户端请求 prototype 作用域的 Bean 时,Spring 容器都会创建一个新的实例,并且不会管那些被配置成 prototype 作用域的 Bean 的生命周期

为了定义安装和拆卸一个 bean,我们只要声明带有 init-method 和/或 destroy-method 参数的 。init-method 属性指定一个方法,在实例化 bean 时,立即调用该方法。同样,destroy-method 指定一个方法,只有从容器中移除 bean 之后,才能调用该方法。

Bean的生命周期可以表达为:Bean的定义——Bean的初始化——Bean的使用——Bean的销毁。

<bean id="helloWorld" 
    class="com.tutorialspoint.HelloWorld"
    init-method="init" destroy-method="destroy">
    <property name="message" value="Hello World!"/>
bean>

Spring Bean的属性依赖注入

Bean 的装配可以理解为依赖关系注入,Bean 的装配方式也就是 Bean 的依赖注入方式。Spring 容器支持多种形式的 Bean 的装配方式,如基于 XML 的 Bean 装配、基于 Annotation 的 Bean 装配和自动装配等。

1、依赖注入方式:手动装配和自动装配,

2、手动装配:一般进行配置信息都采用手动。

3、基于xml装配:设值注入(Setter Injection)和构造注入(Constructor Injection)。

在 Spring 实例化 Bean 的过程中,首先会调用默认的构造方法实例化 Bean 对象,然后通过 Java 的反射机制调用 setXxx() 方法进行属性的注入。因此,设值注入要求一个 Bean 的对应类必须满足以下两点要求。

  • 必须提供一个默认的无参构造方法。
  • 必须为需要注入的属性提供对应的 setter 方法。

使用设值注入时,在 Spring 配置文件中,需要使用 元素的子元素 元素为每个属性注入值。而使用构造注入时,在配置文件中,主要使用 标签定义构造方法的参数,可以使用其 value 属性(或子元素)设置该参数的值。


<bean id="person1" class="com.mengma.assembly.Person">
    <property name="name" value="zhangsan" />
    <property name="age" value="20" />
bean>

<bean id="person2" class="com.mengma.assembly.Person">
	
    <constructor-arg index="0" value="lisi" />
    <constructor-arg index="1" value="21" />
bean>

向一个对象传递一个引用,需要使用标签的 ref 属性;直接传递值,使用如上所示的 value 属性。

使用 p 命名空间(p-namespace)实现 XML 配置:如果你有许多的设值函数方法,那么在 XML 配置文件中使用 p-namespace 是非常方便的,相当于简化替换标签。使用时注意需要配置xml。加入:

xmlns:p="http://www.springframework.org/schema/p"

使用 p-namespace 注入:

<bean id="john-classic" class="com.example.Person"
   p:name="John Doe"
   p:age="18"/>
bean>

SpEL——属性注入的格式优化:所有值格式统一使用 value = “”。(简化替换标签。)

<property name="arg" value="#{表达式}">

常量:#{10}、 #{3.14}、 #{2e5} 、#('itcast’}
引用Bean:#{beanld}
引用Bean属性:#{beanld,propertyName}
引用Bean方法:#{beanld.methodName().method2()}
引用静态方法:通过 T() 调用一个类的静态方法。T(java.lang.Math).PI
运算符支持:#{3 lt 4 == 4ge 3}
正则表达式支持:#{user.name matches ‘[a-z]{6,}’}
集合支持:#{likes[3]}

4、集合注入
Spring 提供了四种类型的集合的配置元素,如下所示:

元素 描述
它有助于连线,如注入一列值,允许重复。
它有助于连线一组值,但不能重复。
它可以用来注入名称-值对的集合,其中名称和值可以是任何类型。
它可以用来注入名称-值对的集合,其中名称和值都是字符串类型。
<property name="addressList">
      <list>
         <value>INDIAvalue>
         <value>Pakistanvalue>
         <value>USAvalue>
         <value>USAvalue>
      list>
   property>

   
   <property name="addressSet">
      <set>
         <value>INDIAvalue>
         <value>Pakistanvalue>
         <value>USAvalue>
         <value>USAvalue>
     set>
   property>

   
   <property name="addressMap">
      <map>
         <entry key="1" value="INDIA"/>
         <entry key="2" value="Pakistan"/>
         <entry key="3" value="USA"/>
         <entry key="4" value="USA"/>
      map>
   property>

   
   <property name="addressProp">
      <props>
         <prop key="one">INDIAprop>
         <prop key="two">Pakistanprop>
         <prop key="three">USAprop>
         <prop key="four">USAprop>
      props>
   property>

5、基于注解装配
从 JDK 5.0 以后,提供了 Annotation(注解)功能,Spring 也提供了对 Annotation 技术的全面支持。从 Spring 2.5 开始就可以使用注解来配置依赖注入。而不是采用 XML 来描述一个 bean 连线,可以使用相关类,方法或字段声明的注解,将 bean 配置移动到组件类本身。
注解:就是一个类,使用@注解名称。
开发中:使用注解取代xml配置文件。。

注解连线在默认情况下在 Spring 容器中不打开。因此,在可以使用基于注解的连线之前,需要在 Spring 配置文件中配置以便可以使用它。

xmlns:context="http://www.springframework.org/schema/context"
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd

常用的注解如下等等:
1)@Component取代
    @Component(“id”)取代
    可以使用此注解描述 Spring 中的 Bean,但它是一个泛化的概念,仅仅表示一个组件(Bean),并且可以作用在任何层次。使用时只需将该注解标注在相应类上即可。

2)web开发,提供3个@Component注解衍生注解(功能一样)。
@Repository
    用于将数据访问层(DAO层)的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
@Service
    通常作用在业务层(Service 层),用于将业务层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。
@Controller
    通常作用在控制层(Web层)(如 Struts2 的 Action),用于将控制层的类标识为 Spring 中的 Bean,其功能与 @Component 相同。

6、自动装配:struts 和spring整合可以自动装配。
byType:按类型装配。
byName:按名称装配。
constructor:构造装配。
auto:不确定装配。

后处理bean:BeanPostProcessor 接口,,对容器中所有的bean都生效。

(注解与 xml 混合使用:将所有的 bean 都配置在 xml 中,将所有的依赖都使用注解配置。)


AOP

什么是AOP

AOP 为 Aspect Oriented Programming 的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

AOP实现原理

  • aop 底层将采用代理机制进行实现
    • 接口 + 实现类的形式:spring 采用 jdk 的动态代理 Proxy
    • 只有实现类:spring 采用 cglib 字节码增强
  • AOP 采取横向抽取机制,取代了传统纵向继承体系的重复性代码,其应用主要体现在事务管理、日志管理、权限控制、异常处理等方面。
  • 目前最流行的 AOP 框架有两个,分别为 Spring AOP 和 AspectJ。
    • Spring AOP 使用纯 Java 实现,不需要专门的编译过程和类加载器,在运行期间通过代理方式向目标类植入增强的代码。
    • AspectJ 是一个基于 Java 语言的 AOP 框架,从 Spring 2.0 开始,Spring AOP 引入了对 AspectJ 的支持。AspectJ 扩展了 Java 语言,提供了一个专门的编译器,在编译时提供横向代码的植入。

AOP术语

为了更好地理解 AOP,就需要对 AOP 的相关术语有一些了解,这些专业术语主要包含 Joinpoint、Pointcut、Advice、Target、Weaving、Proxy 和 Aspect,含义如下表所示。

名称 说明
Target(目标类) 指代理的目标对象,被代理的目标类
Joinpoint(连接点) 指那些被拦截到的(即可能被拦截的方法,是目标类中的所有方法),在 Spring 中,可以被动态代理拦截目标类的方法。
Pointcut(切入点) 指要对哪些 Joinpoint 进行拦截,即被拦截的连接(已经被增强的连接点)。
Advice(通知 / 增强) 指拦截到 Joinpoint 之后要做的事情,即对切入点增强的内容(代码)
Weaving(植入 / 织入) 指把增强代码应用到目标上,生成代理对象的过程
Proxy(代理) 指生成的代理对象,即代理类
Aspect(切面) 切入点和通知的结合。

Spring Aop

手动代理:JDK动态代理 与 CGLIB代理

代理对象需要手动创建,手动获取。

JDK动态代理:

JDK 动态代理是通过 JDK 中的 java.lang.reflect.Proxy 类实现的。(使用前提:必须有接口)

1、目标类:接口+实现类
2、切面类:用于存通知的类。
3、工厂类:编写工厂生成代理。

CGLIB代理:

JDK 动态代理使用起来非常简单,但是它也有一定的局限性,这是因为 JDK 动态代理必须要实现一个或多个接口,如果不希望实现接口,则可以使用 CGLIB 代理。

CGLIB(Code Generation Library)是一个高性能开源的代码生成包,它被许多 AOP 框架所使用,其底层是通过使用一个小而快的字节码处理框架 ASM(Java 字节码操控框架)转换字节码并生成新的类。

导入jar包:

  • 核心jar包:cglib-2.2.jar。
  • 依赖jar包:asm-3.3jar。
    但是 spring-core-3.2.2.RELEASE.jar 已经整合以上两个jar包。
    框架 —— Spring_第4张图片
半自动代理:Spring 工厂Bean代理

让 spring 创建代理对象,从 spring 容器中手动获取代理对象。

导入jar包:

  • spring 的 4+1 jar 包
  • AOP 的 JAR 包:
    • spring-aop-3.2.13.RELEASE.jar:是 Spring 为 AOP 提供的实现,在 Spring 的包中已经提供。
    • com.springsource.org.aopalliance-1.0.0.jar:是 AOP 提供的规范,可以在 Spring 的官网网址 https://repo.spring.io/webapp/#/search/quick/ 中进行搜索并下载。

通知(Advice)其实就是对目标切入点进行增强的内容,Spring AOP 为通知(Advice)提供了 org.aopalliance.aop.Advice 接口。Spring 通知按照在目标类方法的连接点位置,可以分为以下五种类型,

Spring 通知的 5 种类型<\center>
名称 说明
org.springframework.aop.MethodBeforeAdvice(前置通知) 在方法之前自动执行的通知称为前置通知,可以应用于权限管理等功能。
org.springframework.aop.AfterReturningAdvice(后置通知) 在方法之后自动执行的通知称为后置通知,可以应用于关闭流、上传文件、删除临时文件等功能。
org.aopalliance.intercept.MethodInterceptor(环绕通知) 在方法前后自动执行的通知称为环绕通知,可以应用于日志、事务管理等功能。
org.springframework.aop.ThrowsAdvice(异常通知) 在方法抛出异常时自动执行的通知称为异常通知,可以应用于处理异常记录日志等功能。
org.springframework.aop.IntroductionInterceptor(引介通知) 在目标类中添加一些新的方法和属性,可以应用于修改旧版本程序(增强类)。
全自动代理:Spring Aop 编程

Spring 创建一个 AOP 代理的基本方法是使用 org.springframework.aop.framework.ProxyFactoryBean,这个类对应的切入点和通知提供了完整的控制能力,并可以生成指定的内容。

表 2 ProxyFactoryBean 的常用属性<\center>
属性名称 描述
target 代理的目标对象
proxyInterfaces 代理要实现的接口
proxyTargetClass 是否对类代理而不是接口,设置为 true 时,使用 CGLIB 代理
interceptorNames 需要植入目标的 Advice
singleton 返回的代理是否为单例,默认为 true(返回单实例)
optimize 当设置为 true 时,强制使用 CGLIB

AspectJ

http://c.biancheng.net/view/4275.html
AspectJ 是一个基于 Java 语言的 AOP 框架,它扩展了 Java 语言。Spring 2.0 以后,新增了对 AspectJ 方式的支持,新版本的 Spring 框架,建议使用 AspectJ 方式开发 AOP。

使用 AspectJ 开发 AOP 通常有两种方式:

  • 基于 XML 的声明式。
  • 基于 Annotation 的声明式。

通过 Spring 配置文件的方式定义切面、切入点及声明通知,而所有的切面和通知都必须定义在 元素中。

导入 JAR 包:
使用 AspectJ 除了需要导入 Spring AOP 的 JAR 包以外,还需要导入与 AspectJ 相关的 JAR 包,具体如下。

  • spring-aspects-3.2.13.RELEASE.jar:Spring 为 AspectJ 提供的实现,在 Spring 的包中已经提供。
  • com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar:是 AspectJ 提供的规范,可以在官方网址 https://repo.spring.io/webapp/#/search/quick/ 中搜索并下载。

基于xml声明式配置 xml 文件:


<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="  
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd  
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

xmlns:aop=“http://www.springframework.org/schema/aop”
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd

基于注解声明式配置xml文件:


<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context.xsd">

xmlns:context=“http://www.springframework.org/schema/context”
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd


JdbcTemplate

Spring 框架针对数据库开发中的应用提供了 JDBCTemplate 类,该类是 Spring 对 JDBC 支持的核心,它提供了所有对数据库操作功能的支持。

Spring 框架提供的JDBC支持主要由四个包组成,分别是 core(核心包)、object(对象包)、dataSource(数据源包)和 support(支持包),org.springframework.jdbc.core.JdbcTemplate 类就包含在核心包中。作为 Spring JDBC 的核心,JdbcTemplate 类中包含了所有数据库操作的基本方法。

声明式事务

一个数据库事务是一个被视为单一的工作单元的操作序列。这些操作执行要么完全成功,要么完全不成功。事务管理是一个重要组成部分,RDBMS 面向企业应用程序,以确保数据完整性和一致性。事务的概念可以描述为具有以下四个关键属性说成是 ACID

  • 原子性:事务应该当作一个单独单元的操作,这意味着整个序列操作要么是成功,要么是失败的。
  • 一致性:这表示数据库的引用完整性的一致性,表中唯一的主键等。
  • 隔离性:可能同时处理很多有相同的数据集的事务,每个事务应该与其他事务隔离,以防止数据损坏。
  • 持久性:一个事务一旦完成全部操作后,这个事务的结果必须是永久性的,不能因系统故障而从数据库中删除。

Spring 支持两种类型的事务管理:

  • 编程式事务管理 :这意味着你在编程的帮助下有管理事务。这给了你极大的灵活性,但却很难维护。
  • 声明式事务管理 :这意味着你从业务代码中分离事务管理。你仅仅使用注释或 XML 配置来管理事务。

声明式事务管理比编程式事务管理更可取,尽管它不如编程式事务管理灵活,但它允许你通过代码控制事务。但作为一种横切关注点,声明式事务管理可以使用 AOP 方法进行模块化。Spring 支持使用 Spring AOP 框架的声明式事务管理。

Spring 事务管理的五大属性:隔离级别、传播行为、是否只读、事务超时、回滚规则。

导入jar包:
在 Spring 解压包的 libs 目录中,包含一个名称为 spring-tx-3.2.13.RELEASE.jar 的文件,该文件是 Spring 提供的用于事务管理的 JAR 包,其中包括事务管理的三个核心接口:PlatformTransactionManager、TransactionDefinition 和 TransactionStatus。
框架 —— Spring_第5张图片
1、PlatformTransactionManager
PlatformTransactionManager 接口是 Spring 提供的平台事务管理器,用于管理事务。该接口中提供了三个事务操作方法,具体如下。

  • TransactionStatus getTransaction(TransactionDefinition definition):用于获取事务状态信息。
  • void commit(TransactionStatus status):用于提交事务。
  • void rollback(TransactionStatus status):用于回滚事务。

2、TransactionDefinition
TransactionDefinition 接口是事务定义(描述)的对象,它提供了事务相关信息获取的方法,其中包括五个操作,具体如下。

  • String getName():获取事务对象名称。
  • int getIsolationLevel():获取事务的隔离级别。
  • int getPropagationBehavior():获取事务的传播行为。
  • int getTimeout():获取事务的超时时间。
  • boolean isReadOnly():获取事务是否只读。

3、TransactionStatus
TransactionStatus 接口是事务的状态,它描述了某一时间点上事务的状态信息。

你可能感兴趣的:(Java,spring)