Spring学习之路

1.W3school:https://www.w3cschool.cn/wkspring/8kei1icc.html

1 Spring概述

2 Spring IoC 容器

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

2.1 Spring BeanFactory 容器

2.2 Spring ApplicationContext 容器

2.3Spring Bean 定义

Spring Bean 作用域

singleton、prototype、request、session和global session

<!-- A bean definition with singleton scope -->
<bean id="..." class="..." scope="singleton">
    <!-- collaborators and configuration for this bean go here -->
</bean>

Spring Bean 生命周期

当一个 bean 被实例化时,它可能需要执行一些初始化使它转换成可用状态。同样,当 bean 不再需要,并且从容器中移除时,可能需要做一些清除工作。
为了定义安装和拆卸一个 bean,我们只要声明带有 init-method 和/或 destroy-method 参数的 。init-method 属性指定一个方法,在实例化 bean 时,立即调用该方法。同样,destroy-method 指定一个方法,只有从容器中移除 bean 之后,才能调用该方法。

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

Spring Bean 后置处理器

Bean 后置处理器允许在调用初始化方法前后对 Bean 进行额外的处理。

BeanPostProcessor 接口定义回调方法,你可以实现该方法来提供自己的实例化逻辑,依赖解析逻辑等。你也可以在 Spring 容器通过插入一个或多个 BeanPostProcessor 的实现来完成实例化,配置和初始化一个bean之后实现一些自定义逻辑回调方法。

你可以配置多个 BeanPostProcessor 接口,通过设置 BeanPostProcessor 实现的 Ordered 接口提供的 order 属性来控制这些 BeanPostProcessor 接口的执行顺序。

BeanPostProcessor 可以对 bean(或对象)实例进行操作,这意味着 Spring IoC 容器实例化一个 bean 实例,然后 BeanPostProcessor 接口进行它们的工作。

ApplicationContext 会自动检测由 BeanPostProcessor 接口的实现定义的 bean,注册这些 bean 为后置处理器,然后通过在容器中创建 bean,在适当的时候调用它。

Spring Bean 定义继承

使用 parent 属性

3 Spring 依赖注入

Spring框架的核心功能之一就是通过依赖注入的方式来管理Bean之间的依赖关系。
依赖注入
每个基于应用程序的 java 都有几个对象,这些对象一起工作来呈现出终端用户所看到的工作的应用程序。当编写一个复杂的 Java 应用程序时,应用程序类应该尽可能独立于其他 Java 类来增加这些类重用的可能性,并且在做单元测试时,测试独立于其他类的独立性。依赖注入(或有时称为布线)有助于把这些类粘合在一起,同时保持他们独立。

3.1 Spring 基于构造函数的依赖注入

当容器调用带有一组参数的类构造函数时,基于构造函数的 DI 就完成了,其中每个参数代表一个对其他类的依赖。

 <constructor-arg value="Generic Text Editor"/>

如果你想要向一个对象传递一个引用,你需要使用 标签的 ref 属性,如果你想要直接传递值,那么你应该使用如上所示的 value 属性。

3.2 Spring 基于设值函数的依赖注入

当容器调用一个无参的构造函数或一个无参的静态 factory 方法来初始化你的 bean 后,通过容器在你的 bean 上调用设值函数,基于设值函数的 DI 就完成了。
定义在基于构造函数注入和基于设值函数注入中的 Beans.xml 文件的区别。唯一的区别就是在基于构造函数注入中,我们使用的是〈bean〉标签中的〈constructor-arg〉元素,而在基于设值函数的注入中,我们使用的是〈bean〉标签中的〈property〉元素。

第二个你需要注意的点是,如果你要把一个引用传递给一个对象,那么你需要使用 标签的 ref 属性,而如果你要直接传递一个值,那么你应该使用 value 属性。

3.3 Spring 注入内部 Beans

Spring 注入集合

4 Spring Beans 自动装配

Spring 容器可以在不使用和 元素的情况下自动装配相互协作的 bean 之间的关系,这有助于减少编写一个大的基于 Spring 的应用程序的 XML 配置的数量。

你不能自动装配所谓的简单类型包括基本类型,字符串和类。

Spring 自动装配 byName

这种模式由属性名称指定自动装配。Spring 容器看作 beans,在 XML 配置文件中 beans 的 auto-wire 属性设置为 byName。然后,它尝试将它的属性与配置文件中定义为相同名称的 beans 进行匹配和连接。如果找到匹配项,它将注入这些 beans,否则,它将抛出异常。
例如,在配置文件中,如果一个 bean 定义设置为自动装配 byName,并且它包含 ** SpellChecker 类型的spellChecker 属性(即,它有一个 setSpellChecker(…) 方法),那么 Spring 就会查找定义名为 SpellChecker 的 bean**,并且用它来设置这个属性。你仍然可以使用 <property> 标签连接其余的属性。下面的例子将说明这个概念。

