栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

狂神说spring学习笔记(自用)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

狂神说spring学习笔记(自用)

1、Spring 1.1、简介

2002年:首次推出Spring框架雏形interface21框架

2004年发布了1.0正式版

Spring理念:是现有的技术更加容易使用,整和了现有技术框架

SSH: Struct2+Spring+Hibernate!

SSM: SpringMVC+Spring +MyBatis

1.2、优点
  • Spring是一个开源的免费框架
  • Spring是一个轻量级的、非入侵式的框架
  • 控制反转(IOC),面向切面编程(AOP)
  • 支持事务处理,对框架整合的支持!

总结:Spring就是一个轻量级的控制反转和面向切面编程放入框架

1.3、组成

1.4、拓展

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sxDLEwcC-1638844571626)(C:UserszhangyingyingAppDataRoamingTyporatypora-user-imagesimage-20210929150624489.png)]

  • Springboot
    • 一个快速开发的脚手架
    • 基于SpringBoot可以快速的开发单个微服务
    • 约定大于配置
  • Springcloud
    • SpringCloud是基于SpringBoot实现的。

因为现在大多数公司都在使用SpringBoot进行开发,学习SpringBoot的前提,需要完全掌握Spring及SpringMVC!

弊端:发展太久,配置十分繁琐

2、IOC理论推导
  1. UserDao接口
  2. UserDaoImpl实现类(SQL语句实现和数据库的数据交互)
  3. UserSerivce业务接口
  4. UserServiceImpl业务实现类
public void setUserDao(UserDao userDao) {
    this.userDao = userDao;
}
  • 之前,程序是主动创建对象,控制权在程序员手上
  • 使用set注入后,程序不再具有主动性,而是变成了被动的接受对象

​ 这种思想从本质上解决了问题,程序员不用再管理对象的创建了系统耦合性大大降低,可以更加专注在业务的实现上,这是IOC的原型!

控制反转是一种设计思想,DI是实现IOC的一种方法,也有人认为DI(依赖注入)是IOC的另一种说法。没有IOC的程序中,我们使用面向对象编程,对象间的依赖关系没有硬编码在程序中,对象的创建由程序控制,控制反转后将对象的创建转移给三方,个人认为所谓控制反转就是获得依赖对象的方式反转了

采用XML方式配置Bean的时候Bean的定义信息是和现实分离的,而采用注解的方式可以直接把二者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的问题

控制反转是一种通过描述(XML或注解)并通过第三方去生产获取对象方式。在Spring中实现控制反转的是IOC容器,其实现方法是依赖注入

3、HelloSpring

pojo:Hello.java

package com.Zhang.pojo;

public class Hello {

    private String hello;

    public String getHello() {
        return hello;
    }

    public void setHello(String hello) {
        this.hello = hello;
    }

