spring初级自学,部分内容含代码

spring

在b站观看狂神自学一个月,笔记总结

一 简介

  1. Spring框架是一个开放源代码J2EE应用程序框架,由[Rod Johnson](https://baike.baidu.com/item/Rod Johnson/1423612?fromModule=lemma_inlink)发起,是针对bean的生命周期进行管理的轻量级容器(lightweight container)。
  2. Spring解决了开发者在J2EE开发中遇到的许多常见的问题,提供了功能强大IOC、AOP及Web MVC等功能。
  3. Spring可以单独应用于构筑应用程序,也可以和Struts、Webwork、Tapestry等众多Web框架组合使用,并且可以与 Swing等桌面应用程序AP组合。因此, Spring不仅仅能应用于J2EE应用程序之中,也可以应用于桌面应用程序以及小应用程序之中。
  4. Spring框架主要由七部分组成,分别是 Spring Core、 Spring AOP、 Spring ORM、 Spring DAO、Spring Context、 Spring Web和 Spring Web MVC。
  5. 优点:
    • 开源免费的框架(容器)
    • 轻量级,非入侵式的框架
    • 控制反转(IOC)、面向切面编程(AOP)
    • 支持事务的处理、对框架整合的支持

二 IOC

  1. IOC理论推导

    程序将主动权交给用户,化主动为被动

  2. IOC本质

    • 控制反转IOC(Inversion of Control),是一种设计思想。在没有ioc的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,控制反转也就是将静态的代码转变为灵活的代码
    • 采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的
    • 控制反转是一种通过描述(XMl或注解)并通过第三方去生产或获取特定对象的方式。在spring中实现控制反转的是IOC容器,其实现方法是依赖注入(Dependency Injection,DI)
  3. IOC创建对象的方法

    • 使用无参构造创建对象,默认

      <property name="name" value="luo"/>
      
    • 有参构造创建对象

      • 下标赋值

        <constructor-arg index="0" value="com.luo"/>
        
      • 类型(不推荐使用,有局限性,相同类型出问题)

        <constructor-arg type="java.lang.String" value="luo"/>
        
      • 参数名

        <constructor-arg name="name" value="luo"/>
        

      总结:在配置文件加载的时候,容器中管理的对象就已经初始化了

三 Spring 配置

  1. 别名----alias

    <!--    别名——当id名字繁杂重复等问题,可以使用别名代替-->
        <alias name="user" alias="Users"/>
    
  2. Bean常用基础配置----bean

    <!--    id : bean的唯一标识符,相当于对象名
            class : bean对象所对应的全限名 : 包名 + 类型
            name : 别名,而且name可以同时取多个名字
    -->
        <bean id="usert" class="com.luo.pojo.User" name="usert2,u2 t1;t2"></bean>
    
  3. import

    用于团队开发,可以将多个配置文件导入合并为一个(applicationContext.cml)。

    <?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
            https://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <import resource="beans.xml"/>
        <import resource="beans_li.xml"/>
        <import resource="beans_zhang.xml"/>
    </beans>
    

四 依赖注入

  1. 构造器注入

    package com.luo.pojo;
    
    public class User {
        private String name;
    // 无参构造
    //    public User(){
    //        System.out.println("User的无参构造");
    //    }
    //有参构造
        public User(String name){
            this.name = name;
        }
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void show(){
            System.out.println("name=" + name);
        }
    }
    
    
  2. set方式注入

    • 依赖注入:set注入

      • 依赖:bean对象的创建依赖于容器
      • 注入:bean对象中的所有属性,由容器来注入
    • 项目

      • 实体类

        package com.luo.pojo;
        
        import java.util.*;
        
        public class Student {
            private String name;
            private Address address;
            private String[] books;
            private List<String> hobbys;
            private Map<String,String> card;
            private Set<String> games;
            private String wife;
            private Properties info;
        
            public String getName() {
                return name;
            }
        
            public void setName(String name) {
                this.name = name;
            }
        
            public Address getAddress() {
                return address;
            }
        
            public void setAddress(Address address) {
                this.address = address;
            }
        
            public String[] getBooks() {
                return books;
            }
        
            public void setBooks(String[] books) {
                this.books = books;
            }
        
            public List<String> getHobbys() {
                return hobbys;
            }
        
            public void setHobbys(List<String> hobbys) {
                this.hobbys = hobbys;
            }
        
            public Map<String, String> getCard() {
                return card;
            }
        
            public void setCard(Map<String, String> card) {
                this.card = card;
            }
        
            public Set<String> getGames() {
                return games;
            }
        
            public void setGames(Set<String> games) {
                this.games = games;
            }
        
            public String getWife() {
                return wife;
            }
        
            public void setWife(String wife) {
                this.wife = wife;
            }
        
            public Properties getInfo() {
                return info;
            }
        
            public void setInfo(Properties info) {
                this.info = info;
            }
        
            @Override
            public String toString() {
                return "Student{" +
                        "name='" + name + '\'' +
                        ", address=" + address.toString() +
                        ", books=" + Arrays.toString(books) +
                        ", hobbys=" + hobbys +
                        ", card=" + card +
                        ", games=" + games +
                        ", wife='" + wife + '\'' +
                        ", info=" + info +
                        '}';
            }
        }
        
        
      • 测试类

        import com.luo.pojo.Student;
        import org.springframework.context.ApplicationContext;
        import org.springframework.context.support.ClassPathXmlApplicationContext;
        
        public class MyTest {
            public static void main(String[] args) {
                ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
                Student student = (Student) context.getBean("student");
                System.out.println(student.toString();
        
            }
        }
        
        
      • bean.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
                https://www.springframework.org/schema/beans/spring-beans.xsd">
        
            <bean id="address" class="com.luo.pojo.Address">
                <property name="address" value="address"/>
            </bean>
            <bean id="student" class="com.luo.pojo.Student">
        <!--        一. 普通注入,value-->
                <property name="name" value="luo"/>
        
        <!--        二. Bean注入,ref-->
                <property name="address" ref="address"/>
                
        <!--        数组-->
                <property name="books">
                    <array>
                        <value>红楼梦</value>
                        <value>西游记</value>
                        <value>水浒传</value>
                        <value>三国演义</value>
                    </array>
                </property>
                
        <!--        List -->
                <property name="hobbys">
                    <list>
                        <value>写代码</value>
                        <value>听音乐</value>
                        <value>看电影</value>
                        <value>打游戏</value>
                    </list>
                </property>
                
        <!--        Map-->
                <property name="card">
                    <map>
                        <entry key="账号" value="xxxxx@163.com"/>
                        <entry key="密码" value="xxxxxx"/>
                    </map>
                </property>
                
        <!--        Set-->
                <property name="games">
                    <set>
                        <value>王者荣耀</value>
                        <value>qq飞车</value>
                        <value>光遇</value>
                    </set>
                </property>
                
        <!--        null-->
                <property name="wife">
                    <null/>
                </property>
                
        <!--        Property-->
                <property name="info">
                    <props>
                        <prop key="num">201927550318</prop>
                        <prop key="name">酒城</prop>
                        <prop key="gender"></prop>
                    </props>
                </property>
        
            </bean>
        
        </beans>
        
      • address.java

        package com.luo.pojo;
        
        public class Address {
            private String address;
        
            public String getAddress() {
                return address;
            }
        
            public void setAddress(String address) {
                this.address = address;
            }
        
            @Override
            public String toString() {
                return "Address{" +
                        "address='" + address + '\'' +
                        '}';
            }
        }
        
        
  3. 扩展方式注入

    官方提供了p命名空间和c命名空间进行注入

    • userbeans.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:p="http://www.springframework.org/schema/p"
             xmlns:c="http://www.springframework.org/schema/c"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
              https://www.springframework.org/schema/beans/spring-beans.xsd">
      
      <!--    p命名空间注入,可以直接注入属性的值:property-->
          <bean id="user" class="com.luo.pojo.User" p:name="luo" p:age="18"/>
      
      <!--    c命名空间注入,通过构造器注入:construct-args-->
          <bean id="user2" class="com.luo.pojo.User" c:age="19" c:name="luo" />
      </beans>
      
    • usertest.java

      import com.luo.pojo.User;
      import org.junit.Test;
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      
      public class Usertest {
          public static void main(String[] args) {
              ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
              User user = context.getBean("user",User.class);
              System.out.println(user.toString());
          }
      
          @Test
          public void test2(){
              ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
              User user2 = context.getBean("user2", User.class);
              System.out.println(user2.toString());
          }
      }
      
      
    • User.java

      package com.luo.pojo;
      
      public class User {
          private String name;
          private int age;
      
          public User() {
          }
      
          public User(String name, int age) {
              this.name = name;
              this.age = age;
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(String name) {
              this.name = name;
          }
      
          public int getAge() {
              return age;
          }
      
          public void setAge(int age) {
              this.age = age;
          }
      
          @Override
          public String toString() {
              return "User{" +
                      "name='" + name + '\'' +
                      ", age=" + age +
                      '}';
          }
      }
      
      

    注意:p命名与c命名不能直接使用,需导入xml约束。

           xmlns:p="http://www.springframework.org/schema/p"
           xmlns:c="http://www.springframework.org/schema/c"
    

五 Bean的作用域

​ 作用域:singleton、prototype、request、session、application、websocket

  1. 单例模式(Spring默认机制)
    <bean id="user2" class="com.luo.pojo.User" c:age="19" c:name="luo" scope="singleton" />

  1. 原型模式:每次从容器中get的时候,都会产生新的对象

      <bean id="user2" class="com.luo.pojo.User" c:age="19" c:name="luo" scope="prototype" />
    
  2. 其余的request、session、session、application,只能在web开发中使用

六 Bean自动装配

  • 自动装配式Spring满足bean依赖一种方式

  • Spring会在上下文自动寻找,并自动给bean装配属性

    Dog.java

    package com.luo.pojo;
    
    public class Dog {
        public void shout(){
            System.out.println("wang~");
        }
    }
    
    

    Cat.java

    package com.luo.pojo;
    
    public class Cat {
        public void shout(){
            System.out.println("miao~");
        }
    }
    
    

    people.java

    package com.luo.pojo;
    
    public class People {
        private Cat cat;
        private Dog dog;
        private String name;
    
        public Cat getCat() {
            return cat;
        }
    
        public void setCat(Cat cat) {
            this.cat = cat;
        }
    
        public Dog getDog() {
            return dog;
        }
    
        public void setDog(Dog dog) {
            this.dog = dog;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "People{" +
                    "cat=" + cat +
                    ", dog=" + dog +
                    ", name='" + name + '\'' +
                    '}';
        }
    }
    
    

    beans.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
            https://www.springframework.org/schema/beans/spring-beans.xsd">
        <bean id="cat" class="com.luo.pojo.Cat"/>
        <bean id="dog" class="com.luo.pojo.Dog"/>
    <!--    <bean id="people" class="com.luo.pojo.People">-->
    <!--        <property name="name" value="luo"/>-->
    <!--        <property name="dog" ref="dog"/>-->
    <!--        <property name="cat" ref="cat"/>-->
    <!--    </bean>-->
    
    <!--    byName: 会自动在容器上下文中查找,和自己set方法后面的值对象的beanid
            byType: 会自动在容器上下文中查找,和自己对象属性类型相同的bean (可省略id,根据class判断)
    -->
    
        <bean id="people" class="com.luo.pojo.People" autowire="byType">
            <property name="name" value="luo"/>
        </bean>
    
    </beans>
    
  1. 在spring中有三种装配方式

    • 在xml中显示配置
    • 在java中显示配置
    • 隐式的自动装配bean
  2. ByName自动装配

    <!--    byName: 会自动在容器上下文中查找,和自己set方法后面的值对象的beanid-->
        <bean id="people" class="com.luo.pojo.People" autowire="byName">
            <property name="name" value="luo"/>
        </bean>
    
  3. ByType自动装配

    <!--        byType: 会自动在容器上下文中查找,和自己对象属性类型相同的bean (可省略id,根据class判断)
    -->
        <bean class="com.luo.pojo.Cat"/>
        <bean class="com.luo.pojo.Dog"/>
        <bean id="people" class="com.luo.pojo.People" autowire="byType">
            <property name="name" value="luo"/>
        </bean>
    
  4. 小结:

    • byname,需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的set方法保持一致
    • bytype,需要保证所有的bean的class唯一,并且这个bean需要和自动注入的属性类型一致
  5. 使用注解实现自动装配

    1. 条件:

      • 导入约束:context约束
      • 配置注解的支持:context:annotation-config/
      <?xml version="1.0" encoding="UTF-8"?>
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xml:context="http://www.springframework.org/schema/context"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
              https://www.springframework.org/schema/beans/spring-beans.xsd
              http://www.springframework.org/schema/context
              https://www.springframework.org/schema/beans/spring-conext.xsd"
      >
          <!--开启注解自动装配    -->
          <context:annotation-config/>
      
    2. @Autowired

      • 直接在属性上使用,也可以在set方法上使用

      • 使用Autowired后,可以不用编写set方法,前提是这个自动装配的属性在IOC(Spring)容器中存在,且符合名字byname/bytype

      • 科普

        @Nullable 字段标记了这个注解,说明这个字段可以为null
        
        public @interface Autowired{
            boolean required() default true;
        }
        
        public class People{
            //如果显示定义了Autowired的required属性为false,说明这个对象可以为null,否则不允许为空
            @Autowired(required = false)
            private Cat cat;
            @Autowired
            private Dog dog;
            private String name;
        }
        

        如果@Autowired自动装配环境复杂,自动装配无法通过一个注解【@Autowired】完成的时候,可以使用【@Qualifier(value=“xxx”)】去配置@Autowired的使用,指定一个唯一的bean对象注入

    3. @Resource注解

      public class People{
          @Resource(name = "xxx")
          private Cat cat ;
          @Resource
          private Dog dog ;
          
      }
      

      小结:

      @Autowired 与@Resource 的区别:

      • @Autowired 通过spring,@Resource通过java (java11后被@Autowired取代)
      • @Autowired 首先通过bytype的方式实现,其次byname
      • @Resource 默认通过byname的方式实现,如果找不到名字,则通过bytype实现。(特殊:指定id或指定id和type)如果四个情况都找不到,则报错

    七 使用注解开发

    1. bean

    2. 属性如何注入(属性/set方法)

      package com.luo.pojo;
      
      import org.springframework.beans.factory.annotation.Value;
      import org.springframework.stereotype.Component;
      
      //@Component 等价于 <bean id="user" class="com.luo.pojo.User"/>
      @Component
      public class User {
      //    public String name = "luo";
          //相当于<property name="name" value="luo"/>
      //    @Value("luo")
          public String name;
          @Value("luo")
          public void setName(String name) {
              this.name = name;
          }
      }
      
      
    3. 衍生的注解

      @Component 有几个衍生注解,我们在web开发中,会按照mvc三层架构分层

      • dao【@Repository】

      • service【@Service】

      • controller【@Controller】

        这四个注解功能是一样的,都代表将某个类注册到Spring中,装配Bean

    4. 自动装配

      - @Autowired : 自动装配,默认类型其次id,如果Autowired不能唯一自动装配属性
        ,则需要通过@Qualifier(value="xxx")
      - @Nullable  : 字段标记了这个注解,说明这个字段可以为null
      - @Resource  : 自动装配,默认id其次类型
      
    5. 作用域

      与上面bean作用域类似一个写在xml文件一个写在java文件中

      @Scope(“prototyper”)

    6. 小结

      xml与注解:

      • xml更加万能,适用于任何场景,维护简单方便
      • 注解 不是自己类使用不了,有局限性,维护相对复杂

      xml与注解最佳实践:

      • xml用来管理bean

      • 注解只负责完成属性的注入

      • 在使用的过程中要注意:必须让注解注解生效,就要开启注解支持

            <!--指定要扫描的包,这个包下的注解就会生效    -->
            <context:component-scan base-package="com.luo"/>
            <context:annotation-config/>
        

八 JavaConfig配置

不使用Spring的xml配置,全权交给java

JavaConfig是Spring的一个子项目,在Spring4之后,它成为了一个核心功能

User.java(实体类)

package com.luo.pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class User {
    private String name;

    public String getName() {
        return name;
    }

    @Value("luo")
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}

LuoConfig.java(配置类)

package com.luo.config;

import com.luo.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

//这个也会被Spring容器托管,注册到容器中,因为他本身就是一个@Component
//@Configuration代表这是一个配置类,就和我们之前看的beans.xml
@Configuration
//@ComponentScan 代表包扫描与xml中的类似
@ComponentScan("com.luo.pojo")
//Import : 导入多个配置文件
@Import(LuoConfigt.class)
public class LuoConfig {

    //注册一个bean,相当于xml中的bean标签
    //这个方法的名字,相当于bean标签的id属性
    //这个方法的返回值,相当于bean标签的class属性
    @Bean
    public User getUser(){
        return new User(); //返回要注入到bean的对象
    }
}

LuoConfigt.java(配置类)

package com.luo.config;

import com.luo.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

//这个也会被Spring容器托管,注册到容器中,因为他本身就是一个@Component
//@Configuration代表这是一个配置类,就和我们之前看的beans.xml
@Configuration
//@ComponentScan 代表包扫描与xml中的类似
@ComponentScan("com.luo.pojo")
public class LuoConfigt {

    //注册一个bean,相当于xml中的bean标签
    //这个方法的名字,相当于bean标签的id属性
    //这个方法的返回值,相当于bean标签的class属性
    @Bean
    public User getUser(){
        return new User(); //返回要注入到bean的对象
    }
}

MyTest.java(测试类)

import com.luo.config.LuoConfig;
import com.luo.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;


public class MyTest {
    public static void main(String[] args) {
        //如果完全使用了配置类,那么只能通过AnnotationConfig上下文获取容器,通过配置类的class对象加载
        ApplicationContext context = new AnnotationConfigApplicationContext(LuoConfig.class);
        User getUser = (User) context.getBean("getUser");
        System.out.println(getUser.getName());
    }
}

九 代理模式

代理模式是SpringAOP的底层

代理模式分为:

  • 静态代理
  • 动态代理
  1. 静态代理
    • 角色分析
      • 抽象角色:一般会使用接口或抽象类
      • 真实角色:被代理的角色
      • 代理角色:代理真实角色,代理真实角色后,做附属操作
      • 客户:访问代理对象的人

代理模式的好处:

  • 真实业务由真实角色做,公共业务由代理角色做
  • 公共业务就交给代理角色,实现业务的分工
  • 公共业务发生扩展的时候,方便集中管理

代码步骤:

  1. 接口

    package com.luo.demo01;
    
    public interface Rent {
        public void rent();
    }
    
  2. 真实角色

    package com.luo.demo01;
    
    public class Host implements Rent {
        @Override
        public void rent() {
            System.out.println("房东出租房子");
        }
    
    }
    
    
  3. 代理角色

    package com.luo.demo01;
    
    public class Proxy {
        private Host host;
    
        public Proxy(){
    
        }
    
        public Proxy(Host host){
            this.host= host;
        }
    
        public void rent(){
            host.rent();
        }
    
        public void seeHouse(){
            System.out.println("中介带你看房");
        }
    
        public void heTong(){
            System.out.println("代签合同");
        }
    }
    
    
  4. 客户端访问代理角色

    package com.luo.demo01;
    
    public class Client {
        public static void main(String[] args) {
            Host host = new Host();
    //        host.rent();
            Proxy proxy = new Proxy(host);
            proxy.rent();
            proxy.seeHouse();
        }
    }
    
    

代理模式的缺点:

  • 一个真实角色会只产生一个代理角色;代码量翻倍,开发效率低

扩展深度理解:

在不修改源代码的基础上增加新的功能。

在程序开发中一般都是纵向开发,当我们程序上线后,客户要增加一个新的功能,这时候我们需要在不改动dao层的情况下对service层进行纵向开发也就是Aop。

代码演示:

UserService.java

package com.luo.demo02;

public interface UserService {
    public void add();
    public void delete();
    public void update();
    public void query();
}

UserServiceImpl.java

package com.luo.demo02;

//真实对象
public class UserServiceImpl implements UserService {

    @Override
    public void add() {
        System.out.println("增加用户");
    }

    @Override
    public void delete() {
        System.out.println("删除用户");
    }

    @Override
    public void update() {
        System.out.println("修改用户");
    }

    @Override
    public void query() {
        System.out.println("查询用户");
    }
}

UserServiceProxy.java

package com.luo.demo02;

public class UserServiceProxy implements UserService{
    private UserServiceImpl userService;

    public void setUserService(UserServiceImpl userService) {
        this.userService = userService;
    }

    @Override
    public void add() {
        log("add");
        userService.add();
    }

    @Override
    public void delete() {
        log("delete");
        userService.delete();
    }

    @Override
    public void update() {
        log("update");
        userService.update();
    }

    @Override
    public void query() {
        log("query");
        userService.query();
    }

    //日志方法
    public void log(String msg){
        System.out.println("使用了"+ msg + "方法");
    }
}

Client.java

package com.luo.demo02;

public class Client {
    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();
        UserServiceProxy userServiceProxy = new UserServiceProxy();
        userServiceProxy.setUserService(userService);
        userServiceProxy.add();
    }
}

动态代理

  • 动态代理和静态代理角色一样
  • 动态代理的代理是动态生成的
  • 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
    • 基于接口----JDK动态代理
    • 基于类-----cglib
    • java字节码----javasist

常用两个类:Proxy,InvocationHandler

十 Aop

  1. Aop在Spring中的作用:提供声明式事务,允许用户自定义切面

  2. 依赖包

        <dependencies>
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>1.9.4</version>
            </dependency>
        </dependencies>
    
  3. 实现方法

    1. 使用Spring API接口【主切点】

          <aop:config>
              <!--切入点:expression:表达式,execution(要执行的位置 * * * * *)-->
              <aop:pointcut id="pointcut" expression="execution(* com.luo.service.UserServiceImp.*(..))"/>
      
              <!--执行环绕增加-->
              <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
              <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
      
          </aop:config>
      
    2. 自定义类实现【主切面】

          <aop:config>
              <!-- 自定义切面,ref 要引用的类-->
              <aop:aspect ref="diy">
                  <!--切入点-->
                  <aop:pointcut id="point" expression="execution(* com.luo.service.UserServiceImp.*(..))"/>
                  <!--通知 -->
                  <aop:before method="before" pointcut-ref="point"/>
                  <aop:after method="after" pointcut-ref="point"/>
              </aop:aspect>
                  <!--方式三:注解    -->
          <bean id="annotationPointCut" class="com.luo.anno.AnnotationPointCut"/>
          <!--开启注解支持   JDK(默认 proxy-target-class="false")    cglib(proxy-target-class="true") -->
          <aop:aspectj-autoproxy proxy-target-class="false"/>
          </aop:config>
      
    3. 注解实现aop

    4. 测试

      Log.java

      package com.luo.log;
      
      import org.springframework.aop.MethodBeforeAdvice;
      
      import java.lang.reflect.Method;
      
      public class Log implements MethodBeforeAdvice {
          // method:要执行的目标对象的方法
          //object:参数
          //target:目标对象
          @Override
          public void before(Method method, Object[] args, Object target) throws Throwable {
              System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了");
          }
      }
      

      AfterLog.java

      package com.luo.log;
      
      import org.springframework.aop.AfterReturningAdvice;
      
      import java.lang.reflect.Method;
      
      public class AfterLog implements AfterReturningAdvice {
          @Override
          //returnValue:返回值
          public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
              System.out.println("执行了"+method.getName()+"方法,返回结果为:"+returnValue);
          }
      }
      

      UserService.java

      package com.luo.service;
      
      public interface UserService {
          public void add();
          public void delete();
          public void update();
          public void query();
      }
      

      UserServiceImp.java

      package com.luo.service;
      
      public class UserServiceImp implements UserService{
          @Override
          public void add() {
              System.out.println("增加用户");
          }
      
          @Override
          public void delete() {
              System.out.println("删除用户");
          }
      
          @Override
          public void update() {
              System.out.println("修改用户");
          }
      
          @Override
          public void query() {
              System.out.println("查找用户");
          }
      }
      

      DiyPointCut.java

      package com.luo.diy;
      
      public class DiyPointCut {
          public void before(){
              System.out.println("方法前");
          }
      
          public void after(){
              System.out.println("方法后");
          }
      }
      

      AnnotationPointCut.java

      package com.luo.anno;
      
      //使用注解实现aop
      
      import org.aspectj.lang.ProceedingJoinPoint;
      import org.aspectj.lang.Signature;
      import org.aspectj.lang.annotation.After;
      import org.aspectj.lang.annotation.Around;
      import org.aspectj.lang.annotation.Aspect;
      import org.aspectj.lang.annotation.Before;
      
      @Aspect //标注这个类是一个切面
      public class AnnotationPointCut {
          @Before("execution(* com.luo.service.UserServiceImp.*(..))")
          public void before(){
              System.out.println("方法前");
          }
          @After("execution(* com.luo.service.UserServiceImp.*(..))")
          public void after(){
              System.out.println("方法后");
          }
      
          @Around("execution(* com.luo.service.UserServiceImp.*(..))")
          public void around(ProceedingJoinPoint jp) throws Throwable {
              System.out.println("环绕前");
      
              Signature signature = jp.getSignature();// 获得签名
              System.out.println("signature:" + signature);
      
              //执行方法
              Object proceed = jp.proceed();
              System.out.println("环绕后");
      
              System.out.println(proceed);
          }
      }
      
      

      MyTest.java

      import com.luo.diy.DiyPointCut;
      import com.luo.service.UserService;
      import com.luo.service.UserServiceImp;
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      
      public class MyTest {
          public static void main(String[] args) {
              ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
              UserService userService = (UserService) context.getBean("userService");
              userService.add();
          }
      }
      

      applicationContext.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:aop="http://www.springframework.org/schema/aop"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
              https://www.springframework.org/schema/beans/spring-beans.xsd
              http://www.springframework.org/schema/aop
              https://www.springframework.org/schema/aop/spring-aop.xsd
      ">
      
      
          <!--注册bean-->
          <bean id="userService" class="com.luo.service.UserServiceImp"/>
          <bean id="log" class="com.luo.log.Log"/>
          <bean id="afterLog" class="com.luo.log.AfterLog"/>
      
          <!--方式一:使用原生Spring API接口-->
          <!--配置aop:导入aop约束-->
      <!--    <aop:config>-->
      <!--        &lt;!&ndash;切入点:expression:表达式,execution(要执行的位置 * * * * *)&ndash;&gt;-->
      <!--        <aop:pointcut id="pointcut" expression="execution(* com.luo.service.UserServiceImp.*(..))"/>-->
      
      <!--        &lt;!&ndash;执行环绕增加&ndash;&gt;-->
      <!--        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>-->
      <!--        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>-->
      
      <!--    </aop:config>-->
      
          <!--方式二:自定义类-->
          <bean id="diy" class="com.luo.diy.DiyPointCut"/>
      
          <aop:config>
              <!-- 自定义切面,ref 要引用的类-->
              <aop:aspect ref="diy">
                  <!--切入点-->
                  <aop:pointcut id="point" expression="execution(* com.luo.service.UserServiceImp.*(..))"/>
                  <!--通知 -->
                  <aop:before method="before" pointcut-ref="point"/>
                  <aop:after method="after" pointcut-ref="point"/>
              </aop:aspect>
          </aop:config>
      
      </beans>
      

十一 mybatis-spring

  1. 编写数据源配置

  2. sqlSessionFactory

  3. sqlSessionTemplate

  4. 给接口加实现类

  5. 注入spring

    • spring-dao.xml (spring_10_mybatis工程)

      <?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:aop="http://www.springframework.org/schema/aop"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
              https://www.springframework.org/schema/beans/spring-beans.xsd
              http://www.springframework.org/schema/aop
              https://www.springframework.org/schema/aop/spring-aop.xsd
      ">
          <!--DataSource:使用spring的数据源替换mybatis的配置    -->
          <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
              <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
              <property name="url" value="jdbc:mysql://localhost:3306/fund?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
      <!--        <property name="url" value="jdbc:mysql://localhost:3306/fund?useSSL=ture"/>-->
              <property name="username" value="root"/>
              <property name="password" value="luo3306.J"/>
          </bean>
      
          <!-- sqlSessionFactory   -->
          <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
              <property name="dataSource" ref="dataSource"/>
              <!-- 绑定mabatis配置文件       -->
              <property name="configLocation" value="classpath:mybatis-config.xml"/>
              <property name="mapperLocations" value="classpath:/com/luo/mapper/*.xml"/>
          </bean>
          <!--  SqlSessionTemplate:就是sqlSession  -->
          <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
              <!--  只能使用构造器注入sqlSessionFactory,因为没有set方法      -->
              <constructor-arg index="0" ref="sqlSessionFactory"/>
          </bean>
      
          <bean id="userMapper" class="com.luo.mapper.UserMapperImpl">
              <property name="sqlSession" ref="sqlSession"/>
          </bean>
      </beans>
      

十二 声明式事务

  1. 事务

    • 把一组业务当成一个业务来做,要么都成功,要么都失败;
    • 事务在项目开发中,十分重要,涉及到数据的一致性
    • 确保完整性和一致性
  2. 事务ACID原则:

    • 原子性
    • 一致性
    • 隔离性
      • 多个业务可能操作同一资源,防止数据损坏
    • 持久性
      • 事务一旦提交,无论系统发生什么问题,结果都不会被影响。
  3. spring中的事务管理

    • 声明式事务:AOP
    • 编程式事务:需要在代码中进行事务管理
  4. spring中7种Propagation类的事务属性详解

    • REQUIRED(required) : 支持当前事务,如果当前没有事务,就新建一个事务。(常用)
    • SUPPORTS(supports) : 支持当前事务,如果当前没有事务,就以非事务方式执行
    • MANDATORY(mandatory) : 支持当前事务,如果当前没有事务,就抛出异常
    • REQUIRES_NEW(requires_new) : 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
    • NEVER(never) : 以非事务方式执行,如果当前存在事务,则抛出异常
    • NESTED(nested) : 支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务
  5. 实例

    UserMapper.java

    package com.luo.mapper;
    
    import com.luo.pojo.User;
    
    import java.util.List;
    
    public interface UserMapper {
        public List<User> selectUser();
    
        //添加数据
        public int addFound(User user);
    //    //删除数据
        public int deleteFound(int id);
    }
    
    

    UserMapper.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.luo.mapper.UserMapper">
        <select id="selectUser" resultType="user">
            <!--   fund.web 这是数据库     -->
            select * from fund.web;
        </select>
    
        <insert id="addFound" parameterType="user">
            insert into fund.web(id,name,pwd) values(#{id},#{name},#{pwd});
        </insert>
    
        <delete id="deleteFound" parameterType="int">
            delete from fund.web where id=#{id}
        </delete>
    
    </mapper>
    

    UserMapperImpl.java

    package com.luo.mapper;
    
    import com.luo.pojo.User;
    import org.mybatis.spring.support.SqlSessionDaoSupport;
    
    import java.util.List;
    
    public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper{
    
        @Override
        public List<User> selectUser() {
    
            User user = new User(5, "小罗", "xiaoluo");
    
            UserMapper mapper = getSqlSession().getMapper(UserMapper.class);
    
            mapper.addFound(user);
            mapper.deleteFound(4);
            return mapper.selectUser();
        }
    
        @Override
        public int addFound(User user) {
            return getSqlSession().getMapper(UserMapper.class).addFound(user);
        }
    
        @Override
        public int deleteFound(int id) {
            return getSqlSession().getMapper(UserMapper.class).deleteFound(id);
        }
    }
    
    

    User.java

    package com.luo.pojo;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class User {
        private int id ;
        private String name;
        private String pwd;}
    
    

    applicationContext.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
            https://www.springframework.org/schema/beans/spring-beans.xsd
    ">
        <import resource="spring-dao.xml"/>
    
        <bean id="userMapper" class="com.luo.mapper.UserMapperImpl">
            <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
        </bean>
    </beans>
    

    mybatis-config.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
    
        <typeAliases>
            <package name="com.luo.pojo"/>
        </typeAliases>
    
    </configuration>
    

    spring-dao.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:tx="http://www.springframework.org/schema/tx"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
            https://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/tx
            https://www.springframework.org/schema/tx/spring-tx.xsd
            http://www.springframework.org/schema/aop
            https://www.springframework.org/schema/aop/spring-aop.xsd
    ">
        <!--DataSource:使用spring的数据源替换mybatis的配置    -->
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/fund?useSSL=false&amp;useUnicode=true&amp;characterEncoding=UTF-8"/>
            <property name="username" value="root"/>
            <property name="password" value="luo3306.J"/>
        </bean>
    
        <!-- sqlSessionFactory   -->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"/>
            <!-- 绑定mabatis配置文件       -->
            <property name="configLocation" value="classpath:mybatis-config.xml"/>
            <property name="mapperLocations" value="classpath:/com/luo/mapper/*.xml"/>
        </bean>
        <!--  SqlSessionTemplate:就是sqlSession  -->
        <bean id="userMapper" class="org.mybatis.spring.">
            <!--  只能使用构造器注入sqlSessionFactory,因为没有set方法      -->
            <constructor-arg index="0" ref="sqlSessionFactory"/>
        </bean>
    
        <!-- 配置声明式事务   -->
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"/>
        </bean>
    
        <!-- 结合AOP实现事务织入   -->
        <!--  配置事务通知  -->
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
            <!-- 给方法配置事务       -->
            <!-- 配置事务的传播特性:new    -->
            <tx:attributes>
                <tx:method name="add" propagation="REQUIRED"/>
                <tx:method name="delete" propagation="REQUIRED"/>
                <tx:method name="update" propagation="REQUIRED"/>
                <tx:method name="query" read-only="true"/>
                <tx:method name="*" propagation="REQUIRED"/>
            </tx:attributes>
        </tx:advice>
    
        <!-- 配置事务切入   -->
        <aop:config>
            <aop:pointcut id="txPointCut" expression="execution(* com.luo.mapper.*.*(..))"/>
            <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
        </aop:config>
    </beans>
    

    MyTest.java

    import com.luo.mapper.UserMapper;
    import com.luo.pojo.User;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    import java.util.List;
    
    public class MyTest {
        public static void main(String[] args) {
            ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
            UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
    //        for (User user : userMapper.selectUser()) {
    //            System.out.println(user);
    //        }
            List<User> users = userMapper.selectUser();
            for (User user:users) {
                System.out.println(user);
            }
        }
    }
    
    

    pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>kuangshen-spring</artifactId>
            <groupId>org.spring</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>spring_11_transaction</artifactId>
    
        <properties>
            <maven.compiler.source>8</maven.compiler.source>
            <maven.compiler.target>8</maven.compiler.target>
        </properties>
        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.20</version>
            </dependency>
    
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.5.2</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>5.3.19</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jdbc</artifactId>
                <version>5.3.19</version>
            </dependency>
    
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>1.9.4</version>
            </dependency>
    
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis-spring</artifactId>
                <version>2.0.2</version>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>1.16.10</version>
            </dependency>
    
        </dependencies>
    
        <build>
            <resources>
                <resource>
                    <directory>src/main/java</directory>
                    <includes>
                        <include>**/*.xml</include>
                    </includes>
                    <filtering>true</filtering>
                </resource>
            </resources>
        </build>
    
    </project>
    

    测试结果

    User(id=1, name=李辰, pwd=lichen001)
    User(id=2, name=罗天宇, pwd=luotianyu002)
    User(id=3, name=会飞的鱼, pwd=huifeideyu003)
    User(id=5, name=小罗, pwd=xiaoluo)
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值