Spring 自动装配 byType

这种模式由属性类型指定自动装配。Spring 容器看作 beans,在 XML 配置文件中 beans 的 autowire 属性设置为 byType。然后,如果它的 type 恰好与配置文件中 beans 名称中的一个相匹配,它将尝试匹配和连接它的属性。如果找到匹配项,它将注入这些 beans,否则,它将抛出异常。
例如,在配置文件中,如果一个 bean 定义设置为自动装配 byType,并且它包含 SpellChecker 类型的 spellChecker 属性,那么 Spring 就会查找定义名为 SpellChecker 的 bean,并且用它来设置这个属性。你仍然可以使用 <property> 标签连接其余属性。

Spring 由构造函数自动装配

<bean id="textEditor" class="com.tutorialspoint.TextEditor" 
      autowire="constructor">
      <constructor-arg value="Generic Text Editor"/>
   </bean>

5 Spring 基于注解的配置

使用注解来配置依赖注入。而不是采用 XML 来描述一个 bean 连线,你可以使用相关类,方法或字段声明的注解,将 bean 配置移动到组件类本身。

在 XML 注入之前进行注解注入,因此后者的配置将通过两种方式的属性连线被前者重写。

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

Spring @Required 注释

@Required 注释应用于 bean 属性的 setter 方法,它表明受影响的 bean 属性在配置时必须放在 XML 配置文件中,否则容器就会抛出一个 BeanInitializationException 异常。

Spring @Autowired 注释

@Autowired 注释对在哪里和如何完成自动连接提供了更多的细微的控制。
@Autowired 注释可以在 setter 方法中被用于自动连接 bean,就像 @Autowired 注释,容器,一个属性或者任意命名的可能带有多个参数的方法。
Setter 方法中的 @Autowired
你可以在 XML 文件中的 setter 方法中使用 @Autowired 注释来除去 元素。当 Spring遇到一个在 setter 方法中使用的 @Autowired 注释,它会在方法中视图执行 byType 自动连接。
属性中的 @Autowired
你可以在属性中使用 @Autowired 注释来除去 setter 方法。当时使用 为自动连接属性传递的时候,Spring 会将这些传递过来的值或者引用自动分配给那些属性。
构造函数中的 @Autowired
你也可以在构造函数中使用 @Autowired。一个构造函数 @Autowired 说明当创建 bean 时,即使在 XML 文件中没有使用 元素配置 bean ,构造函数也会被自动连接。
@Autowired 的(required=false)选项
默认情况下,@Autowired 注释意味着依赖是必须的,它类似于 @Required 注释,然而,你可以使用 @Autowired 的 (required=false) 选项关闭默认行为。

Spring @Qualifier 注释

可能会有这样一种情况,当你创建多个具有相同类型的 bean 时,并且想要用一个属性只为它们其中的一个进行装配,在这种情况下,你可以使用 @Qualifier 注释和 @Autowired 注释通过指定哪一个真正的 bean 将会被装配来消除混乱。

Spring 基于 Java 的配置

@Configuration 和 @Bean 注解
带有 @Configuration 的注解类表示这个类可以使用 Spring IoC 容器作为 bean 定义的来源
@Bean 注解告诉 Spring,一个带有 @Bean 的注解方法将返回一个对象,该对象应该被注册为在 Spring 应用程序上下文中的 bean。
带有 @Bean 注解的方法名称作为 bean 的 ID,它创建并返回实际的 bean。你的配置类可以声明多个 @Bean。一旦定义了配置类,你就可以使用 AnnotationConfigApplicationContext 来加载并把他们提供给 Spring 容器,
@Import 注解:
@import 注解允许从另一个配置类中加载 @Bean 定义。
生命周期回调
@Bean 注解支持指定任意的初始化和销毁的回调方法,就像在 bean 元素中 Spring 的 XML 的初始化方法和销毁方法的属性:@Bean(initMethod = "init", destroyMethod = "cleanup" )

Spring 中的事件处理

Spring 的核心是 ApplicationContext,它负责管理 beans 的完整生命周期。当加载 beans 时,ApplicationContext 发布某些类型的事件。
通过 ApplicationEvent 类和 ApplicationListener 接口来提供在 ApplicationContext 中处理事件。如果一个 bean 实现 ApplicationListener,那么每次 ApplicationEvent 被发布到 ApplicationContext 上,那个 bean 会被通知。
由于 Spring 的事件处理是单线程的,所以如果一个事件被发布,直至并且除非所有的接收者得到的该消息,该进程被阻塞并且流程将不会继续。因此,如果事件处理被使用,在设计应用程序时应注意。
监听上下文事件
为了监听上下文事件,一个 bean 应该实现只有一个方法 onApplicationEvent() 的 ApplicationListener 接口。