    @Override
    public String toString() {
        return "Hello{" +
                "hello='" + hello + ''' +
                '}';
    }
}

bean.xml




    
    
        
        
    

Test

import com.Zhang.pojo.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        //使用ApplicationContext context = new ClassPathXmlApplicationContext("spring注入配置文件");
        //Hello hello = context.getBean("对象id",对象id.class);获取对象,效果等同于之前的Hello hello = new Hello();
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        Hello hello = (Hello) context.getBean("hello");
        System.out.println(hello.getHello());
    }

}

​ Hello类在bean中配置对应的属性和值,将这个类交给Spring托管,在Test中要创建Hello类的对象使用ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");来创建

使用Hello hello = (Hello) context.getBean("hello");来获取对象。

然后使用对象的get和set方法对对象属性进行取值和赋值。

hello对象的属性值是由Spring容器设置,这个过程就叫控制反转:

控制:谁来控制对象的创建,传统应用程序的对象是由程序本身控制创建的,使用Spring后,对象是由Spring来创建的。

反转:程序本身不创建对象。变成被动的接受对象

依赖注入:就是利用set方法进行注入的

IOC是一种编程思想。由主动的编程变成被动的接收

可以通过ClassPathXmlApplicationContext去浏览一下底层源码

4、IOC创建对象的方式
  1. 使用无参构造创建对象,默认

  2. 假设我们要使用有参构造创建对象

  3. 个人认为通过参数名设置代码更有可读性,但现实中下标赋值使用更多

    1. 下标赋值

      
          
      
      
    2. 类型

      
          
      
      
    3. 参数名

      
          
      
      

在test文件中没有接受和创建UserTwo对象,但仍然执行了UserTwo的无参构造方法,说明对象在托管给Spring的加载配置文件xml的时候就已经初始化

在配置文件加载的时候,容器的对象就已经被初始化,以后取出的对象就是同一个对象,内存中只有这一个

5、Spring配置 5.1、别名

    
    
    


5.2、Bean的配置

    

5.3、import

​ 一般用于团队开发使用,它可以使用多个配置文件,导入合并为一个

假设,现在项目中有多个人开发,这三个人负责不同的开发,不同的人有不同的类,需要注册在不同的bean中。我们可以利用import将所有人的beans.xml合并为一个总的!

使用的时候直接使用总配置就可以了

applicationContest.xml中配置,就可以把这三个配置文件合并到applicationContest.xml中




6、DI依赖注入 6.1、构造器注入 6.2、Set方式注入
  • 依赖注入:Set注入

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

    环境搭建

    1. 复杂类型

      package com.company.pojo;
      
      public class Address {
          private String address;
          
          //属性address的get方法
          public String getAddress() {
              return address;
          }
      
          //属性address的set方法
          public void setAddress(String address) {
              this.address = address;
          }
          
      }
      
    2. 真实测试对象

      package com.company.pojo;
      
      import java.util.*;
      
      public class Student {
          //String类型的
          private String name;
          //对象类型的
          private Address address;
          //数组类型的
          private String[] book;
          //List类型的
          private List hobbys;
          //Map类型的
          private Map card;
          //Set类型的
          private Set games;
          //Properties类型的
          private Properties info;
      
          //所有属性的get和set方法
          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[] getBook() {
              return book;
          }
      
          public void setBook(String[] book) {
              this.book = book;
          }
      
          public List getHobbys() {
              return hobbys;
          }
      
          public void setHobbys(List hobbys) {
              this.hobbys = hobbys;
          }
      
          public Map getCard() {
              return card;
          }
      
          public void setCard(Map card) {
              this.card = card;
          }
      
          public Set getGames() {
              return games;
          }
      
          public void setGames(Set games) {
              this.games = games;
          }
      
          public Properties getInfo() {
              return info;
          }
      
          public void setInfo(Properties info) {
              this.info = info;
          }
          
          //重写toString方法
          @Override
          public String toString() {
              return "Student{" +
                      "name='" + name + ''' +
                      ", address=" + address +
                      ", book=" + Arrays.toString(book) +
                      ", hobbys=" + hobbys +
                      ", card=" + card +
                      ", games=" + games +
                      ", info=" + info +
                      '}';
          }
      }
      
    3. beans.xml

      
      
          
          
              
              
      
              
              
              
              
              
                  
                      红楼梦
                      西游记
                      三国演义
                      水浒传
                      如梦令
                  
              
      
              
              
                  
                      篮球
                      听歌
                      看电影
                      敲代码
                  
              
      
              
              
                  
                      
                      
                  
              
      
              
              
                  
                      LOL
                      COC
                      BOB
                  
              
      
              
              
                  
                  
              
      
              
              
                  
                      小明
                      03012315
                      
                  
              
          
          
      
      

      其中所有的都用的是value,只有Address在赋值的时候用的ref引用,ref引用的是Bean注册Address时设置的id

    4. 测试类

      import com.company.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());
          }
      }
      
6.3、拓展方式注入(p命名空间和c命名空间)

p命名空间



    
    
    

c命名空间



    
    

测试:

@Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("userbeans.xml");
        User user = (User) context.getBean("users");
        User user = (User) context.getBean("user");
        System.out.println(user);
    }

注意:c命名空间和p命名空间不能直接使用,需要导入xml约束

xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
6.4、Bean的作用域

1、单例模式 :Spring默认机制,只产生一个对象,每次调用都调用的该对象


2、原型模式:每次从容器中get的时候,都会产生一个新对象!


singleton和prototype,不能同时使用,同一个实体类只能设置一个

3、其余的request、session、application、这些只能在web开发中使用到!

7、Bean的自动装配
  • 自动装配:是Spring满足bean依赖一种方式!
  • Spring会在上下文中自动寻找,并自动给bean装配属性!

