Spring

Spring 5 框架—入门

1 IOC

1.1 IOC 是什么

  • 控制反转,把对系那个创建和对象间的调用过程,交给 Spring 进行管理。
  • 使用ICO目的是为了降低耦合度

1.2 IOC 底层原理

  • xml 解析,反射,工厂原理
  • 底层原理图 image-20220427133908957

1.3 IOC 接口

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

  • Spring 提供 IOC 容器实现的两种方式 (两个接口)

    • BeanFactory :IOC 容器基本实现,是 Spring 内部的使用接口,不提供开发人员进行使用。
      • 加载配置文件时,不会创建对象,但在获取对象或者在使用对象才回去创建对象。
    • ApplicationContext : BeanFactory 接口是子接口,提供更对更强大的功能,一般由开发人员进行使用。
      • 加载配置文件时,就会把在配置文件的对象进行创建对象。
  • ApplicationContext 接口 实现类 image-20220427135518331

  • BeanFactory 接口 实现类 image-20220427135732819

1.4 IOC 操作 Bean 管理

什么是 Bean 管理

Bean 管理的两个操作

  1. Spring 创建对象
  2. Spring 注入属性

Bean 管理操作有两种方式

  1. 基于 XML 配置文件方式实现
  2. 基于注解方式实现
1.4.3 IOC 操作 Bean管理(基于 XML 方式)
1.4.3.1 基于 XML 方式创建对象

image-20220427141357895

  1. 在 Spring 配置文件中,使用 bean 标签,标签里面添加对应属性,就可以实现对象创建。
  2. 在 bean 标签有很多属性,常用属性:
    1. id 属性 : 唯一标识
    2. class 属性: 类全路径(包类路径)
    3. name 属性:与 id 属性相似,但 name 属性中可以加特殊符号,而 id属性不允许
  3. 创建对象的时候,默认执行无参构造方法创建对象
