spring

Spring框架

第一章 Spring概述

jar包下载地址

https://repo.spring.io/simple/libs-release-local/org/springframework/spring/

1.1 Spring框架是什么

spring全家桶:spring,springmvc,spring boot,spring cloud

spring:解决企业开发的难度,减轻对项目模块之间的管理

​ 类与类之间的管理,帮助开发人员创建对象,管理对象之间的关系

​ spring核心技术 IOC,AOP。能实现模块之间,类之间的解耦和

依赖:类A中调用类B中额属性或者方法,叫做类A依赖类B

1.2 Spring优点

1.2.1 轻量

spring框架使用的jar包都比较小

spring框架裕兴占用的资源少,运行效率高,不依赖其他jar

1.2.2 针对接口编程,解耦和

spring提供了IOC控制反转,有容器管理对象,对象的依赖关系,原来在程序代码中的对象创建方式,现在有容器完成,对象之间的依赖解耦和

1.2.3 AOP编程的支持

通过spring提供的aop功能,方便进行面向切面编程,许多不容易用传统OOP实现的功能可以通过aop轻松应付

在spring中,开发人员可以从繁杂的事务管理代码中解脱出来,通过声明方式灵活的进行事务的管理,提高开发效率和质量

1.2.4 方便集成各种优秀框架

1.3 Spring体系结构

第二章 Ioc控制反转

框架怎么学:框架是一个软件,其他人写好的软件

​ 1.知道框架能做什么,mybatis—访问数据库,对表中的数据执行增删改查

​ 2.框架的语法,框架要完成一个功能,需要一定的步骤支持的

​ 3.框架的内部实现,框架内部怎么做,原理是什么

​ 4.通过学习,可以实现一个框架

Ioc:控制反转,是一个理论,概念,思想

​ 描述的:把对象的创建,赋值,管理工作都交给代码之外的容器实现,也就是对象的创建时由其他外部资源完成。

控制:创建对象,对象的属性赋值,对象之间的关系管理

反转:把原来的开发人员管理,创建对象的权限转移给代码之外的容器实现,由容器代替开发人员管理对象,创建对象,给属性赋值

正转:由开发人员在代码中,使用new构造方法创建对象,开发人员主动管理对象

容器:是一个服务软件,一个框架(spring)

为什么要用ioc:目的是减少对代码的改动,也能实现不同的功能,实现解耦合

Java中创建对象的方式有哪些?

1.构造方法,new Student()

2.反射

3.序列化

4.ioc:容器创建对象

5.动态代理

Ioc的技术实现

servlet:1.创建类继承HttpServlet

​ 2.在web.xml中注册servlet

​ 3.没有创建servlet对象,没有Myservlet myservlet=new Myservlet();

​ 4.serclet是tomacate服务器,它是你创建的,tomcat也称为容器

​ tomcat作为容器:里面存放的有servlet对象,Lisetener,Rilter对象

​ DI是ioc的技术实现

​ DI(Dependency Injection):依赖注入,只需要在程序中提供要使用的对象名称就可以,至于对象如何在容器中创建,赋值,查找都是由容器内部实现的

Spring是使用的DI实现了IOC的功能,Spring底层创建对象,使用的是反射机制

spring是一个容器,管理对象,给属性赋值,底层是反射创建对象

2.1 开发工具准备

实现步骤:
1.新建的student表
2.加入meven的mybatis坐标,mybatis驱动的坐标
3.创建实体类,student--保存表中的一行数据
4.创建持久层的dao接口(studentDao),执行操作数据库的方法(studentDao.xml)
5.创建一个mybatis使用的配置文件
        叫做sql映射文件:写sql语句的,一般一个表一个sql映射文件,这个文件是xml文件。
        这个文件写在接口所在的目录之中,文件名与接口保持一致
6.创建mybatis的主配置文件
                             一个项目就是一个主配置文件
        主配置文件提供了数据库的连接信息和sql映射文件的位置信息
7.创建使用mybatis类
    通过mynbatis访问数据库

2.2 Spring的第一个程序

2.2.1 创建maven项目

实现步骤:

​ 1.创建maven项目

​ 2.加入maven依赖

​ spring的依赖,版本是5.2.5

​ junit依赖

​ 3.创建类(接口和他的实现类)

​ 和没有使用框架一样,就是普通的Java类

​ 4.创建spring需要使用的配置文件

​ 声明类的信息,这些类由spring创建和管理

​ 5.测试spring创建。

2.2.2 引入maven依赖

<!-- spring依赖-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
        <version>5.2.5.RELEASE</version>
    </dependency>

2.2.3定义接口与实体类

public interface SomeService {
    void doSome();
}
public class SomeServiceImpl implements SomeService {
    public  SomeServiceImpl(){
        System.out.println("构造方法SomeServiceImpl执行了");
    }
    @Override
    public void doSome() {
        System.out.println("你好呀");
    }
}

2.2.4 创建spring配置文件

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

</beans>
http://www.springframework.org/schema/beans/spring-beans.xsd是约束文件的路径


<!--告诉spring创建对象
声明bean,就是告诉spring要创建某个类的对象
id:对象自定义名称,唯一值。spring通过这个名称找到对象
class:类的全限定名称(不能是接口,因为spring是反射机制创建对象,必须使用类)

spring就完成SomeServiceImpl someService=new SomeServiceImpl();
spring就是把床架好的对象放在map中,spring框架有一个map存放对象的。
        springMap.put(id的值,对象)
        例如:springMap.put("someService",new SomeServiceImpl());

注意:一个bean声明一个对象
-->

    <bean id="someService" class="com.jike.Impl.SomeServiceImpl"/>
</beans>
<!--
spring的配置文件
1.beans:是根标签,spring把Java对象成为bean
2.spring-beans.xsd  是约束文件,和mybatis指定,dtd是一样的
-->

2.2.5 定义测试类

spring容器中常用的两个方法

String config="beans.xml";
ApplicationContext ac=new ClassPathXmlApplicationContext(config);
//使用spring容器提供的方法,获取容器中对象的数量
int num=ac.getBeanDefinitionCount();
System.out.println("容器中定义对象的数量:"+num);
//容器中每个定义的对象的名称
String nums[]=ac.getBeanDefinitionNames();
for (String name:nums
     ) {
    System.out.println("容器中定义对象的名称是:"+name);
}

2.2.6 使用spring创建非自定义

<!--
spring能创建一个非自定义类的对象,创建一个存在的某个类的对象
-->
    <bean  id="mydata" class="java.util.Date"/>
