您的位置:首页 > 编程语言 > Java开发

Spring入门笔记简要

2022-03-10 10:06 459 查看
总览:https://www.processon.com/view/link/605b14ab5653bb2225e6b0c5

一、Spring

1、概述

1、spring框架简介

​ 为简化企业级开发而生,有效的降低代码的耦合度,极大的方便项目的后期维护、升级和扩展。

2、优点

​ 轻量、AOP支持、支持对各种框架的集成

3、体系结构

1、数据访问

2、Web开发

3、AOP

4、集成消息等

5、核心容器 IOC

2、IOC控制反转

​ ioc(Inversion of Control)是一种设计思想,把对象的创建、赋值、管理工作都交给代码之外的容器实现,也就是对象的创建是有其他外部资源完成。

**控制:**创建对象,对象赋值,对象之间的关系管理

**反转:**把原来开发人员管理、创建对象的权限转交给代码之外的容器实现,由容器代替开发人员管理对象,创建、赋值等

正转:由开发人员在代码中,使用new构造方法创建对象,开发人员主动管理对象‘;

容器:是一个服务器软件(Tomcat),一个框架(spring)等

目的:

减少对代码的改动,也能实现不同的功能,实现解耦合

所以:java中创建对象的方式:

1、new

2、反射,class的newInstance()方法,constructor的newInstance()方法

3、反序列化

4、克隆

5、ioc

ioc的技术实现:

​ DI 是 ioc 的技术实现

​ DI (Dependency Injection)依赖注入:只需要在程序中提供使用的对象名称就可以,至于对象如何在容器中创建、赋值、查找都由容器内部实现。

spring是使用的 DI 实现了 ioc 的功能,spring底层创建对象,使用的是反射机制。

2.1 由spring创建对象

实现步骤:
  1. 创建maven项目

  2. 加入maven依赖

    ​ spring依赖、junit依赖

  3. 创建类(接口和他的实现类)

    ​ 和没有使用框架一样,就是普通类

  4. 创建spring需要使用的配置文件

    ​ 声明类的信息,由spring创建和管理

仅限于初学的写法:

2.2 DI(依赖注入)的实现方式:

1、基于xml配置文件:在Spring配置文件中,使用标签和属性完成

2、基于注解的实现:使用spring中的注解,完成属性赋值

2.2.1 基于xml配置文件

​ 适合经常需要修改

DI的语法分类:

1、 注入(set设值, 注入就是赋值):spring调用类的set方法,在set方法中实现属性的赋值(最常用)

2、构造注入,spring调用类的有参构造方法,创建对象,在构造方法中完成赋值

set注入:

  1. 简单类型的set注入:

property设值时name属性必须在相应的类中有set方法,且有set方法没有相应的变量也不会报错

​ 2.引用类型的set注入:

​ 引用类型的自动注入:

​ 1、byName:java类中引用类型的属性名和spring容器中(配置文件)的id名称一样,且数据类型一致,这样的容器中的bean,spring能够赋值给引用类型

<bean id="xx" class="yy" autowire="byName"></bean>

让Student类中所有的引用类型都按照byName规则完成赋值

​ 2、byType(按类型注入):java类中引用类型的数据类型和spring容器中(配置文件)的class属性是同源关系的,这样的bean能够赋值给引用类型

​ 同源:1、java类中引用类型的数据类型和bean中的class值一样

​ 2、java类中引用类型的数据类型和bean中的class值父子类关系的

​ 3、java类中引用类型的数据类型和bean中的class值接口和实现类关系的

​ 注:只能有一个符合条件的,多个会报错

​ class是Student类中引用的School的值:

构造注入

name属性实现构造注入

index属性实现

可以省略index=“”,但是必须按照参数的定义顺序书写

多配置文件优势:

  1. 每个文件的大小比一个文件小很多,效率高

  2. 避免多人竞争带来的冲突

    按文件的分配方式:

  3. 按功能模块,一个模块一个配置文件

  4. 按类的功能,数据库相关的配置一个配置文件,做事务的功能一个配置文件,做service功能的一个配置文件

2.2.2 基于注解的实现

​ 快捷,方便,适合不经常修改的