6 Spring 框架的 AOP

Spring 框架的一个关键组件是面向方面的编程(AOP)框架。面向方面的编程需要把程序逻辑分解成不同的部分称为所谓的关注点。跨一个应用程序的多个点的功能被称为横切关注点,这些横切关注点在概念上独立于应用程序的业务逻辑。
在 OOP 中,关键单元模块度是类,而在 AOP 中单元模块度是方面。依赖注入帮助你对应用程序对象相互解耦和 AOP 可以帮助你从它们所影响的对象中对横切关注点解耦。
在这里插入图片描述
通知的类型
Spring 方面可以使用下面提到的五种通知工作:
在这里插入图片描述

Spring 中基于 AOP 的 XML架构

需要导入 spring-aop j架构
还需要在你的应用程序的 CLASSPATH 中使用以下 AspectJ 库文件。这些库文件在一个 AspectJ 装置的 ‘lib’ 目录中是可用的,否则你可以在 Internet 中下载它们。

aspectjrt.jar
aspectjweaver.jar
aspectj.jar
aopalliance.jar

在bean配置文件中,所有的Spring AOP配置都必须定义在<aop:config>元素内部。对于每个切面而言,都要创建一个<aop:aspect>元素来为具体的切面实现引用后端bean实例。
切面bean必须有一个标识符,供<aop:aspect>元素引用。
在这里插入图片描述
在这里插入图片描述

声明切入点

  1. 切入点使用<aop:pointcut>元素声明。
  2. 切入点必须定义在<aop:aspect>元素下,或者直接定义在<aop:config>元素下。
    ① 定义在<aop:aspect>元素下:只对当前切面有效
    ② 定义在<aop:config>元素下:对所有切面都有效
  3. 基于XML的AOP配置不允许在切入点表达式中用名称引用其他切入点。

声明通知

  1. 在aop名称空间中,每种通知类型都对应一个特定的XML元素。
  2. 通知元素需要使用<pointcut-ref>来引用切入点,或用<pointcut>直接嵌入切入点表达式。
  3. method属性指定切面类中通知方法的名称

声明一个 aspect
一个 aspect 是使用 元素声明的,支持的 bean 是使用 ref 属性引用的,如下所示:

<aop:config>
   <aop:aspect id="myAspect" ref="aBean">
   ...
   </aop:aspect>
</aop:config>
<bean id="aBean" class="...">
...
</bean>

这里,“aBean” 将被配置和依赖注入,就像前面的章节中你看到的其他的 Spring bean 一样。

声明一个切入点
一个切入点有助于确定使用不同建议执行的感兴趣的连接点(即方法)。在处理基于配置的 XML 架构时,切入点将会按照如下所示定义:

<aop:config>
   <aop:aspect id="myAspect" ref="aBean">
   <aop:pointcut id="businessService"
      expression="execution(* com.xyz.myapp.service.*.*(..))"/>
   ...
   </aop:aspect>
</aop:config>
<bean id="aBean" class="...">
...
</bean>

下面的示例定义了一个名为 “businessService” 的切入点,该切入点将与 com.tutorialspoint 包下的 Student 类中的 getName() 方法相匹配:

<aop:config>
   <aop:aspect id="myAspect" ref="aBean">
   <aop:pointcut id="businessService"
      expression="execution(* com.tutorialspoint.Student.getName(..))"/>
   ...
   </aop:aspect>
</aop:config>
<bean id="aBean" class="...">
...
</bean>

声明建议
你可以使用 <aop:{ADVICE NAME}> 元素在一个 中声明五个建议中的任何一个,如下所示:

<aop:config>
   <aop:aspect id="myAspect" ref="aBean">
      <aop:pointcut id="businessService"
         expression="execution(* com.xyz.myapp.service.*.*(..))"/>
      <!-- a before advice definition -->
      <aop:before pointcut-ref="businessService" 
         method="doRequiredTask"/>
      <!-- an after advice definition -->
      <aop:after pointcut-ref="businessService" 
         method="doRequiredTask"/>
      <!-- an after-returning advice definition -->
      <!--The doRequiredTask method must have parameter named retVal -->
      <aop:after-returning pointcut-ref="businessService"
         returning="retVal"
         method="doRequiredTask"/>
      <!-- an after-throwing advice definition -->
      <!--The doRequiredTask method must have parameter named ex -->
      <aop:after-throwing pointcut-ref="businessService"
         throwing="ex"
         method="doRequiredTask"/>
      <!-- an around advice definition -->
      <aop:around pointcut-ref="businessService" 
         method="doRequiredTask"/>
   ...
   </aop:aspect>