String config="beans.xml";
ApplicationContext ac=new ClassPathXmlApplicationContext(config);
Date date=(Date) ac.getBean("mydata");
System.out.println("当前时间是:"+date);

2.2.7 容器接口和实现类

2.3 基于XML的DI

junit:单元测试,一个工具类库,做测试方法使用

​ 单元:指定的是方法,一个类中有很多方法,一个方法称为单元

使用单元测试:

1.需要加入单元测试依赖

2.3.1 注入分类

1.set注入(掌握)(2020/10/6)

​ A.简单类型

public class Student {
    private String name;
    private int age;
<!--声明student对象
注入:就是赋值的意思
简单类型:spring中规定java的基本数据类型和spring都是简单类型。
di:给属性赋值
1.set注入(设置注入):spring掉用类的set方法,在set方法可以实现属性的赋值
    1):简单类型的set注入
    <bean id="xx" class="yyy">
        <property name="属性名字" value="此属性的值"/>
        一个property只能给一个属性赋值
    </bean>
    name后面的属性名称是根据属性的set方法执行的,只要有set方法,就会执行,不需要定义属性
<bean id="student" class="com.jike.ba01.Student">
    <property name="name" value="张三"/>
    <property name="age" value="20"/>
</bean>		
@Test
public void test01(){
    String config="ba01/applicationContext.xml";
    ApplicationContext ac=new ClassPathXmlApplicationContext(config);
    Student student1=(Student) ac.getBean("student");
    student1.setName("李明");
    student1.setAge(23);
    System.out.println("学生的信息为:"+student1);
}

B.引用类型

public class School {
    private String name;
    private String address;
public class Student {
    private String name;
    private int age;

    //声明一个引用类型的对象
    private School school;
2):引用类型的set注入:spring调用类的set方法
    <bean id="xx" class="yyy">
    <property name="属性名字" ref="bena的id(对象的名称)"/>
</bean>

<bean id="student" class="com.jike.ba02.Student">
        <property name="name" value="张三"/>
        <property name="age" value="20"/>
<!--引用类型-->
        <property name="school" ref="myschool"/>
    </bean>

    <bean id="myschool" class="com.jike.ba02.School">
        <property name="name" value="上海交通大学"/>
        <property name="address" value="上海海定区"/>
    </bean>
@Test
    public void test01(){
    String config="ba02/applicationContext.xml";
    ApplicationContext ac=new ClassPathXmlApplicationContext(config);
    Student student1=(Student) ac.getBean("student");
    System.out.println("学生信息为:"+student1);
}
2.构造注入(理解)
public class Student {
    private String name;
    private int age;

    //定义无参构造方法
    public Student(){}
    //定义有参构造
    public Student(String myname,Integer myage,School myschool){
        this.name=myname;
        this.age=myage;
        this.school=myschool;
    }
    //定义一个引用类型
    private School school;
public class School {
    private String name;
    private String address;
<!--
2.构造方法注入:spring调用类的有参构造方法,再创建对象的同时,在构造方法种给属性赋值
构造注入使用<constructor-arg>标签
<constructor-arg>标签:一个<constructor-arg>表示构造方法中的一个参数
<constructor-arg>属性标签:
    name:表示构造方法的形参名(在Student类种定义的构造方法中的参数)
    index:表示构造方法的参数的位置,参数从左往右位置是0.1.2的顺序
    value:构造方法的形参是简单类型,使用value
    ref:构造方法的形参是引用类型,使用ref

-->
<!--使用name的构造注入-->
<bean id="mystudent" class="com.jike.ba03.Student">
<constructor-arg name="myname" value="李明"/>
    <constructor-arg name="myage" value="20"/>
    <constructor-arg  name="myschool" ref="myschool"/>
</bean>
    <!--使用index的构造注入-->
    <bean id="mystudent1" class="com.jike.ba03.Student">
        <constructor-arg index="0" value="需信息"/>
        <constructor-arg index="1" value="222"/>
        <constructor-arg index="2" ref="myschool"/>
    </bean>
@Test
public void test(){
    String config="ba03/applicationContext.xml";
    ApplicationContext ac=new ClassPathXmlApplicationContext(config);
    Student student=(Student) ac.getBean("mystudent");
    System.out.println("学生信息为"+student);
}

2.3.2 引用类型属于自动注入

1.byName自定注入(2020/10/7)
public class School {
    private String name;
    private String address;
public class Student {
    private String name;
    private int age;

    //声明一个引用类型的对象
    private School school;
<!--
        引用类型的自定注入:spring框架可以根据某些规则可以给引用类型赋值,不用你在给引用类型赋值了
        使用的规则常用的是byName,byType
        1.byName(按名称注入):java类中引用类型的属性名和spring容器中(配置文件)<bean>的id名称一样
                               且数据类型是一致的,这样容器中的bean,spring能够赋值给引用类型
         语法:
          <bean id="" class="" autowire="byName">
                简单类型的赋值
          </bean>
          2.byType(按类型注入):java类中引用类型的数据类型和spring容器中(配置文件)<bean>的class属性
                              是同源关系的,这样的bean能够赋值给引用类型
             同源就是同一类的意思:
                1.java类中引用类型的数据类型和bean的class的值是一样的
                2.java类中引用类型的数据类型和bean的class的值是父子关系的
                3.java类中引用类型的数据类型和bean的class的值是接口和实现类关系的
              语法:
              <bean id="" class="" autowire="byType">
                简单类型的赋值
              </bean>
-->

    <bean id="student" class="com.jike.ba04.Student" autowire="byName">
        <property name="name" value="张三"/>
        <property name="age" value="20"/>
<!--引用类型
        <property name="school" ref="myschool"/>-->
    </bean>

    <bean id="school" class="com.jike.ba04.School">
        <property name="name" value="交通大学"/>
        <property name="address" value="上海海定区"/>
    </bean>
引用类型的自定注入:spring框架可以根据某些规则可以给引用类型赋值,不用你在给引用类型赋值了
使用的规则常用的是byName,byType
1.byName(按名称注入):java类中引用类型的属性名和spring容器中(配置文件)<bean>的id名称一样
                       且数据类型是一致的,这样容器中的bean,spring能够赋值给引用类型
 语法:
  <bean id="" class="" autowire="">
        简单类型的赋值
  </bean>
 
2.byType自动注入

2.byType(按类型注入):java类中引用类型的数据类型和spring容器中(配置文件)的class属性
是同源关系的,这样的bean能够赋值给引用类型
同源就是同一类的意思:
1.java类中引用类型的数据类型和bean的class的值是一样的
2.java类中引用类型的数据类型和bean的class的值是父子关系的
3.java类中引用类型的数据类型和bean的class的值是接口和实现类关系的
语法:

简单类型的赋值

public class School {
    private String name;
    private String address;
public class Student {
    private String name;
    private int age;

