不要急,不要急,马上好^_^...

Spring学习之路


Spring

安装与应用

安装

直接下载https://repo.spring.io/release/org/springframework/spring/,点击我们想要下载的版本,进去之后下载第一个dist.zip

详细下载步骤:

首先我们要进入spring.io界面,然后找到spring Framework,然后点击右上角的GitHub,之后我们进入页面下滑到Access To Binaries ,那里有个查看spring文件,然后我们点击进去之后,点击小房子下面的文件,然后找到release->org->springframework->spring 点击右边会出现一个链接release/org/springframework/spring/,将这个链接追加到io后面就可以访问到下载页面

应用

我们首先创建一个简单的java类,然后引入jar包,然后加入库,然后创建对象

>package Test;

>import Java.hellow;
>import org.junit.Test;
>import org.springframework.context.ApplicationContext;
>import org.springframework.context.support.ClassPathXmlApplicationContext;

>public class hellowTest {
>@Test
>public void Hellow(){
  //加载spring配置文件
  ApplicationContext context = new ClassPathXmlApplicationContext("xml1.xml");

  //获取配置对象文件
  hellow hellow = context.getBean("hellow", hellow.class);
  System.out.println(hellow);
  hellow.Hello();

>}
>}


>package Java;

>public class hellow {
>public void Hello(){
  System.out.println("你好spring");
>}
>}

IOC

  1. IOC底层原理

    1. xml配置
    2. 工厂模式
    3. 反射

    通过这三层,来系统的降低我们的耦合度

  2. IOC接口

    1. IOC思想基于IOC容器完成的,IOC容器底层就是对象工厂
    2. spring提供IOC容器实现两种方式(两个接口)
      1. BeanFactory:IOC基本实现,是spring内部的使用接口,不提供开发人员进行使用(加载配置文件的时候不会创建对象,只有在获取对象的时候才去创建对象)
      2. ApplicationContext:BeanFactory的子接口,拥有更多更强大的功能,一般由开发人员进行使用(加载配置文件的时候就会将配置文件对象创建出来)
    3. ApplicationContext接口有实现类
      1. FileSystemXmlApplicationContext
      2. ClassPathXmlApplicationContext
IOC中基于xml依赖注入
set方法的注入
public class book{
    private String name;
    private String author;
    public void setName(String name){
        this.name=name;
    }
    public void setAuthor(String author){
        this.author=author;
    }
}
<Bean id = "book" class="Java.book">
    <properties name="name" value="123"></properties>
    <properties name="author" value="456"></properties>
</Bean>
public class test{
    //加载配置文件
    ApplicationContext context = new ClassPathXmlApplicationContext("book.xml");
    //获取配置对象
    Book book = context.getBean("book",Book.class);
}
构造方法的注入

默认的是无参构造,所以我们需要用构造器重新构造这个对象

<bean id="book" class="Java.book">
        <constructor-arg name="name" value="123"></constructor-arg>
        <constructor-arg name="author" value="456"></constructor-arg>
    </bean>
特殊字符的注入
<bean id="book" class="Java.book">
       <property name="author">
           <null></null>
       </property>
   </bean>

   <bean id="book" class="Java.book">
       <property name="author">
          <value>
              <![CDATA[<<南京>>]]]]>
          </value>
       </property>
   </bean>s
对象的注入
package dao;

public class Userimpl implements User{
    @Override
    public void add() {
        System.out.println("add...........");
    }
}
package service;

public class UserserviceImpl implements Userservice {
    private User user;
    public void setUser(User user) {
        this.user = user;
    }

    @Override
    public void update() {
        System.out.println("update...........");
        user.add();
    }
}
    <bean id="Userimpl" class="dao.Userimpl"></bean>

    <bean id="UserserviceImpl" class="service.UserserviceImpl">
        <property name="user" ref="Userimpl"></property>
    </bean>
</beans>
        //这里的name是我们在类中创建的名字
        //这里的ref是我们bean标签的id值
级联属性的设置
emp
    package Java;

public class emp {
    private String ename;
    private Dept dept;

    public void setEname(String ename) {
        this.ename = ename;
    }

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    public Dept getDept() {
        return dept;
    }

    public void sout(){
        System.out.println(ename+"  "+dept);
    }
}
Dept
    package Java;

public class Dept {
    private String dname;

    public void setDname(String dname) {
        this.dname = dname;
    }

    @Override
    public String toString() {
        return "Dept{" +
                "dname='" + dname + '\'' +
                '}';
    }
}
Test
    public class DeptTest {
    @Test
    public void Test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("xml3.xml");
        emp emp = context.getBean("emp", emp.class);
        emp.sout();
    }
 <bean id="dept" class="Java.Dept">
        <property name="dname" value="财务部"></property>
    </bean>

    <bean id="emp" class="Java.emp">
        <!--普通属性设置-->
        <property name="ename" value="123"></property>
        <!--对象属性设置-->
        <property name="dept" ref="dept"></property>
<!--        <property name="dept">-->
<!--            <bean id="dept2" class="Java.Dept">-->
<!--                <property name="dname" value="456"></property>-->
<!--            </bean>-->
<!--        </property>-->
//这里要使用dept.dname必须要求有get方法
<!--        <property name="dept.dname" ref="dept"></property>-->
    </bean>

数组、集合、map、set属性的注入
package Java;

import java.sql.Array;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class array {
    private String [] course;
    private List<String> list;
    private Map<String,String> map;
    private Set<String> set;

    public void setCourse(String[] course) {
        this.course = course;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    public void setMap(Map<String, String> map) {
        this.map = map;
    }

    public void setSet(Set<String> set) {
        this.set = set;
    }

    public void sout(){
        System.out.println(Arrays.toString(course));
        System.out.println(list);
        System.out.println(map);
        System.out.println(set);
    }
}
public class arrayTest {
    @Test
    public void Test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("xml4.xml");
        array array = context.getBean("array", array.class);
        array.sout();
    }
<bean id="array" class="Java.array">
       <property name="course">
           <array>
               <value>123</value>
               <value>456</value>
           </array>
       </property>

       <property name="list">
           <list>
               <value>list</value>
               <value>list</value>
           </list>
       </property>

       <property name="map">
           <map>
               <entry key="JAVA" value="java"></entry>
               <entry key="PHP" value="php"></entry>
           </map>
       </property>

       <property name="set">
           <set>
               <value>set</value>
               <value>abc</value>
           </set>
       </property>
   </bean>
基于XML的自动装配
<!--基于XML的自动装配注入-->
   <!--XML有两种自动装配注入的方法
       第一种:通过名称注入 ByName
       第二种:通过类型注入 ByType
   -->
   <bean id="dept" class="Java.Dept"></bean>
   <bean id="emp" class="Java.Dept" autowire="byName"></bean>
   <bean id="emp" class="Java.Dept" autowire="byType"></bean>
IOC中基于注解的注入

四种注解方式:

  • @Component(一般用于bean)
  • @Service(一般用于Service层)
  • @Controller(一般用于web层)
  • @Repository(一般用于dao层)

使用注解的方式:

​ 对象的创建:

1.首先需要引入aop的jar包

2.然后需要在xml文件中添加:

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

3.然后进行配置

<!--基于注解的配置-->
<context:component-scan base-package="service"></context:component-scan>

4.配置完之后,我们需要在相应的类上面添加@注解名称(在注解中,value值默认的是我们类名,首字母小写)

5.运行

​ 属性的注入:

  • @Autowired:根据类型进行注入
  • @Qualifier:根据名称进行注入
  • @Resource:可以类型注入,可以属性注入
  • @Value:普通注入

1.首先需要在两个类上面都添加对象创建的注解

2.然后再service中创建dao对象,不需要set方法

3.然后在dao对象上面添加属性注入的注解(

  • 使用@Autowired直接在属性上写

  • 使用Qualifier这个注解,需要和@Autowired一起使用

  • 使用Resource,直接添加到属性上就是根据类型注入,如果加上name属性就是根据名称进行注入

  • 使用Value这个注解,在普通属性上添加,并且设置value值就是它的值)

4.(要注意我们的xml文件的配置中,一定要将我们需要自动装备的包都添加进去)

基于java类的自动装配
@Configuration//作为配置类,替代xml配置文件
@ComponentScan(basePackages = "Java")//路径
public class Config {

}
普通bean和工厂bean的区别
  1. 普通bean返回的类型只能是我们定义的类型

  2. 工厂bean返回的可以不是我们定义的类型

IOC的生命周期
  1. 执行无参构造,创建bean的实例
  2. 调用set方法设置属性值
  3. 在初始化之前执行的方法
  4. 执行初始化的方法
  5. 在初始化之后执行的方法
  6. 获取创建bean的实例对象
  7. 执行销毁方法

AOP

概念:不通过修改源码的方式,在主干功能里面添加新的功能

底层原理:使用动态代理

  1. 有接口的情况下:创建接口实现类的代理对象,增强类的方法

  2. 没有接口的情况下:创建子类的代理对象,增强类的方法

AOP术语:

  1. 连接点:类里面那些方法被增强了

  2. 切入点:实际被增强的方法

  3. 通知(增强):实际被增强的逻辑部分成为通知

    1. 前置通知
         2. 后置通知
         3. 环绕通知
         4. 异常通知
         5. 最终通知
    
    1. 切面:动作,把通知应用到切入点的过程

AOP准备操作:

 1. Spring框架一般都是基于AspectJ实现AOP操作的
       1. AspectJ不是spring的组成部分,是独立的框架
  1. 基于AspectJ实现AOP操作
    1. 基于xml配置文件
    2. 基于注解方式
  2. 在项目中引入相关jar包
    1. springsource.net.sf.cglib
    2. springsource.org.aopalliance
    3. springsource..org.aspectj.weaver
    4. aspectj.release
  3. 切入点表达式
    1. 作用:知道对哪个类里面的哪个方法进行增强
    2. 语法结构:execution(权限修饰符、返回类型、类全路径、方法名称(参数列表))
      1. 例:execution(* com.dao.add.*)

AOP操作:

  • 基于注解方式开发

    1. 创建类:

      @Component
      public class Userimpl {
          public void add() {
              System.out.println("add...........");
          }
      }
    2. 创建增强类

      @Component
      @Aspect
      public class UserProxy {
          //增强类
       @Before("execution(* dao.Userimpl.add())")
          public void before(){
              System.out.println("before/........");
          }
          public void after(){
              System.out.println("before/........");
          }
      
      }
      
    3. 创建配置文件

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:context="http://www.springframework.org/schema/context"
             xmlns:aop="http://www.springframework.org/schema/aop"
             xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                                  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                                  http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
          <!--开启自动扫描    -->
          <context:component-scan base-package="dao"></context:component-scan>
          <!--生成AspectJ对象    -->
          <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
      </beans>
    4. 配置不同类型的通知

       //增强类
      
      //调用前
          @Before("execution(* AspeectJ.User1.add())")
          public void before(){
              System.out.println("before/........");
          }
      //调用后
          @After("execution(* AspeectJ.User1.add())")
          public void after(){
              System.out.println("after/........");
          }
      //返回值时
          @AfterReturning("execution(* AspeectJ.User1.add())")
          public void AfterReturning(){
              System.out.println("AfterReturning/........");
          }
      //抛异常时
          @AfterThrowing("execution(* AspeectJ.User1.add())")
          public void AfterThrowing(){
              System.out.println("AfterThrowing/........");
          }
      //环绕
          @Around("execution(* AspeectJ.User1.add())")
          public void Around(ProceedingJoinPoint joinPoint) throws Throwable {
      
              System.out.println("环绕前/........");
              joinPoint.proceed();
              System.out.println("环绕后/........");
          }
      
    5. 方法抽取

       //公共抽取
          @Pointcut(value = "execution(* AspeectJ.User1.add())")
          public void Pointdemo(){
      
          }
      
       @Before(value = "Pointdemo()")
          public void before(){
              System.out.println("before/........");
          }
      
      //这里报错了,可能是因为jar包版本的错误,也可能是jdk版本的错误
      
    6. 设置优先级

      在增强方法的类上面添加@Order(数字值越小,优先级越高)

  • 基于xml配置文件开发

    1. 首先创建两个类,一个普通类,一个增强类

    2. 然后再写配置文件

      <!--    配置类-->
          <bean id="user1" class="AspeectJ.User1"></bean>
          <bean id="userproxy" class="AspeectJ.UserProxy"></bean>
      
          <!--aop配置-->
          <aop:config>
      <!--        配置切入点-->
              <aop:pointcut id="p" expression="execution(* AspeectJ.User1.add())"/>
      <!--        配置切面-->
              <aop:aspect id="proxy" ref="userproxy">
                 <aop:before method="before" pointcut-ref="p"></aop:before>
              </aop:aspect>
          </aop:config>
  • 完全开发,没有配置文件的开发

    • 需要添加一个aop操作的类文件

      package AspeectJ;
      @Configuration//变成配置类文件
      @ComponentScan(basePackages = "AspeectJ")//组件扫描
      @EnableAspectJAutoProxy(proxyTargetClass = true)
      public class AspectJConfig {
      
      }

JDBCTemplate

​ 概念:JDBCTemplate是spring对JDBC的封装,使用JDBCTemplate对数据库进行操作

​ 准备工作:

  1. 引入相关依赖

    . druid-1.0.9.jar

            2. mysql-connector-java-5.1.6.jar
            3. spring-jdbc-5.2.9.RELEASE.jar
            4. spring-tx-5.2.9.RELEASE.jar
            5. spring-orm-5.2.9.RELEASE.jar
    
    
    2. 配置数据库连接池
    
    <bean id="datasource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
            <property name="url" value="jdbc:mysql:///user_db"></property>
            <property name="username" value="root"></property>
            <property name="password" value="root"></property>
            <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        </bean>
    3. 配置jdbc对象,注入DataSource
    
    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <!--        注入DataSource-->
            <property name="dataSource" ref="datasource"></property>
        </bean>
    4. 装配实现的dao以及service层
    
    <!--配置自动装配-->
        <context:component-scan base-package="service,dao"></context:component-scan>
  2. 总结:这里因为我的MySQL版本和驱动版本问题,不能进行数据库连接,无法进行下面的课程学习代码,但是JDBCTemplate在javaweb中都用过,所以这些都是复习性的过一遍

事务

  1. 什么是事务:事务是数据库操作的最基本单元,逻辑上一组操作,要么都成功,要么都失败

  2. 事务的四个特性(ACID)

    1. 原子性:操作过程不可分割,要么都成功,要么都失败
    2. 一致性:操作前和操作后总量是不变的
    3. 隔离性:多事务操作之间不会产生影响
    4. 持久性:提交数据后,会进行保存
  3. 事务操作

    1. 配置事务管理器

      //加入tx命名空间
      xmlns:tx="http://www.springframework.org/schema/tx"
      
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
      
      //创建事务操作
       <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
              <!--注入DataSource-->
              <property name="dataSource" ref="datasource"></property>
          </bean>
      
      //开启事务注解
       <tx:annotation-driven transaction-manager="dataSourceTransactionManager"></tx:annotation-driven>
    2. 在类上或者方法上加注解@Transaction

  4. 事务管理参数配置

    1. 事务传播行为:7种
      1. REQUIRED:如果一个方法本身有事务,在方法里调用另一个方法,那么就都使用这个事务
      2. REQUIRED_NEW:一个方法调用另一个方法,不管有没有事务,都会创建一个新的事务
      3. 操作:@Transaction(propagation = propagation.REQUIRED
    2. 事务隔离性:
      1. 存在问题:脏读、不可重复读、虚读
        1. 脏读:一个未提交的事务读取到另一个未提交的事务
        2. 不可重复读:一个未提交的事务读取到另一个提交的事务
        3. 虚读:一个未提交的事务读取到另一个提交的添加事务
      2. 解决:通过隔离级别解决
        1. read uncommited:读未提交
        2. read commited:读已提交
        3. repeatable read:可重复读
        4. serializable:串行化
      3. 设置方式:@Transaction(isolation = isolation .serializable)
    3. 超时时间:timeout
      1. 事务需要在一定的时间内提交,如果不提交则回滚
      2. 默认值是-1,设置时间以秒为单位进行计算
    4. readOnly:是否只读
      1. 默认设置为false
      2. 设置为只读,就不能进行增删改操作
    5. rollbackFor:回滚
      1. 设置出现哪些异常进行事务回滚
    6. morollbackFor:不回滚
      1. 设置哪些事务不回滚

spring5框架新功能

  1. spring框架代码基于java8,运行时兼容jdk9,许多不建议使用的类和方法在代码库中删除

  2. spring5框架自带了通用的日志封装

    1. 移除了log4j
    2. 整合了log4j2
    3. 使用:
      1. 引入jar包:
        1. log4j-api
        2. log4j-core
        3. log4j-slf4j
        4. slf4j-api
      2. 写xml配置文件
  3. spring5框架核心容器支持@Nullable注解:

    @Nullable注解可以使用在方法、属性、参数上面,表示它们的返回值可以为空

  4. spring5支持整合JUnit5

    1. 整合JUnit4

      1. 第一步引入spring-test依赖

      2. 创建测试类,使用注解方法

        @RunWithSpringJUnit4ClassRunner.class@ContextConfiguration("classpath:bean.xml")
    2. 整合JUnit5

      1. ​ 第一步引入JUnit5的jar包

      2. 第二步创建测试类,使用注解完成

        @ExtendWith(SpringExtension.calss)
        @ContextConfiguration("calsspath:bean.xml")
        
        //改进之后
        @SpringJUnitConfig(locations="classpath:bean.xml")

Spring5框架新功能:WebFlux

  1. springwenflux介绍
    1. 是spring5添加新的模块,用于web开发,功能和springMVC类似的,webflux适用当前一种比较流程响应式编程出现的框架
    2. 使用传统web框架,比如springMVC,这些基于servlet容器,webflux是一种一步非阻塞的框架,一步非阻塞的框架在servlet3.1以后才支持,核心是基于Reactor的相关API实现的
    3. 解释什么是异步非阻塞
      1. 异步和同步针对调用者:调用者发送请求,如果等着对方回应之后才去做其他事情就是同步,如果发送请求之后不等着对方回应就去做其他事情就是异步
      2. 阻塞和非阻塞对被调用者:被调用者收到请求之后,做完请求任务之后才给出反馈就是阻塞,受到请求之后马上给出反馈然后再去做事情就是非阻塞
    4. Webflux特点:
      1. 非阻塞式:在有限的资源下,提高系统吞吐量和伸缩性,以reactor为基础实现响应式编程
      2. 函数式编程:spring5框架基于java8,webflux使用java8函数式编程方式实现路由请求
    5. 比较Springmvc
      1. 两个框架都可以使用注解方式,都运行在Tomcat等容器中
      2. SpringMVC采用命令式编程,Webflux采用异步响应式编程
  2. 响应式编程(Reactor实现)
    1. 响应式编程操作中,Reactor是满足Reactive规范框架
    2. Reactor有两个核心类,Mono和Flux,这两个类实现接口publiser,提供丰富操作符。flux对象实现发布者,返回N和元素;Mono实现发布者,返回0或者1个元素
    3. flux和Mono都是数据流的发布者,使用Flux和Mono都可以发出三种数据信号:元素值、错误信号、成功信号,错误信号和完成信号都代表终止信号,终止信号用于告诉订阅者数据流结束了,错误信号终止数据流同时吧错误信息传递给订阅者
    4. 三种信号特点:
      1. 错误信号和完成信号都是终止信号,不能共存
      2. 如果没有发送任何元素值,而是直接发送错误或者完成信号,表示空数据流
      3. 如果没有错误信号,没有完成信号,表示是无线数据流
    5. 调用just或者其他方法只是声明了数据流,数据流并不会发出,只有订阅了才会发出,不订阅什么都不会发生
    6. 操作符
      1. map:将元素映射成新元素
      2. flatMap:将元素映射成流
        1. 将每个元素映射成流,然后将流都合并成一个大流
  3. springwebflux执行流程和核心api
    1. springwebflux基于reactor,默认使用容器是Netty,Netty是高性能NIO框架,异步非阻塞框架
    2. 阻塞和非阻塞
      1. BIO:阻塞
      2. NIO:非阻塞
    3. springwebflux执行过程和springMVC相似的
      1. springwebflux核心控制器DispatchHandler,实现接口webHandler
      2. 接口WebHandler有一个方法
      3. springwebflux里面DispatcherHandler,负责请求的处理:
        1. HandlerMapping:请求查询到处理的方法
        2. HandlerAdapter:真正负责请求的处理
        3. HandlerResultHandler:响应处理结果
      4. springwebflux实现函数式变成,两个接口:RouterFunction(路由处理)和HandlerFunction(处理函数)

实践


文章作者: Mr Hou
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Mr Hou !
希望得到你的建议哦
  目录