在Spring 中有三种装配方式

  1. 在xml中显示的配置
  2. 在java中显示配置
  3. 隐式的装配bean [重要]
7.1、测试

​ 环境搭建:一个人有两个宠物

7.2、ByName自动装配





    


7.3、ByType





    

小结:

  • 在byName的时候,需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一致!
  • byType:需要保证所有bean的class唯一,并且这个bean需要和自动注入的属性的类型一致!使用byType的时候xml配置文件中可以不使用id标注类
7.4、使用注解实现自动装配

jdk1.5支持的注解,Spring2.5开始支持注解

The introduction of annotation-based configuration raised the question of whether this approach is “better” than XML.

要使用注解:

  1. 导入约束,context约束

  2. 配置注解的支持, context:annotation-config/

    
    
    
        
        
        
        
        
    
    
    

@Autowired

直接在属性上使用即可!也可以在set方法上使用!

使用Autowired我们可以不用编写Set方法了,前提是自动装配属性在IOC中存在,且符合名字byName!

科普:

@Nullable  字段标记了这个注解,说明这个字段可以为null
//如果显示定义了Autowired的required属性值为false,说明这个对象可以为null,否则不允许为空
@Autowrired(required = false)
private Cat cat;

测试

public class People {
    @Autowired(required = false)
    private Cat cat;
    @Autowired
    private Dog dog;

    private String name;
}

如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解完成的时候,我们可以使用@Qualifier(value=“xxx”)去配置@Autowired的使用

如果配置文件中出现同一个类的属性有多个id, 如下。通过设置autowire = byName或byType都无法实现自动装配。

    
    
    
    
    
     

	
    
    
    
    
    
    

这个时候如果还想实现自动装配,可以将@Autowired和@Qualifier(value=“xxx”)一起使用指定xml文件中特定的一个bean id

public class People {
    @Autowired
    private Cat cat;
    @Autowired
    @Qualifier(value="Dog2")//指定Dog2实现自动装配
    private Dog dog;
    private String name;
}

@Resource java自带注解,也可以实现自动装配,首先会通过id匹配对应属性,如果不能进行自动装配,则自动采用匹配类型进行自动装配。如果二者都不可匹配,则可以定义唯一的xml文件中的bean id进行对应信息的匹配进行自动装配

@Resource(name="cat1")
private Cat cat;

@Resource
private Dog dog;

小结:

@Resource和@Autowired区别

  1. 都是用来自动装配的,都可以放在属性字段上
  2. @Autowired通过byType的方式实现,且必须要求这个对象存在!
  3. @Resouce默认通过byName的方式实现,如果找不到名字,则通过byType实现!如果这两个都找不到就报错
  4. 执行顺序不同:@Autowire通过byType的方式实现。@Resource默认通过byName实现。
8、Spring使用注解的开发

在Spring4之后,要使用注解开发,必须保证aop的包导入了

使用注解需要导入context约束,增加注解的支持!





    

  1. bean

  2. 属性如何注入

    package com.company.pojo;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    
    //等价于
    //@Component组件
    @Component
    public class User {
    
        //相当于
        
        @Value("zhangsan")
        public String name;
    }
    
  3. 衍生的注解

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

    1. dao【@Repository】
    2. service【@Service】
    3. controller【@Controller】

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

  4. 自动装配

    • @Autowired:自动装配通过类型,名字

      如果Autowired不能唯一自动装配上属性,则需要通过@Qualifier(value=“xxx”)

    • @Nullable :字段标记了这个注解,说明这个字段可以为null

    • @Resource:自动装配通过名字,类型

    • @Component:组件,放在类上,说明,这个类被Spring管理了,就是bean默认名称为类的小写字母

  5. 作用域

    package com.company.pojo;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Component;
    
    @Component
    @Scope("singleton")
    或者@Scope("prototype"),只能出现一个
    public class User {
    
        @Value("zhangsan")
        public String name;
    }
    
    
  6. 小结

    xml与注解:

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

    xml与注解最佳实践:

    • xml用来管理bean

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

    • 我们在使用过程中,只需要注意一个问题:必须让注解生效,就必须添加注解的支持

          
          
          
          
      