    //声明一个引用类型的对象
    private School school;
<!--
        引用类型的自定注入:spring框架可以根据某些规则可以给引用类型赋值,不用你在给引用类型赋值了
        使用的规则常用的是byName,byType

          2.byType(按类型注入):java类中引用类型的数据类型和spring容器中(配置文件)<bean>的class属性
                              是同源关系的,这样的bean能够赋值给引用类型
             同源就是同一类的意思:
                1.java类中引用类型的数据类型和bean的class的值是一样的
                2.java类中引用类型的数据类型和bean的class的值是父子关系(子类继承父类)的
                3.java类中引用类型的数据类型和bean的class的值是接口和实现类关系的
              语法:
              <bean id="" class="" autowire="byType">
                简单类型的赋值
              </bean>
-->

    <bean id="student" class="com.jike.ba05.Student" autowire="byType">
        <property name="name" value="张三"/>
        <property name="age" value="20"/>
<!--引用类型
        <property name="school" ref="myschool"/>-->
    </bean>

    <bean id="myschool" class="com.jike.ba05.School">
        <property name="name" value="大学"/>
        <property name="address" value="上海海定区"/>
    </bean>
@Test
    public void test01(){
    String config="ba05/applicationContext.xml";
    ApplicationContext ac=new ClassPathXmlApplicationContext(config);
    Student student1=(Student) ac.getBean("student");
    System.out.println("学生信息为:"+student1);
}

2.3.3 为应用指定对各Spring配置文件

多配置优势

1.每个文件的大小比一个文件要小的多,效率高

2.避免多人竞争带来的冲突

如果你的项目有多个模块(相关功能在一起),一个模块一个配置文件

学生考勤模块一个配置文件

学生成绩一个配置文件

多文件的分配方式

1.按功能模块,一个模块一个配置文件

2.按类的功能,数据库相关的配置一个文件配置文件,做事务的功能一个配置文件,做service功能的一个配置文件等

<!--声明school对象-->
    <bean id="myschool" class="com.jike.ba06.School">
        <property name="name" value="郑州大学"/>
        <property name="address" value="郑州"/>
    </bean>
<!--声明student对象-->
    <bean id="student" class="com.jike.ba06.Student" autowire="byType">
        <property name="name" value="雄安"/>
        <property name="age" value="30"/>

    </bean>
<!--
spring-totle:表示主配置文件:包含其他配置文件的,主配置文件一般是不定义对象的
语法: <import resource="classpath:其他配置文件的路径"/>
关键字:“classpath”表示类路径(class文件所在的位置)-classpath表示target目录下的classes文件夹所在的位置
在spring的配置文件中要值定其他文件的位置,需要使用classpath,告诉spring到哪里去加载读物文件
-->

<!--    加载的是文件列表-->
    <import resource="classpath:ba06/spring-student.xml"/>
    <import resource="classpath:ba06/spring-school.xml"/>
<!--在包含关系的配置文件中,可以使用通配符(*:表示任意字符)-->
<!--
spring-totle:表示主配置文件:包含其他配置文件的,主配置文件一般是不定义对象的
语法: <import resource="classpath:其他配置文件的路径"/>
关键字:“classpath”表示类路径(class文件所在的位置)-classpath表示target目录下的classes文件夹所在的位置
在spring的配置文件中要值定其他文件的位置,需要使用classpath,告诉spring到哪里去加载读物文件
-->

2.4 基于注解DI(2020/10/7)

通过注解完成Java对象创建,属性赋值

使用注解的步骤:

1.加入maven依赖:spring-context,在你加入spring-context的同时,间接加入spring-aop的依赖

​ 使用注解必须使用spring-aop依赖

2.在类中加入spring的注解(多个不同功能的注解)

3.在srping的配置文件中,加入一个组件扫描器的标签,说明注解在你的项目中的位置

学习的注解:

@Component

@Respotory

@Service

@Controller

@Value

@Autowirde

@Resource

2.4.1 定义Bean的注解@Component(掌握)

/**
        * @Component:创建对象的,等同于bena的功能
        *        属性:value 就是对象的名称,也就是bean中id的值
        *              value的值是唯一的,创建的对象在spring容器中就一个
        *        位置:在类的上面
        * @Component(value = "mystudent") :等同于
        * <bean id="myschool" class="com.jike.ba01.School">
        *
        * */
@Component(value = "mystudent")
/**
 * @Component使用的三种方式
 * 1.使用value属性,指定对象名称
 * @Component(value = "mystudent")
 * 2.省略value
 * @Component("mystudent")
 * 3.不指定对象名称,由spring提供默认名称,类名的首字母小写
 * @Component
 * */
 spring中和@Component功能一致,创建对象的注解还有
1.@Respotory(用在持久层类的上面):放在dao的实现类上面,表面创建dao对象,dao对象是能访问数据库的
2.@Service(用在业务层类的上面):放在service的实现类上面,创建service对象,service对象是做业务处理的,可以有事务等功能
3.@Controller(用在控制器的上面):放在控制器(处理器)类上面,创建控制对象,控制器对象,能够接收用户提交的参数,显示请求的处理结果
以上三个注解的使用语法和@Component一样的,都能创建对象,但是这三个注解还有额外的功能,
@Respotory,@Service,@Controller是给项目的对象分层的

<!--
声明组件扫描器(component-scan),组件就是Java对象
base-package:指定注解在你项目中的包名。
component-scan工作方式:spring会扫描遍历base-package指定的包,
    把包中和子包中所有类,找到类中的注解,按照注解的功能创建对象,或给属性赋值

-->
 <context:component-scan base-package="com.jike.ba01"/>
<!--
声明组件扫描器(component-scan),组件就是Java对象
base-package:指定注解在你项目中的包名。
component-scan工作方式:spring会扫描遍历base-package指定的包,
    把包中和子包中所有类,找到类中的注解,按照注解的功能创建对象,或给属性赋值

-->
    <context:component-scan base-package="com.jike.ba01"/>
@Test
public void test01(){
    String config="applicationContext.xml";
    ApplicationContext ac=new ClassPathXmlApplicationContext(config);
    Student student=(Student) ac.getBean("mystudent");
    System.out.println("学生的信息是:"+student);
}

指定多个包的三种方式:

1.第一种方式:使用多次组件扫描器,指定不同的包

<context:component-scan base-package=“com.jike.ba01”/>

<context:component-scan base-package=“com.jike.ba02”/>

2.第二种方式:使用分隔符(,或;)分隔多个包名

<context:component-scan base-package=“com.jike.ba01;com.jike.ba02”/>

3.第三种方式:指定父包

<context:component-scan base-package=“com.jike”/>

2.4.2 简单类型属性注入@Value(掌握)

@Component("mystudent2")
public class Student {
    @Value("张三")
    private String name;
    @Value("30")
    private Integer age;
    