1.4.3.2 基于 XML 方式注入属性
  1. DI:依赖注入,注入属性

    1. 第一种注入方式 : setter() 方法
      java
    • @Description: setter() 方法属性注入
      */
      public class Book {
      //创建属性
      private String Bneam;
      private String Bauthor;
      //setter() 方法
      public void setBauthor(String bauthor) {
      Bauthor = bauthor;
      }
      public void setBneam(String bneam) {
      Bneam = bneam;
      }
     <bean id="book" class="com.atguigu.spring5.Book">
         <!--使用property完成属性注入
            name: 类属性名称
            vaule: 向属性注入的值
         -->
         <property name="bneam" value="易筋经"></property>
         <property name="bauthor" value="达摩祖师"></property>
     </bean>
    


    ​ 2. 第二种注入方式:有参构造注入

    ​ java
    ​ * @Description: 使用有参数构造方法进行属性注入
    ​ */
    ​ public class Orders {
    ​ private String oname;
    ​ private String address;
    ​ //有参构造
    ​ public Orders(String oname, String address) {
    ​ this.oname = oname;
    ​ this.address = address;
    ​ }

    ​ public void ordersTest(){
    ​ System.out.println(oname+“::”+address);
    ​ }
    ​ }






    ​ 3. p 名称空间注入
    ​ 使用 P 明后才能空间注入,可以简化 xml 配置方式
    ​ (1)第一步: 添加 p 名称空间在配置文件中

    (2)第二步 :进行属性注入,在 bean 标签中操作
    
    java
    <!--p 名称空间注入-->
    <bean id="book" class="com.atguigu.spring5.Book" p:bneam="九阳神功" p:bauthor="无名氏">
    </bean>
    
1.4.3.3 字面量
  1. null值

image-20220427152823200

  1. 属性中有特殊符号

    image-20220427153517691

1.4.3.4 注入属性-外部 bean
  1. 创建两个类 service 类和 dao 类
  2. 在 service 调用 dao 里面的方法
  3. 在 spring配置文件中进行配置
//创建 UserDao类型的属性,生成set方法
    private UserDao userDao;
    public void setUserDao(UserDao userDao){
        this.userDao = userDao;
    }

    public void add(){
        System.out.println("service add() ...");
        userDao.update();
    }

//bean2.xml
<!--1.service 和 dao 对象创建-->
    <bean id="userService" class="com.atguigu.spring5.service.UserService">
        <!-- 注入 userDao 对象
        name 属性:类里面的名称
        ref  属性:创建 UserDao 对象 bean 标签 id 值
        -->
        <property name="userDao" ref="userDaoimpl"></property>
    </bean>
    <bean id="userDaoimpl" class="com.atguigu.spring5.dao.UserDaoimpl">
1.4.3.5 注入属性-内部 bean 和级联赋值
  1. 一对多关系:部门和员工(一个部门有多个员工,一个员工只属于某一个部门)
  2. 在实体类之间表示一对多关系,员工表示所属部门,适用对象类型属性进行表示
//部门类
public class Dept {
    private String dnema;

    public Dept(String dnema) {
        this.dnema = dnema;
    }
}

//员工类
public class Emp {
    private String ename;
    private String gender;
    private Dept dept; //员工属于某一个部门
public void setDept(Dept dept) {
        this.dept = dept;
    }
    public void setEname(String ename) {
        this.ename = ename;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }
}

  1. 在Spring配置文件中进行配置
<!--内部bean-->
<bean id="emp" class="com.atguigu.spring5.bean.Emp">
    <!--设置两个基础属性-->
    <property name="ename" value="lucy"></property>
    <property name="gender" value=""></property>
    <!--设置对系那个类型属性-->
    <property name="dept">
        <bean id="dept" class="com.atguigu.spring5.bean.Dept">
            <property name="dname" value="安保部"></property>
        </bean>
    </property>
</bean>
1.4.3.6 注入属性 - 级联赋值
<!--第一种 级联赋值-->
<bean id="emp" class="com.atguigu.spring5.bean.Emp">
    <!--设置两个基础属性-->
    <property name="ename" value="lucy"></property>
    <property name="gender" value=""></property>
    <!--级联赋值-->
    <property name="dept" ref="dept"></property>
    </bean>
    <bean id="dept" class="com.atguigu.spring5.bean.Dept">
        <property name="dname" value="财务部"></property>
    </bean>

<!--第二种 级联赋值-->
    <bean id="emp" class="com.atguigu.spring5.bean.Emp">
        <!--设置两个基础属性-->
        <property name="ename" value="lucy"></property>
        <property name="gender" value=""></property>
        <!--级联赋值-->
        <property name="dept" ref="dept"></property>
        <property name="dept.dname" value="技术部">
            <!--需要在emp中生成getDept()方法-->
        </property>
    </bean>
    <bean id="dept" class="com.atguigu.spring5.bean.Dept">
        <property name="dname" value="财务部"></property>
1.4.3.7 IOC操作 Bean 管理 (xml 注入集合属性)
  1. 注入数组类型属性

  2. 注入 List 集合类型属性

  3. 注入 Map 集合类型属性

    public class Stu {
        //数组类型
        private String[] courses;
        // List 集合类型属性
        private List<String> list ;
        //map 集合类型属性
        private Map<String,String> maps;
        // Set 集合类型属性
        private Set<String> sets;
        public void setCourses(String[] courses) {
            this.courses = courses;
        }
    
        public void setSets(Set<String> sets) {
            this.sets = sets;
        }
    
        public void setList(List<String> list) {
            this.list = list;
        }
    
        public void setMaps(Map<String, String> maps) {
            this.maps = maps;
        }
    }
    
       4. 在 Spring 配置文件中进行配置
    
          ```xml
          <!--1.集合类型属性注入-->
          <bean id="stu" class="com.atguiogu.spring5.collectiontype.Stu">
              <!--数组类型属性注入-->
              <property name="courses">
                  <array>
                      <value>java</value>
                      <value>sql</value>
                  </array>
              </property>
              <!--list类型属性注入-->
              <property name="list">
                  <list>
                      <value>张三</value>
                      <value>小三</value>
                  </list>
              </property>
              <!--Map 类型属性注入-->
              <property name="maps">
                  <map>
                      <entry key="JAVA" value="java"></entry>
                      <entry key="PHP" value="php"></entry>
                  </map>
              </property>
              <!--set类型属性注入-->
              <property name="sets">
                  <set>
                      <value>java</value>
                      <value>php</value>
                  </set>
              </property>
          </bean>
          ```
    
       5. 在集合中设置对象类型值
    
          ```xml
          <!--注入list集合类型,值是对象-->
          <property name="courseList">
              <list>
                  <ref bean="course1"></ref>
                  <ref bean="course2"></ref>
              </list>
          </property>
          
          <!--创建多个course对象-->
              <bean id="course1" class="com.atguiogu.spring5.collectiontype.Course">
                  <property name="cname" value="Spring5 框架"></property>
              </bean>
              <bean id="course2" class="com.atguiogu.spring5.collectiontype.Course">
                  <property name="cname" value="MyBatis 框架"></property>
              </bean>
          ```
    
       6. 把集合注入部分提取出来
    
          1. 在 spring 配置文件中引入名称空间 util
    
             ```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"
                    xmlns:util="http://www.springframework.org/schema/util"
                    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
                                        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
             ```
    
          2. 使用 util 标签完成 list 集合注入提取
    
             ```xml
             <!--1.提取list集合类型属性注入-->
             <util:list id="booklist">
                 <value>易筋经</value>
                 <value>九阴真经</value>
                 <value>九阳神功</value>
             </util:list>
             <!--1.提取list集合类型属性注入使用-->
             <bean id="book" class="com.atguiogu.spring5.collectiontype.Book">
                 <property name="list" ref="booklist"></property>
             </bean>
             ```
    
1.4.3.8 IOC 操作 Bean 管理 (FactoryBean)
  1. Spring 有两种 Bean ,一种是普通 Bean,另一种是工程 Bean (FactoryBean)

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

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

    1. 创建类,让该类作为工厂 bean,实现接口 FactoryBean

    2. 实现接口里面的方法,在实现的方法中定义返回的 bean 类型

      public class MyBean implements FactoryBean {
      
          //定义返回 bean
          @Override
          public Object getObject() throws Exception {
              Course course = new Course();
              course.setCname("abc");
              return course;
          }
      
          @Override
          public Class<?> getObjectType() {
              return null;
          }
      
          @Override
          public boolean isSingleton() {
              return false;
          }
      }
      
       @Test
          public void testFactoryBean(){
              ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");
              Course myBean1 = context.getBean("myBean", Course.class);
              System.out.println(myBean1);
          }
      
      
      //bean3.xml
      <bean id="myBean" class="com.atguiogu.spring5.collectiontype.factorybean.MyBean"></bean>
      
1.4.3.9 IOC 操作 Bean 管理 (bean 作用域)
  1. 在 Spring 中,设置创建 Bean 实例是单实例还是多实例

  2. 在 Spring 中,默认情况下创建单实例对象

    image-20220427230320856

  3. 设置但实力还是多实例

  4. 在 Spring 配置文件 bean 标签里面有属性 (scope) 用于设置但实力还是多实例

  5. scope 属性值

    ​ 第一个值 默认值 singleton 表示单实例对象

    ​ 第二个值 prototype 表示多实例对象

    还有 request session .

  6. singleton 和 prototype 区别

  1.  singleton 单实例  prototype 多实例
  2. 设置 scope 值是  singleton 时,加载 Spring 配置文件时就会创建单实例对象; 设置 scope 值为 prototype 时,不是在加载 Spring 配置文件时创建对象,而是在调用 getBean 方法时,创建多实例对象。

image-20220427231009482

image-20220427230852479
1.4.3.10 IOC 操作 Bean 管理 (bean 生命周期)
  1. 生命周期:从对象创建到对象销毁的过程

  2. bean 生命周期

    1. 通过构造器创建 bean 实例(无参构造)

    2. 为 bean 的属性设置值和对其他 bean 引用 (调用 set 方法)

    3. 将 bean 是传递 bean后置处理器的方法

      @Override
      public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
          return bean;
      }
      
    4. 调用 bean 的初始化的方法 (需要进行配置初始化的方法)

    5. 把 bean 实例传递 bean 后置处理器的方法

      @Override
      public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
          return bean;
      }
      
    6. bean 可以使用了(对象获取到了)

    7. 当容器关闭时,调用 bean 的销毁的方法 (需要进行配置销毁的方法)

  3. 演示 bean生命周期

    bean4.xml
    <bean id="orders" class="com.atguiogu.spring5.bean.Orders"
          init-method="initMethod" destroy-method="destroyMethod">
        <property name="oname" value="手机"></property>
    </bean>
    
    public class Orders {
        private String oname;
    
        public void setOname(String oname) {
            this.oname = oname;
            System.out.println("2. 调用set方法设置属性值");
        }
        // 无参构造
        public Orders() {
            System.out.println("1.  Orders 无参数构造");
        }
        // 创建执行的初始化的方法
        public void initMethod(){
            System.out.println("3.   执行初始化的方法");
        }
        // 创建销毁方法
        public void destroyMethod(){
            System.out.println("5.   执行销毁的方法");
        }
    }
    
        @Test
        public void testBean(){
            ApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");
            Orders orders = context.getBean("orders", Orders.class);
            System.out.println("4.   获取创建的 bean 实例对象");
            System.out.println(orders);
            //手动让 bean 实例销毁
            ((ClassPathXmlApplicationContext)context).close();
        }
    // 运行结果:未添加后置处理器
    1.  Orders 无参数构造
    2. 调用set方法设置属性值
    3.   执行初始化的方法
    4.   获取创建的 bean 实例对象
    com.atguiogu.spring5.bean.Orders@4524411f
    5.   执行销毁的方法
    
  4. Bean生命周期 – 添加后置处理器效果

    1. 创建类,实现接口 BeanPostProcessor,创建后置处理器
    public class MyBeanPost implements BeanPostProcessor {
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("在初始化之前执行");
            return bean;
        }
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            System.out.println("在初始化之后执行");
            return bean;
        }
    }
    //bean4.xml
            <bean id="orders" class="com.atguiogu.spring5.bean.Orders"
              init-method="initMethod" destroy-method="destroyMethod">
            <property name="oname" value="手机"></property>
        </bean>
        
        <!--配置后置处理器-->
        <bean id="MyBeanPost" class="com.atguiogu.spring5.bean.MyBeanPost"></bean>
            //运行结果 添加后置处理器
            1.  Orders 无参数构造
    		2. 调用set方法设置属性值
    			在初始化之前执行
    		3.  执行初始化的方法
    			在初始化之后执行
    		4.  获取创建的 bean 实例对象
    		com.atguiogu.spring5.bean.Orders@704d6e83
    		5.  执行销毁的方法
    