9、使用java的方式配置Spring 9.1 实体类
package com.company.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("张三")
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + ''' +
                '}';
    }
}
9.2 配置类
package com.company.MyConfig;

import com.company.pojo.User;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.import;

//作用域下的注解生效
@ComponentScan("com.company.pojo")
@Configuration
//将两个java配置文件整合成一个文件
@import(MyConfig2.class)
public class MyConfig {

    @Bean
    public User getUser(){
        return new User();
    }
}
9.3 测试类
import com.company.MyConfig.MyConfig;
import com.company.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MyTest {
    @Test
    public void test(){

        ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
        User user = (User) context.getBean("getUser");
        System.out.println(user.getName());
    }
}
10、代理模式

为什么要学习代理模式,因为SpringAOP的底层!【SpringAOP和SpringMVC】

代理模式的分类

  • 静态代理
  • 动态代理
10.1、静态代理

角色分析:

  • 抽象角色:一般会使用接口或者抽象类来解决
  • 真实角色:被代理的角色
  • 代理角色:代理真实角色,代理真实角色后,我们一般会做一些附属操作
  • 客户:访问代理对象的人

代码步骤:

  1. 接口

    //租房这个操作
    public interface Rent{
        public void Rent();
    }
    
  2. 真实角色

    //房东
    public class Host implment Rent{
        
        public void Rent(){
            System.out.println("房东要出租房!");
        }
    }
    
  3. 代理角色

    //中介
    public class proxy implment Rent{
        private Host host;
        public proxy(){
        }
        public proxy(Host host){
            this.host = host;
        }
        public void seeHouse(){
            System.out.println("中介带你看房子");
        }
        public void hetong(){
            System.out.println("签合同");
        }
        public void fare(){
            System.out.println("收中介费");
        }
        //重新实现Rent接口
        public void Rent(){
            seeHouse();
            host.Rent();
            fare();
            hetong();
        }
    }
    
  4. 客户端访问代理角色

    public class Client{
        public static void main(String[] args){
            Host host = new Host();
            proxy pro = new proxy(host);
            pro.Rent();
        }
    }
    

代理模式的好处:

  • 可以使真实角色的操作更加纯粹,不用关注公共业务
  • 公共也就交给代理角色!实现了业务的分工!
  • 公共业务发生扩展的时候,方便集中管理!
  • 耦合性降低了

缺点:

  • 一个真实的角色就会产生一个代理角色:代码量会翻倍,开发效率会变低
10.2、加深理解

1、改原有的业务代码,在公司中是大忌!

这里丢了一张图

10.3、动态代理
  • 动态代理和静态代理角色一样
  • 动态代理的代理类是动态生成的,不是我们直接写好的
  • 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
    • 基于接口的——jdk的动态代理【我们使用】
    • 基于类——cglib
    • JAVA字节码:javassist

两个类:

  1. Proxy:代理
  2. InvocationHandler:调用处理程序

UserService:真实角色要实现的接口

package com.company.demo4;

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

UserServiceImpl:真实角色接口实现

package com.company.demo4;

import com.company.demo4.UserService;

public class UserServiceImpl implements UserService {

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

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

    @Override
    public void updata() {
        System.out.println("修改了一个用户!");

    }

    @Override
    public void query() {
        System.out.println("查询了一个用户!");

    }
}

InvocationHandler:动态代理类

package com.company.demo4;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//实现InvocationHandler接口中的invoke方法
public class ProxyInvocationHandler implements InvocationHandler {

    //真实角色,因为不知道要传入的对象是什么类型的所以这里用Object统一代替
    private Object target;

    //set真实角色
    public void setTarget(Object target) {
        this.target = target;
    }

    //返回动态创建的代理类,接口和代理类
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),this);
    }


    //实现接口中的invoke方法
    //添加需要额外实现的方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        //需要额外实现的方法
        log(method.getName());
        
        //原本需要实现的方法
        Object invoke = method.invoke(target, args);
        return invoke;
    }

    //在真实角色上额外拓展的类
    public void log(String msg){
        System.out.println("使用了" +  msg + "方法");
    }
}

客户端访问代理模式

package com.company.demo4;

import com.company.demo4.UserServiceImpl;
import com.company.demo4.UserService;

public class Client {
    public static void main(String[] args) {
        //创建一个UserServiceImpl实现类,真实角色
        UserServiceImpl userServiceImpl = new UserServiceImpl();

        //创建ProxyInvocationHandler对象
        ProxyInvocationHandler pih = new ProxyInvocationHandler();
        //将真实角色传入pih,代理
        pih.setTarget(userServiceImpl);
        //返回动态创建的代理类(强转为接口类)
        UserService proxy = (UserService) pih.getProxy();

        //代理类调用真实角色的方法,方法执行后会输出代理类新加的各种方法
        proxy.query();
        proxy.add();
        proxy.delete();
        proxy.updata();
    }


}

动态代理的优点

  • 可以使真实角色的操作更加纯粹,不用关注公共业务
  • 公共也就交给代理角色!实现了业务的分工!
  • 公共业务发生扩展的时候,方便集中管理!
  • 耦合性降低了
  • 降低了代码量,不用再编写大量代码
11、AOP 11.1、什么是AOP

面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。

AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生泛型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发效率

丢了一张图

11.2、AOP在Spring中的作用

提供声明式事务:允许用户自定义切面

  • 横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志,安全,缓存,事务等等 ……
  • 切面(Aspect):横切关注点被模块化的特殊对象。即,它是一个类。
  • 通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。
  • 目标(Target):被通知对象
  • 代理(Proxy):向目标对象应用通知之后创建的对象
  • 切入点(PointCut):切面通知执行的”地点“的定义
  • 连接点(JointPoint):与切入点匹配的执行点。
11.3、使用Spring实现AOP

【重点】使用AOP织入,需要导入一个依赖包!否则会报错!


   
        org.aspectj
        aspectjweaver
        1.9.4
    


方式一:使用Spring的API接口

MyTest:测试类

import com.company.service.UserService;
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("userServiceImpl");

        userService.add();
    }
}

applicationContext.xml:配置文件





    
    
    

    
    
        
        

        
        
        
    


Log:前置日志

package com.company.log;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class Log implements MethodBeforeAdvice {

    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName() + "的" + method.getName() + "方法执行了");
    }
}

AfterLog:后置日志

package com.company.log;

import org.springframework.aop.AfterAdvice;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.lang.Nullable;

import java.lang.reflect.Method;

public class AfterLog implements AfterReturningAdvice {
    @Override
    public void afterReturning( Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName() + "的" + method.getName() + "方法执行后的返回值是" + returnValue);
    }
}

UserServiceImpl:接口实现类

package com.company.service;

public class UserServiceImpl implements UserService{
    @Override
    public void add() {
        System.out.println("增加了一个用户!");
    }

    @Override
    public void updata() {
        System.out.println("修改了一个用户!");
    }

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

    @Override
    public void select() {
        System.out.println("查找了一个用户!");
    }
}

UserService:接口

package com.company.service;

public interface UserService {
    public void add();
    public void updata();
    public void delete();
    public void select();
}

方式二:自定义类来实现AOP【主要是切面定义】

applicationContext.xml

    

    
        
        
            
            
            
            
            
        
    

方法

package com.company.diy;

public class DiyPointCut {
    public void before(){
        System.out.println("=========方法执行前=========");
    }

    public void after(){
        System.out.println("=========方法执行后=========");
    }

}

方式三:使用注解实现AOP!

实现类

@Aspect//标注这个类是一个切面
public class AnnotationContext{
    
    @Before(execution(* com.company.service.UserServiceImpl.*(..)))
    public void before(){
        System.out.println("=========方法执行前=========");
    }
    @After(execution(* com.company.service.UserServiceImpl.*(..)))
    public void after(){
        System.out.println("=========方法执行后==========");
    }
    
    @around(execution(* com.company.service.UserServiceImpl.*(..)))
    public void around(ProceedingJoinPoint jp) throws Throwable{
        System.out.println("环绕前");
        Object proceed = jp.proceed();
        System.out.println("环绕后");
        
    }
}

applicationContext.xml



注解开发的缺点:每个注解都需要写一次切入点

12、整合MyBatis

步骤:

  1. 导入相关jar包
    • junit
    • mybatis
    • mysql数据库
    • spring相关的
    • aop织入
    • mybatis-spring【new】
  2. 编写配置文件
  3. 测试
12.1、回忆mybatis
  1. 编写实体类
  2. 编写核心配置文件
  3. 编写接口
  4. 编写Mapper.xml
  5. 编写测试
12.2、Mybatis-spring

在spring配置文件中使用bean标签配置数据源就可以省去在MyBatis核心配置文件中的配置。


    
    
    
    

代替mybatis-config.xml中的相关配置


    
        
        
        
            
            
            
            
        
    

12.3、Spring和MyBatis整合之后 方式1

1、spring-config.xml




    

    
        
        
        
        
    

    
    
    
        
        
        
        为什么要在sqlSessionFactory中配置mybatis配置文件,能在这个bean外面配吗?
        
        
        
    

    
    
        
        
    

    
    
        
       
    

2、mybatis-config.xml




    
    
        
    


3、UserDaoMapper.xml






    

4、UserDao.java

package com.company.dao;

import com.company.pojo.User;
import java.util.List;

public interface UserDao {

    List getAllUser();

}

5、UserDaoImpl.java

package com.company.dao;

import com.company.pojo.User;
import org.apache.ibatis.session.SqlSession;

import java.util.List;

public class UserDaoImpl implements UserDao{

    private SqlSession sqlSession;

    public void setSqlSession(SqlSession sqlSession) {
        this.sqlSession = sqlSession;
    }

    @Override
    public List getAllUser() {
        UserDao userDao = sqlSession.getMapper(UserDao.class);
        return userDao.getAllUser();
    }
}

6、test.java

import com.company.dao.UserDaoImpl;
import com.company.pojo.User;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;
import java.util.List;

public class MyTest6 {
    @Test
    public void test() throws IOException {

        ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml");
        UserDaoImpl userDaoImpl = context.getBean("userDaoImpl", UserDaoImpl.class);
        List allUser = userDaoImpl.getAllUser();
        for (User user : allUser) {
            System.out.println(user);
        }
    }
}
12.4、使用SqlSessionDaoSupport获取mybatis中的SqlSession 方式2

1、UserDaoImpl.java

package com.company.dao;

import com.company.pojo.User;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.support.SqlSessionDaoSupport;

import java.util.List;

public class UserDaoImpl2 extends SqlSessionDaoSupport implements UserDao{

    @Override
    public List getAllUser() {
        //SqlSession sqlSession = getSqlSession();
        //UserDao userDao = sqlSession.getMapper(UserDao.class);
        //List allUser = userDao.getAllUser();
        //return allUser;
        //return和上面的代码等同
        return getSqlSession().getMapper(UserDao.class).getAllUser();
    }
}

2、spring-dao.xml




    
        
        
        
        
    

    
        
        
        
    


    
    
        
    

3、test.java

import com.company.dao.UserDaoImpl2;
import com.company.pojo.User;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;
import java.util.List;

public class MyTest6 {
    @Test
    public void test() throws IOException {

        ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml");
        UserDaoImpl2 userDaoImpl2 = context.getBean("userDaoImpl2", UserDaoImpl2.class);
        List allUser = userDaoImpl2.getAllUser();
        for (User user : allUser) {
            System.out.println(user);
        }
    }
}
13、声明式事务 13.1、回顾事务
  • 把一组业务当成一个业务来做;要么都成功,要么都失败
  • 事务在项目开发中,十分重要,涉及到数据的一致性问题,不能马虎
  • 确保完整性和一致性

事务的ACID原则:

  • 原子性
  • 一致性
  • 隔离性
    • 多个业务可能操作同一个资源,防止数据损坏
  • 持久性
    • 事务一旦提交,无论发生什么问题,结果都不会被影响,被持久化的写在存储器中!
13.2、Spring事务管理
  • 声明式事务:AOP
  • 编程式事务:需要在代码中,进行事务的管理

思考:

为什么需要事务?

  • 如果不配置事务,可能存在数据提交不一致的情况下;
  • 如果我们不在spring中配置声明式事务,我们就需要在代码中手动配置事务!
  • 事务在项目的开发中十分重要,涉及到数据一致性和完整性问题,不容小觑
13.3、在spring中配置声明式事务

代码不需要任何改变,只需要在配置文件中进行设置

spring-dao.xml




    
        
        
        
        
    

    
        
        
        
    

    
        
    


    
        
    

    
    
    
    
        
        
    

    
    
    
        
        
        
            
            
            
            
            
        
    
    
    
        
        
    
    
    

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/644773.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号