 <context:component-scan base-package="com.jike.ba02"/>


<context:component-scan base-package="com.jike.ba02"/>
@Test
public void test01(){
    String config="applicationContext.xml";
    ApplicationContext ac=new ClassPathXmlApplicationContext(config);
    Student student=(Student) ac.getBean("mystudent2");
    System.out.println("学生的信息是:"+student);
}

2.4.3byType自动注入@Autowirde(掌握)

@Component("myschool")
public class School {
    @Value("清华大学")
    private String name;
    @Value("北京海定区")
    private String address;

@Component("mystudent3")
public class Student {
    @Value("小明")
    private String name;
    @Value("30")
    private Integer age;

    /**
     * 引用类型
     * @Autowired :spring框架提供的注解,实现引用类型的赋值
     * spring通过注解给引用类型赋值,使用的是自动注入原理,支持byName,buType
     * @Autowired 默认的是使用的是byType自动注入
     *
     * 位置:1)在属性的定义上面,不需要set方法,推荐使用
     *      2) 在set方法的上面
     * */
    //引用类型的定义
    @Autowired
    private School school;

<context:component-scan base-package="com.jike.ba03"/>
@Component("myschool")
public class School {
    @Value("清华大学")
    private String name;
    @Value("北京海定区")
    private String address;
<context:component-scan base-package="com.jike.ba03"/>
@Test
public void text01(){
    String config="applicationContext.xml";
    ApplicationContext ac=new ClassPathXmlApplicationContext(config);
    Student student=(Student) ac.getBean("mystudent3");
    System.out.println(student);
}

2.4.4byName自定注入@Autowirde与@Qualifier

 * 如果使用byName方式,需要做的是
 * 1.在属性上加 @Autowired
 * 2.在属性上面加@Qualifier(value = "bean的id"):表示使用指定名称的bean完成赋值
 * */
//引用类型的定义
@Autowired
@Qualifier(value = "myschool4")
private School school;

@Component("myschool4")
public class School {
    @Value("人民大学")
    private String name;
    @Value("北京海定区")
    private String address;
    
@Component("myschool4")
public class School {
    @Value("人民大学")
    private String name;
    @Value("北京海定区")
    private String address;
<context:component-scan base-package="com.jike.ba04"/>
@Test
public void text01(){
    String config="applicationContext.xml";
    ApplicationContext ac=new ClassPathXmlApplicationContext(config);
    Student student=(Student) ac.getBean("mystudent4");
    System.out.println(student);
}

2.4.5 JDK注解@Resource自定注入(掌握)

1.byType注入引用类型属性
/**
 * 引用类型:
 * @Resource 来自jdk中的注解,spring框架提供了对这个注解的功能支持,可以使用它给引用类型赋值
 *             使用的是自动注入的原理,支持byName,byType,默认是byName
 *   位置:1.在属性定义的上面,无无需使用set方法,推荐使用
 *        2.在set方法的上面
  @Resource 只是用byName方式,需要增加一个属性 name
     name的值是bean的id(名称)
 * */
//引用类型的定义
@Resource
private School school;
<context:component-scan base-package="com.jike.ba06"/>
@Test
public void text01(){
    String config="applicationContext.xml";
    ApplicationContext ac=new ClassPathXmlApplicationContext(config);
    Student student=(Student) ac.getBean("mystudent6");
    System.out.println(student);
}
2.byName注入引用类型属性

2.4.6注解与xml的对比

经常改动就用xml配置文件,不经常改动要用注解

第三章 AOP面向切面编程

3.1 动态代理

能创建对象

动态代理的作用:

在目标源代码不改变的情况下,增加功能

减少代码的重复

专注业务逻辑代码

解耦和,让你的业务功能和日志,事务非业务功能分离

3.1.1 JDK动态代理

使用JDK中的三个类Proxy,Method和InovcationHandler,创建代理对象,实现动态代理

3.1.2 CGLIB动态代理

cglib动态代理:第三方的工具库,创建代理兑现,原理是继承,通过继承目标类,创建子类

​ 子类就是代理对象,要求目标类不能是final的,方法不能是final的

3.2不使用AOP的开发方式(理解)

Step1:项目

Step2:项目

Step3:项目

45

3.3 AOP概念

3.4 AOP简介

AOP:面向切面编程,从动态角度考虑程序运行过程

AOP:是采用动态代理的方式实现的,采用两种代理:JDK的动态代理,与CGLIB的动态代理

AOP就是动态代理的规范化,把动态代理的实现步骤,方式都定义好了,让开发人员用一种统一的方式,使用动态代理

3.5 面向切面编程有什么好处

AOP的理解:

1.需要在分析项目功能时,找出切面

2.合理的安排切面的执行时间(在目标方法前,还是在目标方法之后)

3.合理的安排切面执行的位置,在哪个类,哪个方法增加增强功能

3.6AOP编程术语(掌握)48

(1)切面( Aspect):给你的目标类增加功能,就是切面,像上面用的事务,日志的都是切脉你

​ 切面的特点:一般都是非业务方法,独立使用的

(2)连接点(JoinPoint):连接业务方法和切面的位置,就某类中的业务方法

(3)切入点(Pointout):指多个连接点方法的集合,多个方法

(4)目标对象():给哪个类的方法增加功能,这个类就是目标对象

(5)通知(advice):通知表示切面执行的时间

说一个切面有三个关键的要素

1.切面的功能代买,切面是干什么的

2.切面的执行位置,使用pointCut表示切面执行的位置

3.切面的执行时间,是使用advice表示时间,在目标方法之前,还是在目标执行之后

3.7 AspectJ对AOP的实现

aop的实现:

aop是一个规范,是动态的一个规范化,一个标准

aop的技术实现框架:

1.spring:spring在内部实现了aop规范,能做aop的工作

​ spring主要在事务处理时使用aop

​ 我们项目开发中很少使用spring的aop实现,因为spring的aop比较笨重

2.aspectJ:一个开源的专门做aop的框架,spring框架中集成了aspectJ框架,通过spring就能使用aspectJ的功能

​ aspectJ框架实现aop的两种方式;

​ 1.使用xml的配置文件:配置全局事务

​ 2.使用注解,我们在项目中要做aop共嫩,一般都使用注解,aspectJ有五个注解

学习aspectJ框架的使用

1.切面的执行时间:这个执行时间在规范中叫通知advice,也叫增强

​ 在aspectJ框架中使用注解表示,也可以使用xml配置文件中的标签

​ @Before

​ @AfterReturning

​ @Around

​ @AfterThrowing

​ @After

2.表示切面执行的位置,使用的是切入点表达式

3.7.1 AspectJ的通知类型(理解)

3.7.2 AspectJ的切入点表达式

3.7.3 AspectJ的开发环境(掌握)

(1)maven依赖
(2)引入AOP约束

3.7.4 AspectJ基于注解的AOP实现(掌握)

ch06-aop-aspectj:使用aspectj框架实现aop
使用aop:目的是给已经存在的一些类和方法,增加额外的功能,前提是不改变原来的类的代码

使用aspectJ实现aop的基本步骤
1.新建maven项目
2.加入依赖
    spring依赖
    aspectJ依赖
    juint单元测试类
3.创建目标类:接口和他的实现类
    要做的事给类中的方法增加功能

4..创建目标类:普通类
    1.在类的上面加入aspect
    2.在类中定义方法,方法就是切面要执行的共能代码
        在方法的上面加入aspect中的通知注解,例如@Before
        有需要指定切入点表达式execution()
5.创建spring的配置文件:声明对象,把对象交给容器统一处理
声明对象,你可以使用注解或者xml配置文件<bean>
    1.声明目标对象
    2.声明切面对象
    3.声明aspectJ框架中的自动代理生成器标签
        自动代理生成器:用来完成代理对象的自动创建功能

6.创建测试类,从spring容器中获取目标对象(实际就是代理对象)
    通过代理执行方法,实现aop的共能增强
(1) 实现步骤
public interface SomeService {
    void doSome(String name,Integer age);
}
//目标类
public class SomeServiceImpl implements SomeService {
    @Override
    public void doSome(String name, Integer age) {
        System.out.println("执行了doSome方法");
    }
}
/**
 *@Aspect 事@Aspect 框架中的注解
 *  作用:当前类是切面类
 *  切面类:是用来给业务方法增加功能的类,在这个类中有切面的功能代码
 *  位置:在类定义的上面
 * */
@Aspect
public class MyAspect {
   /**
    * 定义方法,方法是实现切面功能的
    * 方法的定义要求
    * 公共方法
    * 没有返回值
    * 方法名称自定义
    * 方法可以有参数,也可以没有参数
    *   如果有参数,参数不是自定义的,有几个参数类型可以使用
    * */