</aop:config>
<bean id="aBean" class="...">
...
</bean>

Spring 中基于 AOP 的 @AspectJ

  1. 要在Spring中声明AspectJ切面,只需要在IOC容器中将切面声明为bean实例。
  2. 当在Spring IOC容器中初始化AspectJ切面之后,Spring IOC容器就会为那些与 AspectJ切面相匹配的bean创建代理。
  3. 在AspectJ注解中,切面只是一个带有@Aspect注解的Java类,它往往要包含很多通知。
  4. 通知是标注有某种注解的简单的Java方法。
  5. AspectJ支持5种类型的通知注解:
    ① @Before:前置通知,在方法执行之前执行
    ② @After:后置通知,在方法执行之后执行
    ③ @AfterRunning:返回通知,在方法返回结果之后执行
    ④ @AfterThrowing:异常通知,在方法抛出异常之后执行
    ⑥ @Around:环绕通知,围绕着方法执行;环绕通知的方法需要返回目标方法执行之后的结果,
    切入点表达式 通过表达式的方式定位一个或多个具体的连接点。execution([权限修饰符] [返回值类型] [简单类名/全类名] [方法名]([参数列表]))
    在这里插入图片描述
    切入点
    定位连接点的方式。每个类的方法中都包含多个连接点,所以连接点是类中客观存在的事物。如果把连接点看作数据库中的记录,那么切入点就是查询条件——AOP可以通过切入点定位到特定的连接点。切点通过org.springframework.aop.Pointcut 接口进行描述,它使用类和方法作为连接点的查询条件。
    切入点表达式通常都会是从宏观上定位一组方法,和具体某个通知的注解结合起来就能够确定对应的连接点。那么就一个具体的连接点而言,我们可能会关心这个连接点的一些具体信息,例如:当前连接点所在方法的方法名、当前传入的参数值等等。这些信息都封装在JoinPoint接口的实例对象中。

重用切入点定义

  1. 在编写AspectJ切面时,可以直接在通知注解中书写切入点表达式。但同一个切点表达式可能会在多个通知中重复出现。
  2. 在AspectJ切面中,可以通过@Pointcut注解将一个切入点声明成简单的方法。切入点的方法体通常是空的,因为将切入点定义与应用程序逻辑混在一起是不合理的。
  3. 切入点方法的访问控制符同时也控制着这个切入点的可见性。如果切入点要在多个切面中共用,最好将它们集中在一个公共的类中。在这种情况下,它们必须被声明为public。在引入这个切入点时,必须将类名也包括在内。如果类没有与这个切面放在同一个包中,还必须包含包名。
  4. 其他通知可以通过方法名称引入该切入点
    在这里插入图片描述
@Aspect
public class Logging {
   /** Following is the definition for a pointcut to select
    *  all the methods available. So advice will be called
    *  for all the methods.
    */
   @Pointcut("execution(* com.tutorialspoint.*.*(..))")//这个包下所有的方法都是切入点
   private void selectAll(){}
   /** 
    * This is the method which I would like to execute
    * before a selected method execution.
    */
    //定义了切入点后,在切入点之前需要执行的方法,即切入点重用
    //否则的话括号里需要些入完整的切入点表达式
   @Before("selectAll()")
   public void beforeAdvice(){
      System.out.println("Going to setup student profile.");
   }
   /** 
    * This is the method which I would like to execute
    * after a selected method execution.
    */
   @After("selectAll()")
   public void afterAdvice(){
      System.out.println("Student profile has been setup.");
   }
   /** 
    * This is the method which I would like to execute
    * when any method returns.
    */
   @AfterReturning(pointcut = "selectAll()", returning="retVal")
   public void afterReturningAdvice(Object retVal){
      System.out.println("Returning:" + retVal.toString() );
   }
   /**
    * This is the method which I would like to execute
    * if there is an exception raised by any method.
    */
   @AfterThrowing(pointcut = "selectAll()", throwing = "ex")
   public void AfterThrowingAdvice(IllegalArgumentException ex){
      System.out.println("There has been an exception: " + ex.toString());   
   }  
}

Spring JDBC 框架

Spring JDBC 示例
Spring 中 SQL 的存储过程

Spring 事务管理

Spring 编程式事务管理
Spring 声明式事务管理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值