实现步骤:

  1. 加入maven依赖spring-context(间接加入了spring-aop依赖)

  2. 创建类,在类中加入spring 注解@Component(value=“xxx”),省略value=也可以(常用),如果只写@Component则会默认value=首字母小写的类名

    还有
    @Repository(用在持久层):放在dao的实现类,表示创建dao对象,dao对象是能访问数据库的
    @Service(用在业务层):service对象是做业务处理,可以有事务等功能的
    @Controller(用在控制器上):放在控制器(处理器)类的上面,创建控制器对象的,控制器对象能够接受用户提交的参数,显示请求的处理结果
    以上三个适用语法和@Component一样,都能创建对象,但是他们三个还有额外的功能

    引用类型-@Autowired

    引用类型@Resource

  3. 在spring配置文件中,加入一个组件扫描器的标签,说明注解在项目中的位置

    需要指定多个包时:

3、AOP面向切面编程

3.1 动态代理

​ 动态代理能创建对象,在原有类代码不变的情况下,实现功能的增加,功能增强。

3.1.1 JDK 动态代理

​ 要求目标对象必须实现接口,java语言通过java.lang.reflect包提供三个类支持代理模式Proxy,Method和InvcationHandler,要求目标类和方法不能是final的,因为final不能被继承,不能被重写啊

实现步骤:

  1. 创建目标类,SomeserviceImpl目标类,给它的doSome,dother增加输出时间,事务。

  2. 创建InvocationHandler接口的实现类,在这个类实现给目标方法增加功能。

  3. 使用jdk中类Proxy ,创建代理对象。实现创建对象的能力。

作用:

  1. 在目标类源码不改变的情况下,增加功能

  2. 减少代码的重复

  3. 专注业务代码逻辑

  4. 解耦合,让业务与日志扥,事务非业务功能分离

3.1.2 CGLB动态代理(了解)

​ CDLIB(Code Generation Library)是一个开源项目,原理是生成目标类的子类,子类是代理对象。

3.2 AOP简介

AOP(Aspect Orient Programming) 面向切面编程,底层的实现就是采用动态代理模式实现的,采用了JDK的动态代理和CGLIB的动态代理。

Aspect:切面,给目标类增加的功能

​ 特点:一般都是非业务方法,独立使用的

如何理解AOP:

​ 以切面为核心,围绕切面来开发程序:

​ 1)分析项目功能时找到切面

​ 2)合理安排执行时间,(在目标方法前还是后)

​ 3)合理的安排切面执行的位置, 在哪个类,哪个方法增加增强功能

3.3 AOP编程术语

  1. AOP:切面,表示增强的功能,就是一堆代码,完成某一个功能,非业务功能

    ​ 常见的切面功能有日志,事务,统计信息,参数检查,权限验证

  2. JoinPoint:连接点,连接业务方法和切面的位置,就是某类中的业务方法

  3. PointCut:切入点,指多个连接方法的集合,多个方法

  4. 目标对象:给哪个类的方法这个价功能,这个类就是目标对象

  5. Advice:通知,表示切面功能 执行的时间,方法之前还是之后

切面三个关键要素:

  1. 切面的功能代码,切面干什么
  2. 切面的执行位置,使用PointCut表示切面执行的位置
  3. 切面的执行时间,使用Advice表示时间,在目标方法之前还是之后

3.4 AOP的实现

​ AOP是一个规范,是动态的一个规范化,一个标准

​ aop的技术实现框架:

  1. spring:spring内部实现了aop的规范,能做aop的工作

    ​ spring在处理事务时使用aop

    ​ 在项目开发中很少使用spring的aop实现,因为spring的aop比较笨重

  2. Aspect:一个开源的专门做aop的框架,spring框架中集成了aspectj框架,通过spring就能使用aspectj的功能

    aspectj框架实现aop的两种方式:

    使用xml的配置文件:配置全局事务
  3. 使用注解,在项目中要做aop功能,一般使用注解