   /**
    * @before 前置通知注解
    * 属性:value,是切入点表达式,表示切面的功能的执行的位置
    * 位置:在方法的上面
    * 特点:
    *   在目标方法之前执行
    *   不会改变目标方法的执行结果
    *   不会影响目标方法的执行
    * */
   @Before(value = "execution(public void com.jike.ba01.SomeServiceImpl.doSome(String, Integer))")
   public void myBefore(){
       System.out.println("前置通知,切面功能:在目标方法执行之前输出执行时间:"+new Date());
   }
}

<!--把对象交给spring容器,由spring容器统一床架,管理对象-->
<!--声明目标对象-->
    <bean id="someService" class="com.jike.ba01.SomeServiceImpl"/>
<!--声明切面对象-->
    <bean id="myaspectj" class="com.jike.ba01.MyAspect"/>
<!--声明自定代理生成器,使用aspectj框架内部的功能,创建目标对象的代理生成器
    创建代理对象是自内存中实现的,修改目标对象的内存中的结构,创建为代理对象,
    所以目标对象就是被修改后的代理对象
    aspectj-autoproxy:会把spring容器中所有的目标对象,一次性都生成代理对象
-->

    <aop:aspectj-autoproxy/>
@Test
public void text01(){
    String config="applicationContext.xml";
    ApplicationContext ac=new ClassPathXmlApplicationContext(config);
    SomeService service=(SomeService) ac.getBean("someService");
    service.doSome("张三",20);

}
(2)@Before前置通知-方法有JointPoint
public class SomeServiceImpl implements SomeService {
    @Override
    public void doSome(String name, Integer age) {
        System.out.println("执行了doSome方法");
    }
}
public interface SomeService {
    void doSome(String name, Integer age);
}
 /**
     * JoinPoint:业务方法,要加入切面功能的业务方法
     *      作用:可以在通知方法中获取方法执行时的信息,例如方法名称,方法的实参
     *      如果你的切面功能中需要用到方法的信息,就加入joinPoint
     *      这个joinPoint参数的值由框架赋予,必须是第一个位置的参数
     * */
@Before(value = "execution(* do*(..))")
public void myBefore(JoinPoint jp){
    //获取方法的完整定义
    System.out.println("方法的签名(定义)="+jp.getSignature());
    System.out.println("方法的名称="+jp.getSignature().getName());
    //获取方法的实参
    Object arr[]=jp.getArgs();
    for (Object arrs:arr
         ) {
        System.out.println("参数="+arr);
    }
    System.out.println("1===前置通知,切面功能:在目标方法执行之前输出执行时间:"+new Date());
}
<!--把对象交给spring容器,由spring容器统一床架,管理对象-->
<!--声明目标对象-->
    <bean id="someService" class="com.jike.ba02.SomeServiceImpl"/>
<!--声明切面对象-->
    <bean id="myaspectj" class="com.jike.ba02.MyAspect"/>
<!--声明自定代理生成器,使用aspectj框架内部的功能,创建目标对象的代理生成器
    创建代理对象是自内存中实现的,修改目标对象的内存中的结构,创建为代理对象,
    所以目标对象就是被修改后的代理对象
    aspectj-autoproxy:会把spring容器中所有的目标对象,一次性都生成代理对象
-->

    <aop:aspectj-autoproxy/>
@Test
public void text01(){
    String config="applicationContext2.xml";
    ApplicationContext ac=new ClassPathXmlApplicationContext(config);
    SomeService service=(SomeService) ac.getBean("someService");
    service.doSome("张三",20);

}
(3)@AfterReturning后置通知-注解有returning属性
public interface SomeService {
    void doSome(String name, Integer age);
    //定义一个方法
    String doOther(String name,Integer age);
}
public class SomeServiceImpl implements SomeService {
    @Override
    public void doSome(String name, Integer age) {
        System.out.println("执行了doSome方法");
    }