1.4.3.11 IOC 操作 Bean 管理(自动装配)
  1. 自动装配:根据指定装配规则 (属性名称或者属性类型),Spring 自动将匹配的属性值进行注入

  2. 自动装配过程

        <!--手动装配-->
    <!--    <bean id="emp" class="com.atguiogu.spring5.autowire.Emp">-->
    <!--        <property name="dept" ref="dept"></property>-->
    <!--    </bean>-->
    <!--    <bean id="dept" class="com.atguiogu.spring5.autowire.Dept"></bean>-->
        <!--自动装配-->
        <bean id="emp" class="com.atguiogu.spring5.autowire.Emp" autowire="byName">
            <!--
              bean 标签属性 autowire ,自动装配
              autowire 属性常用两个值: byName 根据属性名成注入 注入值 bean的id值与类属性名称一样
                                      byType 根据属性类型注入
            -->
        </bean>
        <bean id="dept" class="com.atguiogu.spring5.autowire.Dept"></bean>
    </beans>
    
    public class Dept {
        @Override
        public String toString() {
            return "Dept{}";
        }
    }
    public class  Emp {
      private Dept dept;
        public void setDept(Dept dept) {
            this.dept = dept;
        }
        @Override
        public String toString() {
            return "Emp{" +
                    "dept='" + dept + '\'' +
                    '}';
        }
        public void test(){
            System.out.println(dept);
        }
    }
    
1.4.3.12 IOC 操作 Bean 管理 (外部属性文件)
  1. 直接配置数据库信息

    1. 配置德鲁伊连接池

    2. 引入德鲁伊连接池依赖 jar 包

    3. 在配置文件中配置数据库信息

        <!--直接配置连接池-->
          <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
              <!--获取property文件内容,根据key获取,使用spring表达式获取-->
      <!--        <property name="driverClassName" value="${jdbc.driverclass}"></property>-->
              <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
      <!--        <property name="url" value="${jdbc.url}"></property>-->
              <property name="url" value="jdbc:mysql://localhost:3306/hsp_db02"></property>
      <!--        <property name="username" value="${jdbc.username}"></property>-->
              <property name="username" value="lxj"></property>
      <!--        <property name="password" value="${jdbc.password}"></property>-->
              <property name="password" value="lxj"></property>
          </bean>
      
  2. 引入外部属性文件配置数据库连接池

    1. 创建外部属性文件,properties 格式文件,写数据库信息

      prop.driverClass=xom.mysql.cj.jdbc.Driver
      prop.url=jdbc:mysql://localhost:3306/hsp_db02
      prop.userName=lxj
      prop.password=lxj
      
    2. 将外部 properties 属性文件引入 spring 配置文件

      1. 引入 context 名称空间
      ```xml
      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:context="http://www.springframework.org/schema/context"
             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
                       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
      ```
      
      1. 在 spring 配置文件中使用标签引入外部属性文件

        <!--引入外部属性文件-->
        <context:property-placeholder location="classpath:jdbc.properties"/>
        <!--直接配置连接池-->
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
            <!--获取property文件内容,根据key获取,使用spring表达式获取-->
                    <property name="driverClassName" value="${prop.driverclass}"></property>
                    <property name="url" value="${prop.url}"></property>
                    <property name="username" value="${prop.userName}"></property>
                    <property name="password" value="${prop.password}"></property>
        </bean>
        

1.4.4 IOC 操作 Bean 管理(基于注解方式)
  1. 什么是注解

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

    1. @Component

    2. @Service

    3. @Controller

    4. @Repository

    5. 以上四个注解功能是一样的,都可以创建 bean 实例

      image-20220623160032296

1.4.4.1 基于注解方式实现对象创建
  1. 引入依赖 (aop jar 包)

  2. 开启组件扫描

    <?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:p="http://www.springframework.org/schema/p"
           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. 扫描多个包,多个包使用逗号隔开
            <context:component-scan
                base-package="com.atguiogu.spring5.dao,com.atguiogu.spring5.service"></context:component-scan>
            2. 扫描包的上层目录
        -->
        <context:component-scan base-package="com.atguiogu.spring5"></context:component-scan>
        
    </beans>
    
  3. 创建类,在类上添加创建对象的注解

    @Component(value = "userService")
    //<bean id ="userService" class="..."/>
    // 在注解里面value属性值可以省略不写,
    // 默认值是类名称,首字母小写 UserService -- userService
    public class UserService {
        public void add(){
            System.out.println("service add ... ");
        }
    }
    public class TestDemo {
        @Test
        public void testService() {
            ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
            UserService userService = context.getBean("userService", UserService.class);
            System.out.println(userService);
            userService.add();
        }
    com.atguiogu.spring5.service.UserService@60dcc9fe
    service add ... 
    
  4. 开启组件扫描细节配置

    <!--示例1
      use-default-filters="false" 表示不使用默认 filter,自己配置 filter
      context:include-filter 设置扫描哪些内容
    -->
    <context:component-scan base-package="com.atguiogu.spring5" use-default-filters="false">
        <context:include-filter type="annotation"
                                expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
    
    
    <!--实例2
       以下配置扫描包中所有内容
       context:exclude-filter: 设置哪些内容不进行扫描
    -->
       <context:component-scan base-package="com.atguiogu.spring5" >
        <context:exclude-filter type="annotation"
                                expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
    
1.4.4.2 基于注解方式实现属性注入
  1. @AutoWired:根据属性类型进行自动装配

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

    2. 在 service 注入 dao 对象,在 service 类中添加 dao 类型属性

      public class UserService {
          @Autowired
          // 定义dao对象,不需要set方法 添加注入属性注解
          private UserDao userDao;
          public void add(){
              System.out.println("service add ... ");
              userDao.add();
          }
      }
         @Test
          public void testService() {
              ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
              UserService userService = context.getBean("userService", UserService.class);
              System.out.println(userService);
              userService.add();
          }
      com.atguiogu.spring5.service.UserService@60dcc9fe
      service add ... 
      dao add ...
      
  2. @Qualifier:根据属性名称进行注入

    1. @Qualifier 注解使用要和 @AutoWired 一起使用

      public class UserService {
          @Autowired
          @Qualifier(value = "userDaoImp1")//根据名称进行注入
          // 定义dao对象,不需要set方法 添加注入属性注解
          private UserDao userDao;
          public void add(){
              System.out.println("service add ... ");
              userDao.add();
          }
      }
      
  3. @Resource:可以根据属性类型注入,也可以根据属性名称注入

    //@Resource  //根据类型注入
    @Resource(name = "userDaoImp1")//根据名称注入
    private  UserDao userDao;
    
  4. @Value:注入普通类型属性

    @Value(value="abc")
    private String name;//普通类型属性
    
1.4.4.3 完全注解开发
  1. 创建配置类,替代 xml 配置文件

    @Configuration //作为配置类,替代 xml 配置文件
    @ComponentScan(basePackages = {"com.atguigu" })
    public class SpringConfig {
    
    }
    
  2. 编写测试类

    @Test
    public void testService02() {
        //加载配置类
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        UserService userService = context.getBean("userService", UserService.class);
        System.out.println(userService);
        userService.add();
    }
    

2 AOP

2.1 AOP 介绍

  1. AOP: 面向切面(方面)编程
  2. 利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。(不修改源代码方式,在主干功能里面添加新功能)

2.2 AOP 底层原理

  1. 底层使用 动态代理

    1. 有接口动态代理,JDK 动态代理

      创建接口实现类代理对象,增强类的方法

      image-20220430124142476

    2. 无接口动态代理,CGLIB 动态代理

      创建子类的代理对象,增强类的方法

      image-20220430124546639

2.2.1 JDK 动态代理
  1. 使用 JDK 动态代理,使用 Proxy 类里面的方法创建代理对象

    1. 调用 NewProxyInstance 方法
      1. 第一个参数: 类加载器
      2. 第二个参数:增强方法所在的类,该类实现的接口,支持多接口
      3. 第三个参数:实现该接口 InvocationHandler,创建代理对象,写增强方法
  2. JDK动态代理

    1. 创建接口,定义方法

      public interface UserDao {
          public int add(int a, int b);
          public String update(String id);
      }
      
    2. 创建接口实现类,实现方法

      public class UserDaoImpl implements UserDao {
          @Override
          public int add(int a, int b) {
              return a+b;
          }
      
          @Override
          public String update(String id) {
              return id;
          }
      }
      
    3. 使用 Proxy 类创建接口代理对象

    public class JDKProxy {
        public static void main(String[] args) {
            //创建接口实现类的代理对象 方式一
            Class[] interfaces = {UserDao.class};
    //        Proxy.newProxyInstance(JDKProxy.class.getClassLoader(),interfaces,new InvocationHandler() {
    //            @Override
    //            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    //                return null;
    //            }
    //        });
            //方式二
            UserDaoImpl userDao = new UserDaoImpl();
            UserDao dao = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
            int add = dao.add(1, 2);
            System.out.println("add="+add);
        }
    }
    //创建代理对象代码
    class UserDaoProxy implements InvocationHandler{
        //1.将创建的是谁的代理对选哪个,把谁传递过来
        //有参构造函数
        private Object obj ;
        public UserDaoProxy(Object obj) {
            this.obj = obj;
        }
        // 增强的逻辑
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //方法之前
            System.out.println("方法之前执行...."+method.getName() + ":传递的参数..." + Arrays.toString(args));
            //被增强的方法执行
            Object res = method.invoke(obj, args);
            //方法之后
            System.out.println("方法之后执行...."+obj);
            return res;
        }
    }
    
2.2.2 AOP 相关术语

image-20220623175112792

image-20220623175041660

  1. 连接点

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

  2. 切入点

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

  3. 通知(增强)

    1. 实际增强的逻辑部分称为通知(增强)

    2. 通知的类型:

      1. 前置通知
      2. 后置通知
      3. 环绕通知
      4. 异常通知
      5. 最终通知
  4. 切面

    切面是动作,即将通知应用到切入点的过程

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

    • AspectJ 不是 Spring 组成部分,独立AOP 框架,一般把 ASpectJ 和 Spring 框架一起使用,进行 AOP 操作
  2. 基于 AspectJ 实现 AOP 操作

  3. 基于 xml 配置文件实现

  4. 基于注解方式实现(使用)

  5. 在项目工程里引入 AOP 相关依赖

    image-20220501140820333

  6. 切入点表达式

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

    2. 语法结构:

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

      2. 举例1: 对com.atguigu.dao.BookDao 类里面的 add 进行增强

        execution(* com.atguigu.dao.BookDao.add(…))

        举例2: 对com.atguigu.dao.BookDao 类里面的所有方法进行增强

        execution(* com.atguigu.dao.BookDao.*(…))

        举例2: 对com.atguigu.dao 包里所有类里面的所有方法进行增强

        execution(* com.atguigu.dao.*.*(…))