3.4 AspectJ框架的使用

  1. 切面的执行时间,这个执行时间在规范中叫做Advice(通知,增强)

    在aspect框架中使用注解表示,也可以使用xml配置文件中的标签

    <!-- 5个常用注解
    @Before
    @AfterReturning
    @Around
    @After
    @AfterThrowing
    -->
  2. 表示切面执行的位置,使用的是切入表达式

    execution(访问权限 方法返回值 方法参数 异常类型)

    在其中可以使用以下符号:
    *	:0至多个任意字符
    ..	: 用在方法参数中,表示任意多个参数;用在包名后,表示当前包及其子包
    +	:用在类名后,表示当前类及其子类;用在接口名后,表示当前接口及其实现类
    指定切入点为:任意公共方法
    execution(public * *(..))
    指定切入点为:任意一个以set开始的方法
    execution(* set*(..))
    指定切入点为:com.mhz.service包中的任意类中的任意方法,不包含子包
    execution(* com.mhz.service.*.*(..))
    指定切入点为:com.mhz.service或者子包包中的任意类中的任意方法
    execution(* com.mhz.service..*.*(..))
    指定切入点为:所有service包下的任意类的任意方法
    execution(* *..service.*.*(..))
使用aspectJ实现aop的基本步骤:
  1. 新建maven项目

  2. 加入依赖

    spring依赖
  3. aspectj依赖
  4. junit单元测试(可有可无)
  • 创建目标类:接口和他的实现类

    要做的是给类中的方法增加功能

  • 创建切面类:普通类

      在类上加入注解@Aspect

    1. 定义方法,方法就是切面要执行的功能代码

      ​ 在方法上面加入aspectj中的注解,例如@Before,

      ​ 有需要指定切入点表达式execution()

  • 创建spring配置文件:声明对象,把对象交给容器统一管理

    ​ 声明对象可以使用xml配置文件或者注解

      声明目标对象

    1. 声明切面类对象

    2. 声明aspectj框架中的自动代理生成器标签。

      ​ 自动代理生成器:用来完成代理对象的自动创建功能的。

    <!--把对象交给spring容器,由spring容器统―创建,管理对象-->
    <! --声明目标对象-->
    <bean id="someservice" class="com.bjpowernode.bao1.SomeserviceImpl"/>
    <! --声明切面类对象-->
    <bean id="myAspect" class="com.bjpowernode.ba01.MyAspect”/>
    <!--
    声明自动代理生成器:使用aspectj框架内部的功能,创建目标对象的代理对象。
    创建代理对象是在内存中实现的,修改目标对象的内存中的结构。创建为代理对象所以目标对象就是被修改后的代理对象
    aspectj-autoproxy:会把spring容器内的所有目标对象,一次性都生成代理对象
    -->
    <aop: aspectj-autoproxy />
  • 创建测试类,从spring容器中获取目标对象(代理对象)

    ​ 通过代理对象实现aop

  • 六个注解:

    1、@Before:

    前置通知注解
    属性: value,是切入点表达式,表示切面的功能执行的位置。
    位置:	在方法的上面
    特点:
    1.在目标方法之前先执行的
    2.不会改变目标方法的执行结果
    3.不会影响目标方法的执行。

    /*
    * 指定通知方法中的参数:JoinPoint
    * JoinPoint:业务方法,要加入切面功能的业务方法
    * 作用是:可以在通知方法中获取方法执行时的信息,例如方法名称,方法的实参。
    * 如果你的切面  功能中需要用到方法的信息,就加入JoinPoint.
    * 这个JoinPoint参数的值是由框架赋予,必须是第一个位置的参数
    */
    
    @Before(value = "execution(void *..SomeServiceImpl.doSome(String, Integer))")
    public void myBefore(JoinPoint jp){
    //获取方法的完整定义
    system.out.println("方法的签名(定义)="+jp.getsignature());
    system.out.println("方法的名称="+jp.getsignature().getName());//获取方法的实参
    object args []= jp.getArgs();
    for (object arg:args){
    system.out.println("参数="+arg);
    }
    }

    2、@AfterReturning:

    后置通知定义方法,方法是实现切面功能的。
    方法的定义要求:
    1.公共方法 public
    2.方法没有返回值
    3.方法名称自定义
    4.方法有参数的,推荐是object,参数名自定义
    
    @AfterReturning:后置通知
    属性:
    1.value切入点表达式
    2.returning自定义的变量,表示目标方法的返回值的。自定义变量名必须和通知方法的形参名一样。
    位置:在方法定义的上面
    特点:
    1. 在目标方法之后执行的。
    2. 能够获取到目标方法的返回值,可以根据这个返回值做不同的处理功能
    3. 可以修改这个返回值
    @AfterReturning(value="execution(* *..SomeServiceImpl.doOther(..))",returning="res")
    // 此处returning的res名称=Object的res名称就行
    public void myAfterReturing(object res){
    // object res:是目标方法执行后的返回值,根据返回值做你的切面的功能处理
    // 思考:如果是对类对象res的更改会不会影响在程序执行后得到的输出结果?
    system.out.println("后置通知:在目标方法之后执行的,获取的返回值是:"+res);
    if(res.equals("abcd"))
    {
    //做―些功能
    }
    e1se
    {
    //做其它功能
    }
    
    }

    3、@Around

    环绕通知
    方法的定义格式:
    1.public
    2.必须有一个返回值,推荐使用object
    3.方法名称自定义
    4.方法有参数,固定的参数ProceedingjoinPoint
    @Around:环绕通知
    属性:value切入点表达式位宣:在方法的定义什么
    特点:
    1.它是功能最强的通知
    2.在目标方法的前和后都能增强功能。
    3.控制目标方法是否被调用执行
    4.修改原来的目标方法的执行结果。影响最后的调用结果
    
    等同于jdk动态代理的,InvocationHandler接口
    参数:ProceedingJoinPoint 等同于Method
    作用:执行目标方法
    返回值:就是目标方法的执行结果,可以被修改
    @Around(value = "execution(* *..SomeService1mpl.doFirst(..))")
    public object myAround(ProceedingJoinPoint pjp) throws Throwable {
    // 获取第一个参数值
    Object[] args = pjp.getArgs();
    String name = "";
    if(args != null && args.length > 1){
    Object arg = args[0];
    name = (String)arg;
    }
    //实现环绕通知
    object result = null;
    system.out.println("环绕通知:在目标方法之前,输出时间:"+ new Date());
    //1.目标方法调用
    if("xxx".equals(name)){
    // 控制是否执行目标方法
    result = pjp.proceed(); //method.invoke(); object result = doFirst();
    }
    system.out.println("环绕通知:在目标方法之后,提交事务");
    //2.在目标方法的前或者后加入功能
    //返回目标方法的执行结果
    return result;
    }

    4、 @AfterThrowing

    异常通知:
    1、public
    2、没有返回值
    3、方法,名称自定义
    4、方法有一个Exception,如果还有就是JoinPoint
    @AfterThrowing:异常通知
    属性:1、value
    2、throwing自定义变量,表示目标方法抛出的异常对象,变量名和方法的参数名一样
    特点:1、在目标方法抛出异常时执行
    2、可以做异常的监控程序,如果有异常,可以发邮件,短信通知等
    执行时:
    没有异常就走正常逻辑,有异常就走定义的@AfterThrowing注解的方法
    try{
    SomeServiceImpl.doSecond(..);
    }
    catch(Exception ex){
    myAfterThrowing(ex);
    }
    @AfterThrowing(value = "execution(* *..SomeServiceImpl.doSecond(..))",throwing = "ex")
    public void myAfterThrowing(Exception ex){
    system.out.println("异常通知:方法发生异常时,执行: "+ex.getMessage());//发送邮件,短信,通知开发人员
    }

    5、@ After

    最终通知
    方法的定义格式
    1.public
    2.没有返回值
    3.方法名称自定义
    4.方法没有参数,如果还有是JoinPoint
    @After:最终通知
    属性:value 切入点表达式
    位置:方法上面
    特点:
    1、总是执行
    2、目标方法后执行,即使抛出了异常
    类似于:
    try/catch中的finally代码块
    @After(value = "execution(* *..SomeserviceImpl.doThird(..))")
    public loidmyAfter(){
    //一般做资源清除工作的。
    systemyout.println("执行最终通知,总是会被执行的代码");
    }

    6、 @PointCut

    定义管理切入点
    如果项目中很多个切入点表达式是重复的,,使用@PointCut
    属性:value 切入点表达式
    位置:方法上面
    特点:
    当使用@Pointcut定义在一个方法的上面,此时这个方法的名称就是切入点表达式的别名。其它的通知中,value属性就可以使用这个方法名称,代替切入点表达式了
    @Pointcut(value = "execution(* *..SomeserviceImpl.doThird(..))”)
    private void mypt(){
    //无需代码,
    }
    // 然后:
    @Before(value="mypt()")
    public void myBefore(){
    
    }

    4、Spring事务

    4.1 Spring的事务管理

    1. 什么是事务?

      ​ 指的是一组sql语句的集合,集合中有多个sql语句,增删查改,希望这些sql语句斗殴成功或者都失败,这些sql 的执行是一致的,作为一个整体执行。

    2. 什么时候用到事务?

      ​ 当操作涉及多个表或者多个sql语句的增删改,需要保证这些sql语句都成功才能完成功能,或者都失败,保证操作是符合要求的。

      ​ 在java代码中写程序,控制事务,需要写在service类的业务方法上,因为业务方法汇调用多个dao方法,执行多个sql语句

    3. jdbc、Mybatis访问数据库处理事务?

      //jdbc
      Connection conn;
      conn.commit();
      conn.rollback();
      //mybatis
      SqlSession.commit();
      SqlSession.rollback();
    4. 问3中处理事务的方式是不同的,所以有哪些不足:

      不同的数据库访问技术,处理事务的对象、方法不同,需要掌握了解不同数据库访问技术使用事务的原理

    5. 掌握多种数据库中事务的处理逻辑,提交、回滚等

      多种数据库访问技术,有不同的事务处理的机制,对象、方法

  • 解决不足

    ​ spring提供一种统一处理事务的统一模型,能使用统一步骤,方式完成多种不同数据库访问技术的事务处理。

    ​ 使用spring的事务处理机制,可以完成mybatis、hibernate等访问数据库的事务处理。

  • 处理事务,需要怎么做,做什么 spring处理事务的模型,使用的步骤都是固定的。把事务使用的信息提供给spring就可以了

      事务内部提交,回滚事务,使用的事务管理器对象,代替你完成commit,rollback

      事务管理器是一个接口和他的众多实现类。

      接口:PlatformTransactionManager ,定义了事务重要方法commit , rollback

      实现类: spring把每一种数据库访问技术对应的事务处理类都创建好了。 mybatis访问数据库---spring创建好的是DatasourceTransactionManagerhibernate

      ​ 访问数据库----spring创建的是HibernateTransactionManager 怎么使用:你需要告诉spring 你用是那种数据库的访问技术,怎么告诉spring呢? 声明数据库访问技术对于的事务管理器实现类,在spring的配置文件中使用声明就可以了例如,你要使用mybatis访问数据库,你应该在xml配置文件中

      <bean id="xxx" class=" . ..DataSourceTransactionManager">
    1. 业务方法需要什么样的事务,说明需要事务的类型。

      ​ 说明方法需要的事务:

      ​ 1)事务的隔离级别:

      ​ DEFAULT:采用 DB默认的事务隔离级别。Mysql的默认为REPEATABLE_READ;Oracle默认为 READ_COMITTED.READ

      ​ UNCOMMITTED:读未提交。未解决任何并发问题。 ​ READ_COMMITTED:读已提交。解决脏读,存在不可重复读与幻读。

      ​ REPEATABLE_READ:可重复读。解决脏读、不可重复读,存在幻读SERIALIZABLE:串行化。不存在并发问题。

      ​ 2)事务的超时时间:表示一个方法的最长执行时间,如果方法执行超过了时间,事务就回滚

      ​ 3)事务的传播行为:控制业务方法是不是有事务的,是什么样的事务

      ​ 7个传播行为,表示业务方法调用时,事务在方法之间是如何使用的

      <!--!!!
      PROPAGATION REQUIRED
      PROPAGATION_REQUIRES_NEW
      PROPAGATIONsUPPORTS
      -->
      PROPAGATIONMANDATORY
      PROPAGATION_NESTED
      PROPAGATION_NEVER
      PROPAGATIONNOT_SUPPORTED
    2. 事务提交事务,回滚事务的时机 1)当你的业务方法,执行成功,没有异常抛出,当方法执行完毕,spring在方法执行后提交事务。事务管理器commit

      2)当你的业务方法抛出运行时异常或ERROR,spring执行回滚,调用事务管理器的rollback 运行时异常的定义: RuntimeException 和他的子类都是运行时异常,例如Ntul1PointException , MunberFormatzxcept. 3)当你的业务方法抛出非运行时异常,主要是受查异常时,提交事务 受查异常:在你写代码中,必须处理的异常。例如IOException,SQLException

    总结Spring事务:

    1. 管理事务的是 事务管理 和他的实现类
    2. spring的事务是一个统一模型 指定使用的事务管理器的实现类,使用
    3. 指定哪些类,哪些方法需要加入事务的功能
    4. 指定方法需要的隔离级别,传播行为,超时

    4.2 Spring的事务传播机制

    **Required **解义:如果上下文中已经存在事务,就加入到事务当中

    上下文有事务 上下文没有事务
    Required 加入到事务当中 新建事务
    Supports 加入到事务当中 非事务方式运行
    Mandatory 必须要有事务 抛出异常
    Requires_New 新建事务 新建事务
    Not_Supported 事务挂起,方法结束后恢复事务
    Never 抛出runtime异常,强制停止执行
    Nested 嵌套事务执行 新建事务

    二、SpringMVC

    1.1 MVC在B/S下的应用

    mvc是一个设计模式

    1.2 springmvc框架

    过程

    1、发起请求到前端控制器

    2、前端控制器请求HandlerMapping查找Handler

    ​ 根据xml配置、注解进行查找

    3、处理器映射器HandlerMapping向前端控制器返回Handler

    4、前端控制器用处理器适配器去执行Handler

    5、理器适配器执行Handler

    6、Handler执行完成给适配器返回ModelAndView

    7、处理器向前端控制器返回ModelAndView

    ​ ModelAndView是springmvc框架的一个底层对象,包括model 和 view

    8、前端控制器请求视图解析器去进行视图解析

    ​ 根据逻辑视图名解析程真正的视图jsp

    9、视图解析器向前端控制器返回View

    10、前端控制器进行视图渲染

    ​ 视图渲染将模型数据(在ModelAndView中)填充到request域

    11、前端控制器向用户返回响应结果

    组件:

    1、前端控制器DispatcherServlet,(不需要程序员开发)

    ​ 接收请求,响应结果,相当于转发器,中央处理器

    ​ 减少其他组件之间的耦合度

    2、处理器映射器HandlerMapping,(不需要程序员开发)

    ​ 根据请求的url查找Handler

    3、处理器适配器HandlerAdapter(不需要程序员开发)

    ​ 按照特定规则(HandlerAdapter要求的规则)去执行Handler

    ​ 编写Handler时按照HandlerAdapter的要求去做才能正确执行Handler

    4、处理器Handler,(需要程序员开发)

    5、视图解析器View Resolver

    ​ 视图解析,根据逻辑视图域名解析成真正的视图View

    6、视图View,(需要程序员开发jsp)

    ​ 是一个接口,实现类支持不同的View类型(jsp、freemarker、pdf...)

    2、 json数据交互

    2.1、使用json交互的原因:

    ​ json数据格式在接口调用中、html页面中常用,json格式简单,解析比较方便

    2.2、springmvc进行json交互

    springmvc中使用jackson的jar包进行json转换

    客户端请求key / value串
    请求的是json串
    contenttype=application/json
    请求的是key / value
    contenttype=
    @RequestBody将json串转成java对象 不需要@RequestBody将json串转成java对象
    @ResponseBody将java对象转成json输出 @ResponseBody将java对象转成json输出
    最后都输出json数据,为了在前端页面方便对请求结果进行解析

    1、请求json、输出json,要求请求的是json串,所以在前端页面中需要将请求的内容转成json,不太方便

    2、请求key / value ,输出json,比较常用

    3、Restful支持

    restful是一种开发理念,是对http的一个诠释,即表现层状态的转化

    对url进行规范,写restful格式的url,就是简洁

    非rest的url:http://.../finditems.action?id=001

    rest的url风格:http://.../items/001

  • 内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: