• Spring学习


    Spring框架概述

    1. Spring是轻量级的开源的JavaEE框架
    2. Spring可以解决企业应用开发的复杂性
    3. Spring有两个核心部分:IOC和Aop
      1. IOC:控制反转,把创建对象过程交给Spring进行管理
      2. Aop:面向切面,不修改源代码进行功能增强
    4. Spring特点:
      1. 方便解耦,简化开发
      2. Aop编程支持
      3. 方便程序测试
      4. 方便和其他框架进行整合
      5. 方便进行事务操作
      6. 降低API开发难度

    入门案例

    1. 下载Spring5jar包

      https://repo.spring.io/artifactory/release/org/springframework/spring/

      通过spring.io查看最新版本的spring,然后下载,也可以走maven。

    2. 打开IDEA,创建普通的Java工程。

    3. 导入Spring5相关jar包

      先导入基础的Beans、Core、Context、Expression,额外还需要一个commons-logging包

    spring-1

    spring-2

    1. 创建一个普通的类,一个普通的方法

      public class User {
          public void add(){
              System.out.println("add==========");
          }
      }
      
    2. 创建spring配置文件,在配置文件中配置创建对象

      文件格式为xml。

      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
          <bean id="user" class="bean.User"></bean>
      </beans>
      
    3. 测试代码编写

      public class TestAdd {
          @Test
          public void testAdd(){
              //1.记载spring配置文件
              ApplicationContext context = new ClassPathXmlApplicationContext("bean1config.xml");
              //2.获取配置的对象
              User user = context.getBean("user", User.class);
              System.out.println(user);
              user.add();
          }
      }
      

      IOC容器

      1. IOC底层原理

      1. 什么是IOC

        1. 控制反转,把对象创建和对象之间的调用过程,交给Spring进行管理
        2. 使用IOC目的:为了耦合度降低
        3. 做入门案例就是IOC实现
      2. IOC底层原理

        1. xml解析、工厂模式、反射
      3. 画图解析IOC

        spring-3

      2. IOC接口(BeanFactory)

      1. IOC思想基于IOC容器完成,IOC容器底层就是对象工厂

      2. Spring提供IOC容器实现两种方式:(两个接口)

        1. BeanFactory:IOC容器基本实现,是Spring内部的使用接口,不提供开发人员使用。
          • 加载配置文件的时候不会创建对象,在获取(使用)对象才去创建对象。
        2. ApplicationContext:BeanFactory接口的子接口,提供了更多更强大的功能,一般由开发人员使用。
          • 加载配置文件时就会把在配置文件对象进行创建
      3. ApplicationContext接口有实现类

        spring-4

      3. IOC操作Bean管理

      1. 什么时Bean管理
        1. Bean管理指的是两个操作
        2. Spring创建对象
        3. Spring注入属性
      2. Bean管理操作有两种方式
        1. 基于XML配置文件方式实现
        2. 基于注解方式实现

      4. IOC操作Bean管理(基于XML)

      1. 基于XML方式创建对象

        1. 在spring配置文件中,使用bean标签,标签里面添加对应属性,就可以实现对象创建
        2. bean标签有很多属性
          • id属性:唯一标识
          • class属性:类的全路径(包类路径)
        3. 创建对象时,默认也是执行无参构造方法,如果没有无参方法,会报错。
      2. 基于XML方式注入属性

        1. DI:依赖注入,就是注入属性
      3. 第一种注入方法,使用set方法进行注入

        1. 创建类,定义属性和对应的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;
              }
          
              @Override
              public String toString() {
                  return "book{" +
                          "name='" + name + '\'' +
                          ", author='" + author + '\'' +
                          '}';
              }
          }
          
        2. 在spring配置文件中配置对象创建,配置属性注入

          <bean class="com.luomuchen.bean.Book" id="book">
          <!--        name 属性的名字
                      value 属性的值-->
                  <property name="name" value="易筋经"></property>
                  <property name="author" value="达摩老祖"></property>
              </bean>
          
        3. 测试运行

          @Test
              public void testBookAdd(){
                  ApplicationContext context = new ClassPathXmlApplicationContext("bean1config.xml");
                  Book book = context.getBean("book", Book.class);
                  System.out.println(book);
              }
          结果:
              book{name='易筋经', author='达摩老祖'}
          
      4. 通过有参构造器进行注入

        1. 创建类,创建有参构造器

          public class Person {
              private String name;
              private int age;
              public Person(String name, int age) {
                  this.name = name;
                  this.age = age;
              }
          
              @Override
              public String toString() {
                  return "Person{" +
                          "name='" + name + '\'' +
                          ", age=" + age +
                          '}';
              }
          }
          
        2. XML用有参构造注入属性

          <bean class="com.luomuchen.bean.Person" id="person">
                  <constructor-arg value="张三" name="name"></constructor-arg>
                  <constructor-arg name="age" value="27"></constructor-arg>
              </bean>
          
        3. 测试运行

          @Test
              public void testPersonAdd(){
                  Person person = context.getBean("person", Person.class);
                  System.out.println(person);
              }
          结果:Person{name='张三', age=27}
          
      5. p名称空间注入

        • 使用p名称空间注入,可以简化基于XML配置(了解即可)

          <beans xmlns="http://www.springframework.org/schema/beans"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 在头上加这个
                 xmlns:p = "http://www.springframework.org/schema/p"
                 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
              <bean class="com.luomuchen.bean.Book" id="book2" p:author="同济大学" p:name="高等数学">
          

        4. IOC操作Bean管理(注入其他类型属性)

        1. 字面量

          1. null

             <property name="address">
                 <null/>
             </property>
            
          2. 属性中包含特殊符号

           <property name="address">
               <value><![CDATA[<<南京>>]]></value>
           </property>
          ![CDATA[]]中为纯文本
          
        2. 注入属性-外部bean

          1. 创建两个类service类和dao类

            
            //service类
            public class UserService {
                private UserDao userDao;
            
                public void setUserDao(UserDao userDao) {
                    this.userDao = userDao;
                }
            
                public void add(){
                    System.out.println("Service Add.........");
                    userDao.update();
                }
            }
            
            //dao层接口类
            public interface UserDao {
                public void update();
            }
            //dao层实现类
            public class UserDaoImpl implements UserDao{
                @Override
                public void update() {
                    System.out.println("service update................");
                }
            }
            
            
          2. service调用dao里面的方法

          3. 在spring配置文件中进行配置

               <bean id="userService" class="com.luomuchen.service.UserService">
                    <property name="userDao" ref="userDao"></property>
                </bean>
                <bean id="userDao" class="com.luomuchen.dao.UserDaoImpl"></bean>
            
        3. 注入属性-内部bean和级联赋值

          1. 一对多关系:部门跟员工

            //员工类
            public class Emp {
                private String ename;
                private String gender;
                private Dept dept;
                //级联赋值需要get方法
                public Dept getDept() {
                    return dept;
                }
            
                public void setEname(String ename) {
                    this.ename = ename;
                }
            
                public void setGender(String gender) {
                    this.gender = gender;
                }
            
                public void setDept(Dept dept) {
                    this.dept = dept;
                }
            
                @Override
                public String toString() {
                    return "Emp{" +
                            "ename='" + ename + '\'' +
                            ", gender='" + gender + '\'' +
                            ", dept=" + dept +
                            '}';
                }
            }
            //部门类
            public class Dept {
                private String dname;
            
                public void setDname(String dname) {
                    this.dname = dname;
                }
            
                @Override
                public String toString() {
                    return "Dept{" +
                            "dname='" + dname + '\'' +
                            '}';
                }
            }
            
            <!--    内部bean赋值-->
                <bean id="emp1" class="com.luomuchen.bean.Emp">
                    <property name="ename" value="Lucy"></property>
                    <property name="gender" value="女"></property>
                    <property name="dept">
                        <bean id="dept" class="com.luomuchen.bean.Dept">
                            <property name="dname" value="开发"></property>
                        </bean>
                    </property>
                </bean>
            <!--    级联赋值-->
                <bean id="emp2" class="com.luomuchen.bean.Emp">
                    <property name="ename" value="ming"></property>
                    <property name="gender" value="男"></property>
                    <property name="dept" ref="dept2"></property>
                </bean>
                <bean id="dept2" class="com.luomuchen.bean.Dept">
                    <property name="dname" value="运维"></property>
                </bean>
            <!--    级联赋值方法2-->
                <bean id="emp3" class="com.luomuchen.bean.Emp">
                    <property name="ename" value="洛"></property>
                    <property name="gender" value="女"></property>
                    <property name="dept" ref="dept3"></property>
            <!--        需要Emp类中有Dept的get方法-->
                    <property name="dept.dname" value="boss"></property>
                </bean>
                <bean id="dept3" class="com.luomuchen.bean.Dept"></bean>
            

      5. IOC操作Bean管理(XML注入集合属性)

      public class Stu {
          //数组类型
          private String[] courses;
          //list类型
          private List<String> list;
          //map类型
          private Map<String, String> map;
          //set类型
          private Set<String> set;
      
          public void setCourses(String[] courses) {
              this.courses = courses;
          }
      
          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 test(){
              System.out.println(Arrays.toString(courses));
              System.out.println(list);
              System.out.println(map);
              System.out.println(set);
          }
      }
      
      <bean id="stu" class="com.luomuchen.bean.Stu">
              <property name="courses">
                  <array>
                      <value>本科</value>
                      <value>java课程</value>
                      <value>数据机构</value>
                  </array>
              </property>
              <property name="list">
                  <list>
                      <value>洛</value>
                      <value>天</value>
                      <value>依</value>
                  </list>
              </property>
              <property name="map">
                  <map>
                      <entry key="luo" value="洛"></entry>
                      <entry key="tian" value="天"></entry>
                  </map>
              </property>
              <property name="set">
                  <set>
                      <value>yue</value>
                      <value>zheng</value>
                      <value>ling</value>
                  </set>
              </property>
          </bean>
      
      • 通过提取(util)

      6. IOC操作Bean管理(工厂Bean)

      1. Spring有两种类型bean,一种普通bean,另外一种工厂bean(FactoryBean)

      2. 普通bean:在配置文件中定义bean类型就是返回类型

      3. 工厂bean:在配置文件中定义bean类型可以和返回类型不一样

        1. 创建一个普通的类,作为工厂Bean,实现接口FactoryBean

          public class Book implements FactoryBean<Dept> {
              //设置返回的类型
              @Override
              public Dept getObject() throws Exception {
                  Dept dept = new Dept();
                  dept.setDname("保安");
                  return dept;
              }
          
              @Override
              public Class<?> getObjectType() {
                  return null;
              }
          
              @Override
              public boolean isSingleton() {
                  return FactoryBean.super.isSingleton();
              }
          }
          
        2. 实现接口里面的方法,在实现的方法中定义返回的bean类型。

          <bean id="myBean" class="com.luomuchen.factoryBean.Book"></bean>
          
        3. 测试时返回的时Dept类型,而不是原工厂类类型

          public class testFactory {
              ApplicationContext context = new ClassPathXmlApplicationContext("bean5.xml");
              @Test
              public void testFactory(){
                  Dept myBean = context.getBean("myBean", Dept.class);
                  System.out.println(myBean);
              }
          }
          

      7. IOC操作Bean管理(Bean作用域)

      1. 在Spring里面,设置创建bean是单实例还是多实例
      2. 在Spring里面,默认情况下,bean是单例模式
      3. 如何设置单实例还是多实例
        1. 在spring配置文件bean标签里面有属性(scope)用于设置单实例还是多实例
        2. scope属性
          • singleton,单实例
          • prototype,多实例
        3. singleton和prototype区别
          1. 分别代表单实例和多实例
          2. 设置scope为singleton时候,加载spring配置文件时就会创建单实例对象,设置scope为prototype时候,在调用getBean时候,创建多实例对象。

      8. IOC操作Bean管理(Bean的生命周期)

      1. 生命周期
        1. 从对象创建到对象销毁的过程
      2. bean生命周期
        1. 通过构造器创建bean实例(无参数构造)
        2. 为bean的属性设置值和对其他bean引用(调用set方法)
        3. 调用bean的初始化的方法(需要进行配置初始化的方法)
        4. bean可以使用了(对象获取到了)
        5. 当容器关闭时候,调用bean销毁方法(需要进行配置销毁的方法)
      3. bean的后置处理
        1. 在第三步之前,把bean实例传递bean后置处理器的方法
        2. 在第三步之后,把bean实例传递bean后置处理器的方法

      9. IOC操作Bean管理(基于注解)

      1. 什么是注解

        1. 注解时代码特殊标记,格式:@注解名称(属性名称=属性值,属性名称=属性值。。。)
        2. 使用注解,注解作用在类上面,方法上面,属性上面。
        3. 使用注解目的:简化XML配置。
      2. Spring针对Bean管理中创建对象提供注解

        1. @Component
        2. @Service
        3. @Controller
        4. @Repository
        • 这四个注解功能是一样的,都可以用来创建bean实例
      3. 基于注解 方式实现对象创建

        1. 引入依赖,AOP包

        2. 开启组件扫描

          命名空间加入

          <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"
                 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">
          

          开启组件扫描

              <!--开启组件扫描
              1.如果扫描多个包,多个包之间用逗号隔开
              2.或者扫描他们的上层目录
              -->
              <context:component-scan base-package="com.luomuchen"></context:component-scan>
          
        3. 创建一个有注解的类

          //注解中value值可以不写
          //默认为类名的首字母小写
          //UserService -- userService
          @Service(value = "userService")
          public class UserService {
              public void add(){
                  System.out.println("Service Add........");
              }
          }
          
        4. 测试

          public class test1 {
              ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
              @Test
              public void testAdd(){
                  UserService userService = context.getBean("userService", UserService.class);
                  userService.add();
              }
          }
          
      4. 开启组件扫描的细节

        可以自己配置扫描哪个包,或者不扫描

      5. 基于注解方式实现属性注入

        1. @AutoWired:根据属性类型进行注入

          1. 把service和dao对象创建,在service和dao类添加创建对象注解。

            注意dao层的注解要加到实现类上面

          2. 在service注入dao对象

        2. @Qualifier:根据属性名称进行注入

        3. @Resource:可以根据类型注入,也可以根据名称注入

          spring官方不推荐使用,因为这是javax包中的注解,不是spring官方注解

          @Service(value = "userService")
          public class UserService {
          //    @Resource //根据类型注入
              @Resource(name = "userDaoImpl1")
              UserDao userDao;
              public void add(){
                  System.out.println("Service Add........");
                  userDao.add();
              }
          }
          
        4. @Value:注入普通类型属性

              @Value("adb")
              String string;
          
      6. 完全注解开发

        创建配置类,替代xml文件

        @Configuration
        @ComponentScan("com.luomuchen")
        public class MyConfig {
        }
        

        测试类

            ApplicationContext context2 = new AnnotationConfigApplicationContext(MyConfig.class);
            @Test
            public void testAdd(){
                UserService userService = context2.getBean("userService", UserService.class);
                userService.add();
            }
        

    AOP(概念)

    1. 什么是AOP

      1. 面向切面编程(方面),利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

      2. 通俗描述:不通过修改源代码的方式,在主干功能里添加新功能

      3. 使用登录的例子说明AOP

        spring-5

    AOP(底层原理)

    1. AOP底层使用动态代理
      1. 有两种情况动态代理
        1. 有接口情况,使用JDK动态代理
          • 创建接口实现类代理对象,增强类的方法
        2. 没有接口情况,使用CGLIB动态代理
          • 创建子类的代理对象,增强类的方法

    AOP(JDK动态代理)

    AOP(术语)

    1. 连接点

      类的哪些方法可以被增强,这些方法称为连接点。

    2. 切入点

      实际被真正增强的方法,成为切入点

    3. 通知(增强)

      1. 实际增强的逻辑部分称为通知(增强)
      2. 通知有多种类型
        • 前置通知
        • 后置通知
        • 环绕通知
        • 异常通知
        • 最终通知
    4. 切面

      是动作,把通知应用到切入点过程

    AOP(准备工作)

    1. Spring框架一般都是基于AspectJ实现AOP操作

      1. 什么是AspectJ

        AspectJ不是Spring组成部分,独立AOP框架,一般把AspectJ和Spring框架一起使用,进行AOP操作

      2. 基于AspectJ实现AOP操作

        1. 基于XML配置文件
        2. 基于注解方式实现(使用)
      3. 在项目工程里引入AOP相关依赖

            <dependencies>
                <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-aspects</artifactId>
                    <version>5.3.2</version>
                </dependency>
                <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-context</artifactId>
                    <version>5.3.2</version>
                </dependency>
                <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-core</artifactId>
                    <version>5.3.2</version>
                </dependency>
                <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-beans</artifactId>
                    <version>5.3.2</version>
                </dependency>
                <!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-aop</artifactId>
                    <version>5.3.2</version>
                </dependency>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-expression</artifactId>
                    <version>5.3.2</version>
                </dependency>
                <!-- https://mvnrepository.com/artifact/cglib/cglib -->
                <dependency>
                    <groupId>cglib</groupId>
                    <artifactId>cglib</artifactId>
                    <version>2.2</version>
                </dependency>
                <!-- https://mvnrepository.com/artifact/aopalliance/aopalliance -->
                <dependency>
                    <groupId>aopalliance</groupId>
                    <artifactId>aopalliance</artifactId>
                    <version>1.0</version>
                </dependency>
                <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
                <dependency>
                    <groupId>org.aspectj</groupId>
                    <artifactId>aspectjweaver</artifactId>
                    <version>1.6.8</version>
                    <scope>runtime</scope>
                </dependency>
                <dependency>
                    <groupId>org.aspectj</groupId>
                    <artifactId>aspectjrt</artifactId>
                    <version>1.9.7</version>
                </dependency>
                <!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
                <dependency>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                    <version>1.2</version>
                </dependency>
                <dependency>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                    <version>4.12</version>
                    <scope>compile</scope>
                </dependency>
        
            </dependencies>
        
      4. 切入点表达式

        1. 切入点表达式作用:知道对那个类里面的哪个方法进行增强

        2. 语法结构:

          execution([权限修饰符][返回类型][类全路径][方法名称][参数列表])

          例如:

          1. 对com.muchen.dao.BookDao类里面的add进行增强

            execution(* com.muchen.dao.BookDao.add(..))

          2. 对com.muchen.dao.BookDao类里面的所有方法进行增强

            execution(* com.muchen.dao.BookDao.*(..))

          3. 对com.muchen.dao包里所有类,类里面所有方法进行增强

            execution(* com.muchen.dao.*.*(..))

    AOP(AspectJ注解)

    1. 创建类,在类里面定义方法

    2. 创建增强类

      1. 在增强类里面创建方法,让不同的方法代表不同的通知类型
    3. 进行通知的配置

      1. 在spring配置文件中,开启注解扫描

        这里用了注解配置

        @Configuration
        @ComponentScan("com.luomuchen")
        @EnableAspectJAutoProxy
        public class MyConfig {
        }
        
      2. 使用注解创建User和UserProxy对象

        @Component
        public class User {
            public void add(){
                System.out.println("add User .......");
            }
        }
        
        @Component
        @Aspect
        public class UserProxy {
            //前置通知
            //Before注解表示前置通知
            @Before(value = "execution(* com.luomuchen.aopanno.User.add(..))")
            public void before(){
                System.out.println("Before......");
            }
            @After(value = "execution(* com.luomuchen.aopanno.User.add(..))")
            public void after(){
                System.out.println("After......");
            }
            @AfterReturning(value = "execution(* com.luomuchen.aopanno.User.add(..))")
            public void afterReturning(){
                System.out.println("AfterReturning......");
            }
            @AfterThrowing(value = "execution(* com.luomuchen.aopanno.User.add(..))")
            public void afterThrowing(){
                System.out.println("AfterThrowing......");
            }
            @Around(value = "execution(* com.luomuchen.aopanno.User.add(..))")
            public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
                System.out.println("环绕之前");
                proceedingJoinPoint.proceed();
                System.out.println("环绕之后");
            }
        }
        
      3. 在增强类上面添加注解@AspectJ

      4. 在Spring配置文件中开启生成代理对象

      1. 公共切入点抽取

        @Component
        @Aspect
        public class UserProxy {
            //相同切入点抽取
            @Pointcut(value = "execution(* com.luomuchen.aopanno.User.add(..))")
            public void pointDemo(){
        
            }
            //前置通知
            //Before注解表示前置通知
            @Before(value = "pointDemo()")
            public void before(){
                System.out.println("Before......");
            }
            @After(value = "pointDemo()")
            public void after(){
                System.out.println("After......");
            }
            @AfterReturning(value = "pointDemo()")
            public void afterReturning(){
                System.out.println("AfterReturning......");
            }
            @AfterThrowing(value = "pointDemo()")
            public void afterThrowing(){
                System.out.println("AfterThrowing......");
            }
            @Around(value = "pointDemo()")
            public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
                System.out.println("环绕之前");
                proceedingJoinPoint.proceed();
                System.out.println("环绕之后");
            }
        }
        
    4. 有多个增强类对同一个方法进行增强,设置增强类优先级

      1. 在增强类上面添加注解@Order(数字类型),数字类型优先级值越小,优先级越高。

    JdbcTemplate(概念和准备)

    1. 什么是JdbcTemplate

      1. Spring框架对于JDBC进行封装,使用JdbcTemplate方便实现对数据库操作

      2. 准备工作

        1. 引入相关jar包

          新增:druid-1.1.9,mysql-connector,spring-jdbc,spring-orm,spring-tx

        2. 在spring配置文件中配置数据库的连接池

        3. 配置JdbcTemplate对象,注入数据源的bean

        4. 创建service类,创建dao类,在dao注入JdbcTemplate对象

    • 数据库操作,ssm会交给框架解决,这里略过不提。

    事务概念

    1. 什么是事务
      1. 事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,如果有一个失败,所有操作都失败
      2. 典型场景:银行转账
        • lucy转100给mary
        • lucy少100,mary多100
    2. 事务四个特性(ACID)
      1. 原子性
      2. 一致性
      3. 隔离性
      4. 持久性

    ------------恢复内容结束------------

  • 相关阅读:
    不同包中继承关系访问protected内部类问题
    LinuxMM--MemoryHierarchy
    LinuxMM--Memory Pressure
    多态实验:基类——子类成员
    使用vue开发的word-cloud 词云组件
    基于mui.PopPicker的可多选下拉多选的底部弹出组件
    基于mui.popover的自定义底部弹出框-支持多选和搜索筛选的弹出列表组件改造以及mui.prompt添加自定义内容
    js去空 去除空格
    css+js控制文字显示行数,多出部分显示省略号
    使用vue开发自定义tabs标签页组件
  • 原文地址:https://www.cnblogs.com/luoxiaoyi/p/16399409.html
Copyright © 2020-2023  润新知