    @Override
    public String doOther(String name, Integer age) {
        System.out.println("后置通知");
        return "ok";
    }
}
@Aspect
public class MyAspect {
    /**
     * 后置通知定义方法:方法是实现切面功能的
     * 方法的定义要求
     * 1.公共方法public
     * 2.方法没有返回值
     * 3.方法名称自定义
     * 4.方法有参数的,参数推荐使用Object,参数名自定义
     *
     * */
    /*
    * @AfterReturning 后置通知:
    *       属性:1.value 切入点表达式
    *             2.returning 自定义的变量,表示目标方法的返回值的
    *       位置:在方法定义的上面
    *
    * 特点:
    * 1.在目标方法之后执行的
    * 2.能够获取到目标方法 的返回值的,可以根据这个返回值做不同的处理功能
    *Object res=doOther()
    * 3.可以修改这个返回值
    *后置通知的执行
    * Object res=doOther()
    * yAfter(res)
    * */
    @AfterReturning(value = "execution(* doOther(..))",returning = "res")
    public void myAfter(Object res){
        System.out.println("后置通知:在目标方法之后执行的");
        if (res.equals("ok")){
            System.out.println("你好");
        }else{
            System.out.println("你不好");
        }
    }
<!--把对象交给spring容器,由spring容器统一床架,管理对象-->
<!--声明目标对象-->
    <bean id="someService" class="com.jike.ba03.SomeServiceImpl"/>
<!--声明切面对象-->
    <bean id="myaspectj" class="com.jike.ba03.MyAspect"/>
<!--声明自定代理生成器,使用aspectj框架内部的功能,创建目标对象的代理生成器
    创建代理对象是自内存中实现的,修改目标对象的内存中的结构,创建为代理对象,
    所以目标对象就是被修改后的代理对象
    aspectj-autoproxy:会把spring容器中所有的目标对象,一次性都生成代理对象
-->

    <aop:aspectj-autoproxy/>
@Test
public void text01(){
    String config="applicationContext3.xml";
    ApplicationContext ac=new ClassPathXmlApplicationContext(config);
    SomeService service=(SomeService) ac.getBean("someService");
    String name=service.doOther("张三",28);
    System.out.println(name);
}
(4)@Around环绕通知-增强方法有ProceedingJoinPoint参数
public class SomeServiceImpl implements SomeService {
    @Override
    public void doSome(String name, Integer age) {
        System.out.println("执行了doSome方法");
    }

    @Override
    public String doOther(String name, Integer age) {
        System.out.println("后置通知");
        return "ok";
    }

    @Override
    public String doFile(String name, Integer age) {
        System.out.println("这是后置通知中的环绕通知");
        return "success";
    }
public interface SomeService {
    void doSome(String name, Integer age);
    //定义一个方法
    String doOther(String name, Integer age);
    String doFile(String name,Integer age);
}
/**
 * 环绕通知的定义格式
 * 1.公共方法public
 * 2.必须有一个返回值,推荐使用Object
 * 3.方法名称自定义
 * 4.方法有参数的,固定的参数ProceedingJoinPoint
 * */
/**
 * @Around() 环绕通知
 *      属性:value 切入点表达式
 *      位置:在方法定义的上面
 * 特点:
 * 1.他是功能最强的通知
 * 2.再目标方法的前和后都能增强功能
 * 3.控制目标方法是否被调用执行
 * 4.修改原来的目标方法的执行结果。影响最后的调用结果
 *
 * 环绕通知,等同于jdk动态代理,InvocationHandler接口
 *
 * 参数:ProceedingJoinPoint 就等同于Method
 *          作用:执行目标方法的
 *   返回值:就是目标方法的执行结果,可以被修改
 *
 *
 *
 * */
@Around(value = "execution(* doFile(..))")
public Object myAround(ProceedingJoinPoint pj) throws Throwable {
    System.out.println("实行环绕通知");
    //实现环绕通知
    //1.目标方法的调用'
    Object result = null;
    result=pj.proceed();
    System.out.println("环绕通知:再目标方法之后,提交事务");
    //2.再目标方法的前或后加入功能

    //返回目标方法的执行结果
    return result;
}
@Test
public void text01(){
    String config="applicationContext4.xml";
    ApplicationContext ac=new ClassPathXmlApplicationContext(config);
    SomeService service=(SomeService) ac.getBean("someService");
    String name=service.doFile("张三",28);
    System.out.println(name);
}
(5)@AfterThrowing 异常通知-注解中有Throwing属性
(6)@After最终通知
(7)@Pointcut定义切入点

第四章 Spring集成Mybatis

把Mybatis和spring集成再一起,向一个框架一样使用

用的技术是:ioc

为什么ioc:能把mybatis和spring集成在一起,象一个框架,是因为ioc能创建对象

可以把mybatis框架中的对象交给spring统一创建,开发人员从spring中获取对象

开发人员就不用同时面对两个或多个框架了,就面对一个spring

mybatis的使用步骤:

1.定义dao接口,StudentDao

2.定义mapper文件。StudentDao。xml

3.定义mabatis的主配置文件

4.创建dao的代理对象,StudenDao dao = SqlSession.getMapper(StudentDao.xml)

要使用dao对象,需要使用getMapper()方法

怎么样获取到getMapper()方法,需要哪些条件

1.创建SqlSession对象,需要使用SqlSesionFcatory的openSession()方法

2.创建SqlSessionFcatory对象,通过读取mybatis的主配置文件,能创建SqlSesionFcatory对象

需要SqlSesionFcatory对象,使用Factory能获得SqlSession,有了sqlsession就能有dao,目标就是获取dao对象

Factory创建选哟读取著配置文件

主配置文件:

1.数据库信息

2.mapper文件的位置

69

4.1Mysql创建数据库spring.db,新建表Student

4.2 maven的依赖pom.xml

<!--单元测试-->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
<!--spring核心ioc-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>
<!-- 做spring事务用到的   -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.2.5.RELEASE</version>
    </dependency>
<!--    mybatis的依赖-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.1</version>
    </dependency>
<!--    mybatis和spring集成的依赖-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>1.3.1</version>
    </dependency>
<!--mysql驱动-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.9</version>
    </dependency>
<!--阿里公司数据库的连接池-->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.12</version>
    </dependency>
    
     <build>
<!--   包含mapper文件的一个插件,输出到classes目录中-->
      <resources>
          <resource>
              <directory>src/main/java</directory>
              <includes>
                  <include>**/*.properties</include>
                  <include>**/*.xml</include>
              </includes>
              <filtering>false</filtering>
          </resource>
      </resources>

4.3 定义实体类Student

4.4 定义StudentDao接口

public interface StudentDao {

    int insert(Student student);
    List<Student> selectAll();
}

4.5 定义映射文件Mapper

<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.jike.dao.StudentDao">
    <insert id="insert">
        insert into student values(#{id},#{name},#{email},#{age})
    </insert>
    <select id="selectAll" resultType="com.jike.dao.StudentDao">
        select * from student order by id
    </select>
</mapper>

4.6 定义Service接口和实现类

public interface StudentService {

    int addStudent(Student student);
    List<Student> queryStudents();
}
public class StudentServiceImpl implements StudentService {
    //引用类型
    private StudentDao studentDao;

    public void setStudentDao(StudentDao studentDao) {
        this.studentDao = studentDao;
    }

    @Override
    public int addStudent(Student student) {
        int num=studentDao.insert(student);
        return num;
    }

    @Override
    public List<Student> queryStudents() {
        List<Student> students=studentDao.selectAll();
        return students;
    }

4.7 定义Mybatis主配置文件

<configuration>
    <!--setting:控制mybatis全局行为-->
    <settings>
        <!--设置mybatis输出日志-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <!--设置别名-->
    <typeAliases>
        <!--name:实体类所在的包名-->
        <package name="com.jike.domain"/>
    </typeAliases>
    <!--sql mapper(sql映射文件)的位置-->
    <mappers>
        <!--name:是包名,这个包中所有mapper.xml一次能加成
         也可以用:<mapper resource=""></mapper>
        -->
        <package name="com.jike.dao"/>
    </mappers>

4.8 修改Spring配置文件

4.9 向Service注入接口名

4.10 Spring配置文件全部配置

<!--把数据库的配置信息,写在一个独立的配置文件中,编译修改数据库的配置内容
    spring知道jdbc.properties文件的位置
-->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <!--声明数据源database,作用是连接数据库的-->
    <bean id="myDatasources" class="com.alibaba.druid.pool.DruidDataSource"
          init-method="init" destroy-method="close">
<!-- set注入给DruidDataSource提供数据连接信息的-->
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="maxActive" value="${jdbc.max}"/>
    </bean>
<!--声明的事mybatis提供的sqlSessionFactoryBean类,这个类内部创建SqlSessionFactory的-->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--set注入,把数据库连接池赋给了dataSources属性-->
        <property name="dataSource" ref="myDatasources"/>
<!-- mybatis主配置文件的位置
     configLocation属性是Resource类型,读取配置文件
     它的赋值,使用value,指定文件的路径,使用classPath:表示文件的位置
-->
        <property name="configLocation" value="classpath:mybatis.xml"/>
    </bean>
<!--创建dao对象,使用sqlSession的getMapper(studentDao.class)
    MapperScannerConfigurer:在内部调用getMapper()生成每个dao接口的代理对象

-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 指定SqlSessionFactory对象的id-->
        <property name="sqlSessionFactoryBeanName" value="sqlSession"/>
        <!-- 指定包名:包是dao接口所在的包名
        MapperScannerConfigurer会扫描这个包中的所有接口,把每个接口都执行一次getMapper()方法
        得到每个对象的dao接口
        创建好的dao对象放入到spring的容器中的.dao对象的默认名称是接口名首字母小写
        -->
        <!-- 基本类型的赋值,都是使用value,引用类型的赋值,是使用的ref-->
        <property name="basePackage" value="com.jike.dao"/>
    </bean>
<!-- 声明service-->
    <bean id="studentService" class="com.jike.service.Impl.StudentServiceImpl">
        <property name="studentDao" ref="studentDao"/>
    </bean>

第五章 Spring事务(80)

回答问题

1.什么是事务

​ 将mysql的时候,提出了事务,事务是指一组sql语句的集合,集合中有多条sql语句,可能是insert,update,select,delete,我们希望这些sql语句都能成功,或者都失败,这些sql语句的执行是一致的,作为一个整体执行

2.在什么时候想到用事务

当我的操作,涉及多张表,或者多个sql语句的insert,update,delete。需要保证这些语句都是成功擦能完成我的功能,或者都失败 ,保证操作都是符合要求的。

3.通常使用JDBC访问数据库,还是mybatis访问数据库怎么处理事务

jdbc访问数据库,处理事务 Connection conn; conn.commit();conn.rollback();

mybatis访问数据库,处理事务,SqlSession.commit(); SqlSession.rollback();

hibernate访问数据库,处理事务 Session.commit();Session.rollback();

4.3问题中的事务处理的方式,有什么不足

​ 1)不同的数据库访问技术,处理事务的对象,方法不同

​ 需要了解不同数据库访问技术使用事务的原理

2)掌握多种数据库中事务处理逻辑,什么时候提交事务,什么时候回滚事务

3)处理事务的多种方法

总结:就是多种数据库的访问技术,有不同的事务处理机制,对象,方法

5.怎么解决不足

spring提供一种处理事务的统一模型,能使用统一步骤,方式完成多种不同数据库访问技术的事务处理

使用spring的事务处理机制,可以完成mybatis访问数据库的事务处理

使用spring的事务处理机制,可以完成hibernate访问数据库的事务处理

6.处理事务,需要怎么做,做什么

spring处理事务的模型,使用的步骤都是固定的,把事务使用的信息提供给spring就可以了

1)事务内部提交,回滚事务,使用事务管理器对象,代替你完成commit,rollback

​ 事务是一个接口和他的众多实现类

​ 接口:PlatformTransactionManager,定义了事务重要方法commit,rollback

​ 实现类:spring

2)

23

5.1 spring的事务管理

5.2 spring事务管理API

5.3 程序举例环境搭建

ch08-spring-goods:spring和mybatis的集成
步骤:
1.新建maven项目
2.加入maven依赖
   pring依赖,mybatis依赖,mysql驱动,spring的事务的依赖,mybatis和spring集成的依赖:mybatis官方体用的
   用来在spring项目中创建mybatis的SqlSessionFactory,dao对象的
3.创建实体类
sale,goods
4.创建dao接口和mapper文件
saleDao    saleDao.xml
goodsDao   goodsDao.xml
5.创建mybatis的著配置文件
6.创建service接口和实现类,属性是dao
7.创建spring的配置文件:声明mybatis的对象,交给spring创建
      数据源
       sqlsessionfactory
        dao对象
        声明自定义的service
8.创建测试类,获取service对象,通过service调用dao完成数据库的访问

电商购物实现步骤如下:

public class Goods {
    private Integer id;
    private String name;
    private Integer amount;
    private float price;
public class Sale {
    private Integer id;
    private Integer gid;
    private Integer nums;
public interface GoodsDao {
    //goods代表本次用户购买的商品信息,id,购买数量
    int updateGoods(Goods goods);
    Goods selectGoods(Integer id);
}
<mapper namespace="com.jike.dao.GoodsDao">
    <select id="selectGoods" resultType="com.jike.entity.Goods">
        select id,name,amount,price from goods where id=#{gid}
    </select>
    <update id="updateGoods">
        update goods set amount = amount - #{amount} where id=#{id}
    </update>
public interface SaleDao {
    int insertSale(Sale sale);
    List<Sale> selectSale();
}
<mapper namespace="com.jike.dao.SaleDao">
    <insert id="insertSale">
        insert into sale(gid,nums) values(#{gid},#{nums})
    </insert>

    <select id="selectSale" resultType="com.jike.dao.SaleDao">
        select id,gid,nums from sale order by id desc
    </select>
</mapper>
<configuration>
    <!--setting:控制mybatis全局行为-->
    <settings>
        <!--设置mybatis输出日志-->
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    </settings>
    <!--设置别名-->
    <typeAliases>
        <!--name:实体类所在的包名-->
        <package name="com.jike.entity"/>
    </typeAliases>
    <!--sql mapper(sql映射文件)的位置-->
    <mappers>
        <!--name:是包名,这个包中所有mapper.xml一次能加成
         也可以用:<mapper resource=""></mapper>
        -->
        <package name="com.jike.dao"/>
    </mappers>
</configuration>
public interface BuyGoodsService {
    //购买商品,goodsId:购买商品的编号,nums:购买的数量
    void buy(Integer goodsId,Integer nums);
}
public class BuyGoodsServiceImpl implements BuyGoodsService {
    private SaleDao saleDao;
    private GoodsDao goodsDao;

    public void setSaleDao(SaleDao saleDao) {
        this.saleDao = saleDao;
    }

    public void setGoodsDao(GoodsDao goodsDao) {
        this.goodsDao = goodsDao;
    }

    @Override
    public void buy(Integer goodsId, Integer nums) {
        System.out.println("buy方法的开始");
        //记录销售信息,向sale表中添加信息
        Sale sale=new Sale();
        sale.setGid(goodsId);
        sale.setNums(nums);
        saleDao.insertSale(sale);
        //更新库存
        Goods goods=goodsDao.selectGoods(goodsId);
        if (goods ==null){
            throw new NullPointerException("编号是"+goodsId +"不存在");
        }else if (goods.getAmount() < nums){
            throw new NotEnoughExecption("编号是"+goodsId+"商品不足");
        }
        //修改库存
        Goods bygoods=new Goods();
        bygoods.setId(goodsId);
        bygoods.setAmount(nums);
        goodsDao.updateGoods(bygoods);
        System.out.println("buy方法的完成");
    }
<!--把数据库的配置信息,写在一个独立的配置文件中,编译修改数据库的配置内容
    spring知道jdbc.properties文件的位置
-->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <!--声明数据源database,作用是连接数据库的-->
    <bean id="myDatasources" class="com.alibaba.druid.pool.DruidDataSource"
          init-method="init" destroy-method="close">
<!-- set注入给DruidDataSource提供数据连接信息的-->
        <property name="url" value="${jdbc.url}"/>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="maxActive" value="${jdbc.max}"/>
    </bean>
<!--声明的事mybatis提供的sqlSessionFactoryBean类,这个类内部创建SqlSessionFactory的-->
    <bean id="sqlSession" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--set注入,把数据库连接池赋给了dataSources属性-->
        <property name="dataSource" ref="myDatasources"/>
<!-- mybatis主配置文件的位置
     configLocation属性是Resource类型,读取配置文件
     它的赋值,使用value,指定文件的路径,使用classPath:表示文件的位置
-->
        <property name="configLocation" value="classpath:mybatis.xml"/>
    </bean>
<!--创建dao对象,使用sqlSession的getMapper(studentDao.class)
    MapperScannerConfigurer:在内部调用getMapper()生成每个dao接口的代理对象

-->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 指定SqlSessionFactory对象的id-->
        <property name="sqlSessionFactoryBeanName" value="sqlSession"/>
        <!-- 指定包名:包是dao接口所在的包名
        MapperScannerConfigurer会扫描这个包中的所有接口,把每个接口都执行一次getMapper()方法
        得到每个对象的dao接口
        创建好的dao对象放入到spring的容器中的.dao对象的默认名称是接口名首字母小写
        -->
        <!-- 基本类型的赋值,都是使用value,引用类型的赋值,是使用的ref-->
        <property name="basePackage" value="com.jike.dao"/>
    </bean>
<!-- 声明service-->
    <bean id="buyGoodsService" class="com.jike.service.impl.BuyGoodsServiceImpl">
        <property name="goodsDao" ref="goodsDao"/>
        <property name="saleDao" ref="saleDao"/>
    </bean>
Test
public void text01(){
    String config="applicationContext.xml";
    ApplicationContext ap=new ClassPathXmlApplicationContext(config);

    BuyGoodsService buy=(BuyGoodsService) ap.getBean("buyGoodsService");
    buy.buy(1001,3);
}

5.4 使用spring的事务注解管理事务(掌握)

spring框架中提供的事务处理方案

1.适合小项目使用的,注解方案

​ spring框架自己用aop实现给业务方法增加事务的功能,使用@Transactional注解增加事务

​ @Transactional注解是spring框架自己的注解,放在public方法的上面,表示当前方法具有事务

​ 可以给注解的属性赋值,表示具体的隔离级别,传播行为,异常信息等等

使用@Transactional的步骤

1.需要声明事务管理器对象

bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--连接的数据库,指定数据源-->
        <property name="dataSource" ref="myDatasources"/>
    </bean>

2.开启事务注解驱动,告诉spring框架,我要使用注解的方式管理事务

<!--2.开启事务注解驱动,告诉spring框架,我要使用注解的方式管理事务
transaction-manager:事务管理器对象的id
-->
    <tx:annotation-driven transaction-manager="transactionManager"/>

3.在你的方法上面加入@Transactional

@Transactional(
        propagation = Propagation.REQUIRED,
        isolation = Isolation.DEFAULT,
        readOnly = false,
        rollbackFor = {
                NullPointerException.class,NotEnoughExecption.class
        }
)
@Override
public void buy(Integer goodsId, Integer nums) {

5.5 使用AspectJ的AOP配置管理事务(掌握)92

第六章 Spring与Web

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值