2.2.4 AOP 操作 (AspectJ 注解)
  1. 创建类,在类里面定义方法

    //被增强的类
    public class User {
        public void add(){
            System.out.println("add...");
        }
    
    }
    
  2. 创建增强类 (编写增强逻辑)

    1. 在增强类中,创建方法,让不同的方法代表不同的通知类型

      //增强的类
      public class UserProxy {
          //前置通知
          public void before(){
              System.out.println("before......");
          }
      }
      
  3. 进行通知配置

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

      <?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:p="http://www.springframework.org/schema/p"
             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.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">
      
          <!--开组件扫描
              1. 扫描多个包,多个包使用逗号隔开
              <context:component-scan
                  base-package="com.atguiogu.spring5.dao,com.atguiogu.spring5.service"></context:component-scan>
              2. 扫描包的上层目录
          -->
          <context:component-scan base-package="com.atguigu.spring5.aopanno"></context:component-scan>
          
      </beans>
      
    2. 使用注解创建 User 和 UserProxy 对象

    3. 在增强类上面添加注解 @Aspect

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

      <?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:p="http://www.springframework.org/schema/p"
             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.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">
      
          <!--开组件扫描
              1. 扫描多个包,多个包使用逗号隔开
              <context:component-scan
                  base-package="com.atguiogu.spring5.dao,com.atguiogu.spring5.service"></context:component-scan>
              2. 扫描包的上层目录
          -->
          <context:component-scan base-package="com.atguigu.spring5.aopanno"></context:component-scan>
          <!--开启AspectJ生成代理对象-->
          <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
      </beans>
      
  4. 配置不同类型的通知

    1. 在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式

      @Component
      @Aspect
      //增强的类
      public class UserProxy {
          //前置通知
          @Before(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
          public void before(){
              System.out.println("before......");
          }
      
          //最终通知
         @After(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
         public void after(){
             System.out.println("after......方法执行之后执行");
         }
      
          //异常通知
          @AfterThrowing(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
          public void AfterThrowing(){
              System.out.println("AfterThrowing......");
          }
      
      
          //环绕通知
          @Around(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
          public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
              System.out.println("环绕之前......");
              //被增强的方法
              proceedingJoinPoint.proceed();
              System.out.println("环绕之后......");
          }
      
          // 后置通知 (返回通知)
          @AfterReturning(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
          public void afterReturning(){
              System.out.println("AfterReturning......返回值之后执行");
          }
      }
      
      
      
  5. 相同切入点进行抽取

    // 相同切入点抽取
    @Pointcut(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
    public void pointdemo(){
    
    }
    
  6. 有多个增强类对同一个方法进行增强,设置增强类的优先级

    1. 在增强类上添加一个注解@Order(数字类型值),数字类型值越小,优先级越高
  7. 完全注解开发

    @Test
    public void testAopAnnoEntire() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigAop.class);
        User user = context.getBean("user", User.class);
        user.add();
    }
    
    @Configuration
    @ComponentScan(basePackages = {"com.atguigu"})//开启注解扫描
    @EnableAspectJAutoProxy(proxyTargetClass = true)//开启Aspect生成代理对象
    public class ConfigAop {
    }
    
2.2.5 AOP 操作 (AspectJ 配置文件)
  1. 创建两个类,增强类和被增强类,创建方法

  2. 在 Spring 配置文件中创建两个对象

  3. 在 Spring 配置文件中配置切入点

    <?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:p="http://www.springframework.org/schema/p"
           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.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">
    
            <!--创建对象-->
        <bean id="book" class="com.atguigu.spring5.aopxml.Book"></bean>
        <bean id="bookProxy" class="com.atguigu.spring5.aopxml.BookProxy"></bean>
    
        <!--配置aop增强-->
        <aop:config>
            <!--切入点配置-->
            <aop:pointcut id="p" expression="execution(* com.atguigu.spring5.aopxml.Book.buy(..))"/>
            <!--配置切面-->
            <aop:aspect ref="bookProxy">
                    <!--增强作用在具体的方法上-->
                <aop:before method="before" pointcut-ref="p"></aop:before>
            </aop:aspect>
        </aop:config>
    </beans>
    

3 JDBCTemplate

3.1 概念和准备

  1. 什么是 JDBCTempate

    1. Spring 框架对 JDBC 进行封装,使用 JDBCTemplate 方便实现对数据库操作
  2. 准备工作

    1. 引入相关 jar 包

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

    3. 配置 JdbcTemplate 对象,注入 DataSource

    <?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:p="http://www.springframework.org/schema/p"
           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.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">
    
        <!--直接配置连接池-->
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
            <!--获取property文件内容,根据key获取,使用spring表达式获取-->
            <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
            <property name="url" value="jdbc:mysql://localhost:3306/hsp_db02"></property>
            <property name="username" value="lxj"></property>
            <property name="password" value="lxj"></property>
        </bean>
    
        <!--JdbcTempate对象-->
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
            <!--注入-->
            <property name="dataSource" ref="dataSource"></property>
        </bean>
    
    </beans>
    
    1. 创建 service、dao 类 在 dao 注入 jdbcTemplate 对象

      配置文件

      <!--开启注解扫描-->
      <context:component-scan base-package="com.atguigu.spring5"></context:component-scan>
      
      <!--直接配置连接池-->
      <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
          <!--获取property文件内容,根据key获取,使用spring表达式获取-->
          <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
          <property name="url" value="jdbc:mysql://localhost:3306/hsp_db02"></property>
          <property name="username" value="lxj"></property>
          <property name="password" value="lxj"></property>
      </bean>
      
      <!--JdbcTempate对象-->
      <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
          <!--注入-->
          <property name="dataSource" ref="dataSource"></property>
      </bean>
      

      Service

      @Service
      public class BookService {
         //注入 dao
          @Autowired
          private BookDao bookDao;
      }
      

      Dao

      @Repository
      public class BookDaoImpl implements BookDao{
          //注入jdbc Template
          @Autowired
          private JdbcTemplate jdbcTemplate;
      }
      

3.2 JDBCTemplate 操作数据库

3.2.1 DML 操作
  1. 对应数据库表创建实体类

  2. 编写 service 和 dao

    1. 在 dao 进行数据库添加操作

    2. 调用 JDBCTemplate 独享里面 update 方法实现添加操作

      @Repository
      public class BookDaoImpl implements BookDao{
          //注入jdbc Template
          @Autowired
          private JdbcTemplate jdbcTemplate;
      
          @Override
          public void add(Book book) {
              String sql = "insert into t_book values (?,?,?)";
              int update = jdbcTemplate.update(sql, book.getUserId(),book.getUsername(),book.getUstatus());
              System.out.println("update = " + update);
          }
      }
      
    3. 修改删除操作

      String sql = "insert into t_book values (?,?,?)";
      int update = jdbcTemplate.update(sql, book.getUserId(),book.getUsername(),book.getUstatus());
      System.out.println("update = " + update);
      
3.2.2 查询操作
  1. 查询表里记录数量—单值查询

    // 查询表里的记录数量
    @Override
    public void findCount() {
        String sql = "select count(*) from t_book";
        Integer queryCount = jdbcTemplate.queryForObject(sql, Integer.class);
        System.out.println("queryCount = " + queryCount);
    }
    
  2. 查询返回对象

    @Override
    public void findObject(String id) {
        String sql = "select * from t_book where userid=?";
        /**queryForObject
         * 第一个参数:SQL语句
         * 第二个参数:接口,返回不同类型没使用该接口完成数据封装
         * 第三个参数:SQL语句值
         */
        Book book = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Book>(Book.class), id);
        System.out.println("book = " + book);
    }
    
  3. 查询返回集合

    //查询返回集合
    @Override
    public void findAll() {
        String sql = "select * from t_book";
        List<Book> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Book>(Book.class));
        for (Book book : query) {
            System.out.println("book = " + book);
        }
    
    }
    
3.2.3 批量操作
  1. 批量操作:操作表里面多条记录

  2. 批量添加

    @Override
    public void batchAdd(List<Object[]> batchArgs) {
        String sql = "insert into t_book values(?,?,?)";
        /**batchUpdate(sql, batchArgs)
         * 第一个参数:SQL语句
         * 第二个参数:List集合,添加多条记录
         */
        int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
        System.out.println(Arrays.toString(ints));
    }
    
     // 批量添加
           ArrayList<Object[]> objects = new ArrayList<>();
           Object[] o1 ={"3","java","a"};
           Object[] o2 ={"4","english","b"};
           Object[] o3 ={"5","web","c"};
           objects.add(o1);
           objects.add(o2);
           objects.add(o3);
           bookService.batchAdd(objects);
    
3.2.4 事务
  1. 事务是数据操作的最基本的单元,逻辑上的一组操作,要么都成功,要么一个操作失败所有操作都失败。

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

    1. 原子性
    2. 一致性
    3. 隔离性
    4. 持久性
  3. 事务操作(搭建实务操作环境)

    1. 创建数据库和表,添加记录

    2. 创建 service,搭建 dao 完成对象创建和注入关系

      1. service 注入 dao ,在 dao 中注入 JdbcTemplate ,在 JdbcTemplate 注入DataSource 。

        @Service
        public class UserService {
            @Autowired
            private UserDao userDao;
        }
        
        
        public class UserDaoImpl implements UserDao{
            @Autowired
            private JdbcTemplate jdbcTemplate;
        }
        
        
    3. 在 Service 和 Dao 中分别创建转账方法和支付、收款方法 。

      // 转账
      public void accountMoney(){
          userDao.reduceMoney();
          userDao.addMoney();
      
      }
      
      public interface UserDao {
          public void addMoney();
          public void reduceMoney();
      
      }
      
      @Repository
      public class UserDaoImpl implements UserDao{
          @Autowired
          private JdbcTemplate jdbcTemplate;
      
          @Override
          public void addMoney() {
              String sql = "update t_account set money = money + ? where username = ?";
              int mary = jdbcTemplate.update(sql, 100, "mary");
              System.out.println("mary = " + mary);
          }
      
          @Override
          public void reduceMoney() {
                String sql = "update t_account set money = money - ? where username = ?";
                int lucy = jdbcTemplate.update(sql, 100, "lucy");
              System.out.println("lucy = " + lucy);
          }
      }
      
      
    4. 事务操作( Spring 事务管理)

      1. 事务添加到 JavaEE 三层结构的 Service 层(业务逻辑层)

      2. 在 Spring 进行事务管理操作

        • 编程式事务管理 和 声明式事务管理(推荐使用)
      3. 声明式事务管理

      4. 基于注解方式(推荐使用)

      5. 基于 xml 配置文件方式

      6. 在 Spring 进行声明式事务管理,底层使用 AOP

      7. Spring 事务管理 API

        • 提供接口,代表事务管理器,正对不同的框架提供了不同的实现类

          image-20220503191331459

    5. 声明式事务管理

      1. 在spring配置文件中配置事务管理器

        <!--创建事务管理器-->
        <bean id="transactionMananger" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <!--注入数据源-->
            <property name="dataSource" ref="dataSource"></property>
        </bean>
        
      2. 在 spring 配置文件中开启事务注解

        1. 在 Spring 配置文件 引入名称空间 tx

             xmlns:tx="http://www.springframework.org/schema/aop"
                      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
                                
          
        2. 开启事务注解

          <!--开启事务注解-->
          <tx:annotation-driven transaction-manager="transactionMananger"></tx:annotation-driven>
          
        3. 在 service 类上(或者 service 类里面方法上 )添加事务注解 @Transactional

          @Transactional //事务注解
          // 转账
          public void accountMoney() {
                  //1. 开启事务
                  //2. 进行业务操作
                  userDao.reduceMoney();
                  //模拟异常
                  int i = 100 / 0;
                  userDao.addMoney();
                  //3. 提交事务
                  //4. 事务回滚
          }
          
      3. 声明式事务管理参数配置

        1. 在 service 类或者里面方法上添加@Transactional注解中相关参数

          image-20220503194923762

          1. propagation: 事务传播行为

            多事务方法直接进行调用,该过程事务如何进行管理

            image-20220503202903709

            image-20220503202334653

          2. isolation: 事务隔离级别

            • 事务的隔离性,多事务操作之间不会产生影响,不考虑隔离性产生很多问题

            • 脏读、不可重复读、虚(幻)读

            • 脏读:一个未提交事务读取到另一个未提交事务的数据

            • 不可重复读:一个未提交的事务读取到另一个提交事务的修改数据

            • 幻读:一个未提交事务读取到另一个提交事务添加数据

            • 通过设置事务的隔离性,解决以上问题

              image-20220503205124219

          3. timeout:超时时间

            1. 事务需要在一定时间内进行提交,若不提交则回滚
            2. 默认值是-1,设置时间以秒为单位进行计算
          4. readOnly:是否只读

            1. 读: 查询操作,写:添加修改删除操作
            2. readOnly 默认值 false,表示可读,可写
            3. 设置 readOnly 置为 true,只能读
          5. rollbackFor:回滚

            1. 设置出现哪些异常进行事务回滚
          6. noRollbackFor: 不回滚

            1. 设置出现哪些异常不进行事务回滚
    6. 基于 xml 配置文件方式

      1. 配置事务管理器

      2. 配置通知

      3. 配置切入点和切面

            <!--开启注解扫描-->
            <context:component-scan base-package="com.atguigu.spring5"></context:component-scan>
        
            <!--直接配置连接池-->
            <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
                <!--获取property文件内容,根据key获取,使用spring表达式获取-->
                <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
                <property name="url" value="jdbc:mysql://localhost:3306/hsp_db02?"></property>
                <property name="username" value="lxj"></property>
                <property name="password" value="lxj"></property>
            </bean>
        
            <!--JdbcTempate对象-->
            <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
                <!--注入-->
                <property name="dataSource" ref="dataSource"></property>
            </bean>
        
            <!--1.配置事务管理器-->
            <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
                <!--注入数据源-->
                <property name="dataSource" ref="dataSource"></property>
            </bean>
        
          <!--2.配置通知-->
            <tx:advice id="txadvice">
                <!--配置事务参数-->
                <tx:attributes>
                    <!--指定哪种规则的方法上面添加事务-->
                    <tx:method name="accountMoney" propagation="REQUIRED"/>
                    <!--<tx:method name="account*" propagation="REQUIRED"></tx:method>-->
                </tx:attributes>
            </tx:advice>
        
            <!--3.配置切入点和切面-->
            <aop:config>
                <!--配置切入点-->
                <aop:pointcut id="pt" expression="execution(* com.atguigu.spring5.service.UserService.*(..))"/>
                <!--配置切面-->
                <aop:advisor advice-ref="txadvice" pointcut-ref="pt"/>
            </aop:config>
        </beans>
        
         // 转账 xml配置文件
            public void accountMoney() {
                    //1. 开启事务
                    //2. 进行业务操作
                    userDao.reduceMoney();
                    //模拟异常
                    int i = 100 / 0;
                    userDao.addMoney();
                    //3. 提交事务
                    //4. 事务回滚
            }
        
    7. 完全注解开发

      @Test
      public void test03(){
          AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TxConfig.class);
          UserService userService = context.getBean("userService", UserService.class);
          userService.accountMoneyAnno();
      }
      
      
      @Configuration //配置类
      @ComponentScan(basePackages = "com.atguigu.spring5" )//注解扫描
      @EnableTransactionManagement//开启事务
      public class TxConfig {
          //创建数据库连接池
          @Bean
          public DruidDataSource getDruidDataSource() {
              DruidDataSource dataSource = new DruidDataSource();
              dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
              dataSource.setUrl("jdbc:mysql://localhost:3306/hsp_db02");
              dataSource.setUsername("lxj");
              dataSource.setPassword("lxj");
              return dataSource;
          }
      
          // 创建JDBCTemplate 对象
          public JdbcTemplate getJdbcTemplate(DataSource dataSource) {
              // 到 ico 容器中根据数据类型找到 dataSource
              JdbcTemplate jdbcTemplate = new JdbcTemplate();
              //注入dataSource
              jdbcTemplate.setDataSource(dataSource);
              return jdbcTemplate;
          }
      
          // 创建事务管理器
          @Bean
          public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource) {
              DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
              transactionManager.setDataSource(dataSource);
              return transactionManager;
          }
      
      }
      

SpringMvc

入门案例

//UserController.java
package com.itheima.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @Author: Max_Li
 * @Date: 2022/6/27  20:16
 * @Version:
 * @Description:
 */

/**
 * 1.定义 controller
 * 2.使用 @Controller 定义Bean
 */
@Slf4j
@Controller
public class UserController {
     //2.2 设置当前操作的访问路径
    @RequestMapping("/save")
    //2.3 设置当前操作的返回值类型
    @ResponseBody
    public String save(){
        log.info("userController save()...");
        return "{'moudule':'springmvc_save'}";
    }

    @RequestMapping("/delete")
    @ResponseBody
    public String delete(){
        log.info("userController delete()...");
        return "{'moudule':'springmvc_delete'}";
    }

}

//SpringMvcConfig.java 
package com.itheima.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

/**
 * @Author: Max_Li
 * @Date: 2022/6/27  20:04
 * @Version:
 * @Description:
 */

/**
 * 创建 SpringMVC 配置文件,加载 controller 对应的 bean
 */
@Configuration
@ComponentScan({"com.itheima.controller"})
public class SpringMvcConfig {

}

//ServletContainersInitConfig.java
package com.itheima.config;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;

/**
 * @Author: Max_Li
 * @Date: 2022/6/27  20:06
 * @Version:
 * @Description:
 */

/**
 * 初始化Servlet容器,加载SpringMVC环境,并设置SpringMVC技术处理的请求
 */
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
     //加载SpringMVC容器配置
    @Override
    protected WebApplicationContext createServletApplicationContext() {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(SpringMvcConfig.class);
        return ctx;
    }
    //设置哪些请求归属SpringMVC
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
    //加载Spring容器配置
    @Override
    protected WebApplicationContext createRootApplicationContext() {
        return null;
    }
}


image-20220627205414537

image-20220627210022310

image-20220627222457318

//SpringConfig.java
package com.itheima.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;

/**
 * @Author: Max_Li
 * @Date: 2022/6/27  20:04
 * @Version:
 * @Description:
 */

/**
 * 创建 SpringMVC 配置文件,加载 controller 对应的 bean
 */
@Configuration
//@ComponentScan({"com.itheima.service","com.itheima.dao"})
@ComponentScan(value={"com.itheima"},
        excludeFilters = @ComponentScan.Filter(
                type = FilterType.ANNOTATION,
                classes = Controller.class
        )
)

public class SpringConfig {

}

//SpringMvcConfig.java
package com.itheima.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;

/**
 * @Author: Max_Li
 * @Date: 2022/6/27  20:04
 * @Version:
 * @Description:
 */

/**
 * 创建 SpringMVC 配置文件,加载 controller 对应的 bean
 */
@Configuration
@ComponentScan({"com.itheima.controller"})
public class SpringMvcConfig {

}

//ServletContainersInitConfig.java
package com.itheima.config;

import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;

/**
 * @Author: Max_Li
 * @Date: 2022/6/27  20:06
 * @Version:
 * @Description:
 */

/**
 * 初始化Servlet容器,加载SpringMVC环境,并设置SpringMVC技术处理的请求
 */
/public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
     //加载SpringMVC容器配置
    @Override
    protected WebApplicationContext createServletApplicationContext() {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(SpringMvcConfig.class);
        return ctx;
    }

    //加载Spring容器配置
    @Override
    protected WebApplicationContext createRootApplicationContext() {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(SpringConfig.class);
        return ctx;
    }

    //设置哪些请求归属SpringMVC
    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

}*/

public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMvcConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
   
}   

本人学习笔记,如有侵权请联系。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值