SSM框架教程_Spring+SpringMVC+MyBatisPlus笔记(自学用,持续更新)

视频教程地址
Spring的实现有两种方式,一是配置,二是注解

Spring_day01

IOC、DI

※为什么会有IOC和DI?

因为要解决原有代码开发的问题:
写一个业务层的实现类,实现业务层的接口,然后在里面创建一个数据层的接口,给出一个数据层的实现,然后使用这个接口调对应的方法。
基本上都是这样写的,你把这个项目上线发布运行之后,有一天你想换一下数据层的实现,如下图来了一个全新的实现BookDaoImol2,那你在业务层要不要改,改完是不是又得重新编译、测试、部署、发布,这些工作都要做,所以成本太高。
因此IOC就是来解决这个问题的。
在这里插入图片描述
IOC:控制反转,什么控制反转?创建对象的权利由程序反转到程序外部,也就是有IOC容器来创建对象。
DI:依赖注入,其实就是绑定,绑定什么呢?绑定两个有依赖关系的对象。
在这里插入图片描述
IOC和DI的目标和最终效果

在这里插入图片描述

在这里插入图片描述
使用IOC的步骤

    //1.导入spring的坐标spring-context,对应版本是5.2.10.RELEASE
    
    //2.配置bean-->
    //bean标签标示配置bean
    //id属性标示给bean起名字
    //class属性表示给bean定义类型
    
    //3.获取IoC容器
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
     //4.获取bean(根据bean配置id获取)
//        BookDao bookDao = (BookDao) ctx.getBean("bookDao");   强转对象
//        bookDao.save();

这样一套下来,业务层中的代码就可以不new对象了,改为
在这里插入图片描述

在这里插入图片描述
接上面的IOC,实现DI的步骤

//5.删除业务层中使用new的方式创建的dao对象
//6.提供对应的set方法
 
//7.配置server与dao的关系-->
//property标签表示配置当前bean的属性
//name属性表示配置哪一个具体的属性
//ref属性表示参照哪一个bean
 
 

这里的一个对应关系很重要
在这里插入图片描述

Bean的基本配置、实例化、生命周期

Bean的基本配置

对于bean的基础配置,<bean id=" " class=" "/>

IOC容器为我们创建对象默认为单例的,若想创建个多例的,需要在配置文件配置bean的scope属性

使用bean的scope属性可以控制bean的创建是否为单例:

  • singleton默认为单例
  • prototype为非单例
<bean id="bookDao" name="dao" class="com.itheima.dao.impl.BookDaoImpl" scope="prototype"/>
	//spring报错信息处理,看最后一个报错信息,这个解决了报错也就差不多可以解决,看不懂再看倒数第二个以此类推。

IOC容器创造bean对象其实是调用了构造方法,并且这个方法不论是公有的还是私有的都可以调得到,因为用到了反射。

bean的实例化

因此bean实例化的第一个方法就是使用构造方法。

以前为了解耦,往往不自己new对象,而是交给工厂new,现在呢,静态工厂可以移交给spring来创建对象,需要配置要创造的bean的工厂方法(factory-method):

<!--方式二:使用静态工厂实例化bean-->
<!--    <bean id="orderDao" class="com.itheima.factory.OrderDaoFactory" factory-method="getOrderDao"/>-->

因此bean实例化的第二个方法就是使用静态工厂。

第三个方法:用FactoryBean创建对象,用UserDaoFactoryBean实现spring框架的一个FactoryBean接口,这是一个泛型,需要指定对象,并重写接口的方法,接着在配置文件中配置

<bean id="userDao" class="com.itheima.factory.UserDaoFactoryBean"/>

在这里插入图片描述

训练中的不足1:

  • ctx.getBean()不知道要赋值给谁,并且括号里不知道写什么?
  • 重写FactoryBean接口的getObjectType()方法不知道返回一个什么对象?
  • 写完接口总是忘记实现…
  • 好久没写Java,创建对象总是忘记加new…
  • 业务类调用数据类,service调用dao

bean的生命周期

关于是生命周期的核心问题

  • bean生命周期是什么?
    • bean对象从创建到销毁的整体过程。
  • bean生命周期控制是什么?
    • 在bean创建后到销毁前做一些事情。

生命周期的控制主要由两种方是,第一种就是自己写初始化(init)操作和销毁(destory)操作,然后在配置文件中bean标签中添加init-method="初始化方法名" destroy-method="销毁方法名"而运行后发现销毁方法中的内容并不会执行,why?

  • Spring的IOC容器是运行在JVM中
  • 运行main方法后,JVM启动,Spring加载配置文件生成IOC容器,从容器获取bean对象,然后调方法执行
  • main方法执行完后,JVM退出,这个时候IOC容器中的bean还没有来得及销毁就已经结束了
  • 所以没有调用对应的destroy方法

因此解决方法就是:
关闭容器的两种方式:

  • 使用close方法关闭容器,此方法是ClassPathXmlApplicationContext类的,因此要把ApplicationContext换为ClassPathXmlApplicationContext,
  • 注册钩子关闭容器,在容器未关闭之前,提前设置好回调函数,让JVM在退出之前回调此函数来关闭容器使用registerShutdownHook()方法,使用此钩子方法也需要把ApplicationContext换为ClassPathXmlApplicationContext

至此就介绍完了,但是这些初始化和销毁实现起来步骤比较多也比较乱,Spring提供了两个接口来完成生命周期的控制,好处是可以不用再进行配置init-methoddestroy-method,操作:在业务类实现接口时添加两个接口InitializingBeanDisposableBean并实现接口中的两个方法afterPropertiesSetdestroy,例如:

public class BookServiceImpl implements BookService, InitializingBean, DisposableBean {
    private BookDao bookDao;
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
    public void save() {
        System.out.println("book service save ...");
        bookDao.save(); 
    }
    public void destroy() throws Exception {
        System.out.println("service destroy");
    }
    public void afterPropertiesSet() throws Exception {
        System.out.println("service init");
    }
}

DI相关内容

依赖注入的两类方式

  1. setter注入,有两种引用类型和简单类型(基本类型+String)
  2. 构造器注入,同上

setter注入

setter引用类型注入,现在类中注入setter方法,然后在配置文件中使用property标签注入
例如:<property name="bookDao" ref="bookDao"/>其中ref的值是bean的id,name的值是引用类的对象名。

setter简单类型注入,先在类中声明对应的简单数据类型的属性,并提供对应的setter方法,然后在配置文件中使用property标签注入
例如:<property name="connectionNum" value="10"/>其中name的值是声明的数据类型的名称,value是它的值。

对于setter注入方式的基本使用就已经介绍完了,

  • 对于引用数据类型使用的是<property name="" ref=""/>
  • 对于简单数据类型使用的是<property name="" value=""/>

构造器注入

构造器引用数据类型,删除setter方法,添加带有参数的构造方法,然后在配置文件中使用标签<constructor-arg>,例如<constructor-arg name="bookDao" ref="bookDao"/> 其中name属性对应的值为构造函数中方法形参的参数名,必须要保持一致。ref属性指向的是spring的IOC容器中其他bean对象。

构造器简单数据类型,删除setter方法,添加带有参数的构造方法,然后在配置文件中使用标签<constructor-arg>,例如<constructor-arg name="databaseName" value="mysql"/> 其中name属性同上,value是它的值。

其实这俩在配置文件几乎没有差别不过一个property标签,一个是constructor-arg标签
那这两个如何选择呢?自己开发的模板推荐使用setter方法注入。

※setter与构造器注入小结

  • setter注入

    • 简单数据类型

      <bean ...>
      	<property name="" value=""/>
      </bean>
      
    • 引用数据类型

      <bean ...>
      	<property name="" ref=""/>
      </bean>
      
  • 构造器注入

    • 简单数据类型

      <bean ...>
      	<constructor-arg name="" index="" type="" value=""/>
      </bean>
      
    • 引用数据类型

      <bean ...>
      	<constructor-arg name="" index="" type="" ref=""/>
      </bean>
      
  • 依赖注入的方式选择上

    • 建议使用setter注入
    • 第三方技术根据情况选择
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl" autowire="byType"/>
    
    <!-- bookService依赖bookDao,所以在bookService中配置autowire-->

自动注入

一般采用类型注入(byType),比如bean1依赖bean2,所以我们要在bean1标签的autowire属性中设置为byType,此时bean2甚至都不需要id,IOC就可以帮我们自动注入,当然自动注入只能注入引用类型
环境:
在这里插入图片描述
配置文件:

  <bean class="com.itheima.dao.impl.BookDaoImpl"/>
  <bean id="bookService" autowire="byType" class="com.itheima.service.impl.BookServiceImpl"/>
<!-- bookService依赖bookDao,所以在bookService中配置autowire-->

注意事项:
BookServiceImpl中要调用BookDao的方法,势必要在BookServiceImpl中声明一个BookDao的对象,并且若实现自动注入,则BookServiceImpl中必须有BookDao的setter方法,再进行配置;被注入的对象必须要被Spring的IOC容器管理;按照类型在Spring的IOC容器中如果找到多个对象,会报NoUniqueBeanDefinitionException

集合注入

一共有五种:数组、list、set、map、properties
先声明集合,然后设置集合的setter方法,接着在配置中用property标记相应的bean,如:

<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
                <property name="list">
                    <list>
                        <value>100</value>
                        <value>200</value>
                        <value>300</value>
                    </list>
                </property>
                <property name="array">
                    <array>
                        <value>100</value>
                        <value>200</value>
                        <value>300</value>
                    </array>
                </property>
                <property name="set">
                    <set>
                        <value>itcast</value>
                        <value>itheima</value>
                        <value>boxuegu</value>
                        <value>boxuegu</value>
                    </set>
                </property>
                <property name="map">
                    <map>
                        <entry key="username" value="陈富源"/>
                        <entry key="passWord" value="1234"/>
                    </map>
                </property>
            </bean>

说明:

  • property标签表示setter方式注入,构造方式注入constructor-arg标签内部也可以写<array><list><set><map><props>标签
  • List的底层也是通过数组实现的,所以<list><array>标签是可以混用
  • 集合中要添加引用类型,只需要把<value>标签改成<ref>标签,这种方式用的比较少

Spring_day02

IOC/DI 配置 管理第三方bean

对象有我们自己的IOC帮忙创建的,还有第三方提供的,如何管理这些第三方提供的bean呢?

以Spring的IOC容器来管理Druid连接池对象为例:

1.使用第三方的技术,需要在pom.xml添加依赖

2.在配置文件中将【第三方的类】制作成一个bean,让IOC容器进行管理

3.数据库连接需要基础的四要素驱动连接用户名密码,【如何注入】到对应的bean中(driver,url,username,password)

4.从IOC容器中获取对应的bean对象,将其打印到控制台查看结果。

对于一个陌生的第三方的bean,我们就要探索了,在mvnresportry搜索,然后看他是否可以用构造方法注入,如若不行则用setter方法注入,使用setter方法注入则在配置文件中用property和value标签配置就可。

黑马举两个数据连接池的例子,druid和C3p0

加载properties文件

然而把这些配置写在applicationContext.xml文件中是不合适的,所以我们往往将这些配置写在jdbc.properties中

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/spring_db
jdbc.username=root
jdbc.password=1234

因此要先在applicationContext.xml中进行配置。

修改五个地方:
在这里插入图片描述
在xml中读取jdbc.properties,使用${key}来读取properties配置文件中的内容并完成属性注入

<context:property-placeholder location="jdbc.properties"/>

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="driverClass" value="${jdbc.driver}"/>

    </bean>

到此读取配置文件就介绍完了,然后这里有一个小坑,
如果我在jdbc.properties中写了username而不是jdbc.username,然后在applicationContext.xml中使用${username},则获取到的是并不是我设定的值,而是系统变量的值,如:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

运行结果:

在这里插入图片描述

如何解决这个问题?在xml中设置system-properties-mode=“NEVER”

<context:property-placeholder location="jdbc.properties" system-properties-mode="NEVER"/>

再次运行:
在这里插入图片描述
还有一个注意事项,在xml中加载properties文件时,location="*properties"表示当前类路径下所有的配置文件,但不够规范,应写为location="classpath:*properties",而有时候需要加载jar包中的配置文件,则使用location="classpath*:*properties"

加载properties文件小结

在这里插入图片描述

核心容器

核心容器,可以把它简单的理解为ApplicationContext

创建容器

第一种,就是利用类ClassPathXmlApplicationContext创建
第二种,利用类FileSystemXmlApplicationContext来创建,此方法需要在后面跟配置文件的绝对路径,但是当项目的位置发生变化后,代码也需要跟着改,耦合度较高,不推荐使用。

//第一种
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");	

//第二种
ApplicationContext ctx = new FileSystemXmlApplicationContext("D:\\workspace\\spring\\spring_10_container\\src\\main\\resources\\applicationContext.xml");

获取Bean的三种方式 :

        BookDao bookDao = (BookDao) ctx.getBean("bookDao");			//这种方式存在的问题是每次获取的时候都需要进行类型转换
        BookDao bookDao0 = ctx.getBean("bookBao",BookDao.class);	//这种方式可以解决类型强转问题,但是参数又多加了一个,相对来说没有简化多少。
        BookDao bookDao1 = ctx.getBean(BookDao.class); 				//这种方式就类似我们之前所学习依赖注入中的按类型注入。必须要确保IOC容器中该类型对应的bean对象只能有一个。
        //此三种方法各有利弊,选择合适的就行

从ApplicationContext一直向上找,可以找到BeanFactory,所以ApplicationContext最上级的父接口为 BeanFactory,故我们也可以用BeanFactory来创建IOC容器,但是他有一些东西不够全面,所以逐渐才有了ApplicationContext
在这里插入图片描述

使用 BeanFactory创造IOC容器:

public class AppForBeanFactory {
    public static void main(String[] args) {
        Resource resources = new ClassPathResource("applicationContext.xml");
        BeanFactory bf = new XmlBeanFactory(resources);
        BookDao bookDao = bf.getBean(BookDao.class);
        bookDao.save();
    }
}

ApplicationContext和BeanFactory的区别:

  • BeanFactory是延迟加载,只有在获取bean对象的时候才会去创建

  • ApplicationContext是立即加载,容器加载的时候就会创建bean对象

  • ApplicationContext要想成为延迟加载,只需要在xml中的bean中添加lazy-init并将其设置为true,如:

<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"  lazy-init="true"/>

核心容器总结

这节中没有新的知识点,只是对前面知识的一个大总结,共包含如下内容:

容器相关
  • BeanFactory是IoC容器的顶层接口,初始化BeanFactory对象时,加载的bean延迟加载
  • ApplicationContext接口是Spring容器的核心接口,初始化时bean立即加载
  • ApplicationContext接口提供基础的bean操作相关方法,通过其他接口扩展其功能
  • ApplicationContext接口常用初始化类
    • ClassPathXmlApplicationContext(常用)
    • FileSystemXmlApplicationContext
bean相关

在这里插入图片描述

其实整个配置中最常用的就两个属性idclass

把scope、init-method、destroy-method框起来的原因是,后面注解在讲解的时候还会用到,所以大家对这三个属性关注下。

依赖注入相关

在这里插入图片描述

IOC/DI注解开发

注解开发定义bean
三步走:1.删除配置文件中的bean标签、2.在要创建的bean的类上打注解@Component,注意不要打在接口上,3.在配置中写组件扫描component-scan,并指定路径.
小细节,在@Component后面接(“id名称”),然后在获取bean是用id获取再填后面接的名称就可以一一对应起来了,用这种方式需要xml配置文件,例如

//BookServiceImpl.java
@Component("bookService")
public class BookServiceImpl implements BookService {
    
    public void save() {
        System.out.println("book service save ...");

    }

//App.java
        BookService bookService = (BookService) ctx.getBean("bookService");

;或者也可以用类型获取的方式,在@Component后面什么写不用写,当然如果不起名称,那就需要用类型来找

@Component()
public class BookServiceImpl implements BookService {

    public void save() {
        System.out.println("book service save ...");

    }
}

BookService bookService = (BookService) ctx.getBean(BookService.class);

在这里插入图片描述
全都用@Component可能会分不清,所以衍生三个
//@Component
//@Repository:数据仓库的意思
//@Service:业务,服务的意思
//@Controller:表现,控制的意思
这三个跟Component作用完全一样,只不过换了个名字而已,方便区分

纯注解开发

将配置文件改为一个Java文件然后在里面打入注解@Configration就代替了配置文件,这种开发方式便叫:纯注解开发
这个用来配置的java文件可以主包目录下新建的config包中,也可以直接放在主包目录下,spring均能检测到

纯注解开发步骤:

  1. 在包config下新建Java文件(类名可以为SpringConfig)替换xml文件
  2. 在SpringConfig类上打两个注解@Configration和@ComponentScan,要注明扫描的目录 在主程序中new一个AnnotationConfigApplicationContext类,并在()中写入你的配置Java文件例如SpringConfig.class

总结一下纯注解就是把xml中的配置信息给他体现在Java文件中,怎么体现呢?
答:用注解的方式体现,将某个配置在xml中的功能通过注解在类、属性、方法等等的方式体现出来

纯注解的bean的生命周期

用@PostConstruct和@PreDestroy注解方法,前者就是bean的初始化之前做的事,后者就是销毁之后做的事
在这里呀要关闭容器,我们要调用close方法,但是报错了,我的记忆突然被唤起,ApplicationContext没有close方法,之前学周期的之后说是ClassPathXmlApplicationContext有close方法,此时我们新建的对象是AnnotationConfigApplicationContext啊,所以等我一改成AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);报错取消了,开心~

注解开发依赖注入

纯注解只有自动装配啊,没有什么setter注入,也没有构造器注入,所以用@Autowired来注解,而@Autowired它是按照类型注入。

@Service
public class BookServiceImpl implements BookService {
    //@Autowired:注入引用类型,自动装配模式,默认按类型装配
    
    @Autowired
    private BookDao bookDao;

    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }
}

如果我有两个实现类实现了同一个接口,那么自动注入就会报错啊,所以此时我们可以要用@Repository来表示不同的实现类,以此来达到用id来注入的目的

@Repository("bookDao")
public class BookDaoImpl implements BookDao {
    public void save() {
        System.out.println("book dao save ..." );
    }
}
@Repository("bookDao2")
public class BookDaoImpl2 implements BookDao {
    public void save() {
        System.out.println("book dao save ...2" );
    }
} 

但是这个方法不好,所以一般想用哪个就把@Qualifier注在哪个对象上
注:@Repository注解的作用就是对DAO中的类进行注解,同时给每个类一个标识,也就是到时候将IOC中的bean一一对应起来。

@Service
public class BookServiceImpl implements BookService {
    //@Autowired:注入引用类型,自动装配模式,默认按类型装配

    @Autowired
    //@Qualifier:自动装配bean时按bean名称装配
    @Qualifier("bookDao")
    private BookDao bookDao;

    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }
}

一般来说,dao中的类用@Repository来创建Bean,而service中的类用@Component来创建Bean

value注解既可以设置确定的值,也可以通过("${ }")的方式将配置文件中的值赋值给成员变量,使用之前需要在java配置文件中写入@PropertySource(“jdbc.properties”),括号内为配置文件名,若是多文件则使用数组格式,如

@PropertySource({"jdbc.properties","jdbc1.properties","jdbc1.properties"})

用注解管理第三方bean

主要是使用@Bean注解,在java配置文件中定义相应的方法,并返回对象
但凡整个第三方框架,都要使用@Bean

@Configuration
public class SpringConfig {
    //定义一个方法获得要管理的对象
    @Bean
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/db1");
        ds.setUsername("root");
        ds.setPassword("1234");
        return ds;
    }

}

但是你的jdbc配置写在我SpringConfig中是个什么意思,到时候第三方的配置很多很多,都写在一个文件显然不方便,所以你自己在config包下创建自己的配置类,然后在其中写方法,写相应的配置就ok,写完之后得在总的配置类中汇报一下吧,那就用@Import注解注在SpringConfig上就ok

※注解开发实现为第三方bean注入资源

第三方的Bean我们可以管理了,但是如何为第三方注入资源呢?
注入的资源分为两种,简单类型与引用类型
简单类型就@Value注解;引用类型就在方法中写入你要注入的对象的形参

来一个需求(简单类型):
1.resources目录下添加jdbc.properties

2.配置文件中提供四个键值对分别是数据库的四要素

3.使用@PropertySource加载jdbc.properties配置文件

4.修改@Value注解属性的值,将其修改为${key},key就是键值对中的键的值

完成此需求最主要的就是,一要在SpringConfig中添加@PropertySource({"jdbc.properties"})
二在注解@Value中使用${}来获取properties文件中的键名

那么引用类型呢?首先在第三方配置中扫描要注入的对象类型(用@ComponentScan),然后在第三方配置的方法中添加参数这个参数是引用类型(要注入的对象类型)的,如

//比如我需要在dataSource中输出bookDao对象,如何调用它?采用形参的方式
        /*
        DataSource用于提供物理数据源的连接。作为 DriverManager 工具的替代项,DataSource 对象是获取连接的首选方法
        `在第三方配置DruidDataSource中注入一个BookDao`
         */
@Bean
public DataSource dataSource(BookDao bookDao){

    System.out.println(bookDao);
    DruidDataSource ds = new DruidDataSource();
    ds.setDriverClassName(driver);
    ds.setUrl(url);
    ds.setUsername(userName);
    ds.setPassword(password);
    return ds;
}


引用类型注入只需要为bean定义方法设置形参即可,容器会根据类型自动装配对象。

注解大总结+xml配置对比
在这里插入图片描述
标红的注解是最常用的,在开发中的使用频率起码要在百分之七十以上的~

spring整合mybatis

核心就是Spring帮我们创建SqlSessionFactory对象
大概做两件事:
第一件事是:Spring要管理MyBatis中的SqlSessionFactory(真正需要交给Spring管理的是SqlSessionFactory
第二件事是:Spring要管理Mapper接口的扫描

<!--Spring操作数据库的包-->

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.2.10.RELEASE</version>
    </dependency>

<!--    spring整合mybaits的包-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>1.3.0</version>
    </dependency>

支持Spring与Mybatis的整合就已经完成了,其中主要用到的两个类分别是:

  • SqlSessionFactoryBean
  • MapperScannerConfigurer

说明:

  • 使用SqlSessionFactoryBean封装SqlSessionFactory需要的环境信息

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gwLtzPPZ-1674616058512)(assets/1630138835057.png)]

    • SqlSessionFactoryBean是前面我们讲解FactoryBean的一个子类,在该类中将SqlSessionFactory的创建进行了封装,简化对象的创建,我们只需要将其需要的内容设置即可(但凡是FactoryBean都是造对象的)。
    • 方法中有一个参数为dataSource,当前Spring容器中已经创建了Druid数据源,类型刚好是DataSource类型,此时在初始化SqlSessionFactoryBean这个对象的时候,发现需要使用DataSource对象,而容器中刚好有这么一个对象,就自动加载了DruidDataSource对象。
  • 使用MapperScannerConfigurer加载Dao接口,创建代理对象保存到IOC容器中

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sG977Jru-1674616058513)(assets/1630138916939.png)]

    • 这个MapperScannerConfigurer对象也是MyBatis提供的专用于整合的jar包中的类,用来处理原始配置文件中的mappers相关配置,加载数据层的Mapper接口类
    • MapperScannerConfigurer有一个核心属性basePackage,就是用来设置所扫描的包路径
小结:

domain对应数据源(数据库的字段有什么,domain的成员变量就有什么),和数据库的配置是一起的(domain——SqlSessionFactoryBean)
dao对应SQL语句(dao里面的东西就是把增删改查的SQL语句注在对应的方法上,然后我们调用方法,就会执行相应的SQL语句),是和mapper映射是一起的(dao——MapperScannerConfigurer)

Spring_day03

AOP:面向切面编程

在不改动原始代码的基础上做功能增强
要追加功能的地方叫做切入点
共性的功能(大家都要用的方法)起个名叫“通知”,通知可以按着需求开发好多个,那我怎么知道要在这个切入点执行这个通知呢?所以在通知和切入点之间还有一个东西将他们倒腾在一块,这个东西就叫做切面。又因为方法不能独立存在不许得有类,所以就有了通知类。
连接点是所有方法,但是切入点是需要追加功能的方法。

在这里插入图片描述
在这里插入图片描述
当执行到这个方法的时候,执行切入点要执行的通知(功能)

在这里插入图片描述

在通知类当中定义切入点,将@PointCut注在一个私有的方法上,然后将通知和这个私有的方法绑定,如何绑?在通知上打注解,注解里的参数就是那个私有方法名。

在这里插入图片描述

至此通知类中通知定义好了,切入点也定义好了,也绑在一起了,但是Spring并不能管理这个对象,也不知道他是干AOP的,所以在通知类上加两个注解@Component和@Aspect,最后还要在配置文件中打注解@EnableAspectAutoProxy来告诉Spring我们是采用注解的方式来使用Aop。
实操:

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.10.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
        </dependency>
    </dependencies>

小结:因为原有的代码不用动,所以只需要将所有操作放在一个新的类当中,切入点要在通知类中声明,通知(也就是被共用的方法)要写在通知类中,绑定的注解要打在通知上,然后在通知类上和配置文件中打上与AOP相关的注解。

在这里插入图片描述

在这里插入图片描述
AOP的实现方式其实是采用代理模式实现的,采用代理对象来完成对目标对象的操作,还有功能的增强。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
其实就是怎么描述一个方法,首先这个方法的访问范围吧,哎访问修饰符,然后方法总有返回值吧,然后就是这个方法的位置,包名,然后就是方法需要的参数等等。
这样一个一个写效率太低,所有有了通配符描述,可以通过一句话描述好多方法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
..通配符并不常用,为提高匹配效率一般采用精准匹配或者*匹配

在这里插入图片描述
其中最重要的是@Around

注意事项:
在使用@Around的时候要注意如果切入点的方法有返回值,则需要在通知的方法中写上ProceedingJoinPoint 参数,然后调用proceed方法,最后还要用return语句返回,若不调用proceed方法,则会隔离原始方法,也就是不会调用切入点方法的内容,这个特性有什么作用呢?可以做一些权限校验,你要想运行我的方法必须是经理的权限,那好我先看看你是不是经理,如果不是经理,不好意思这个操作不允许你执行。

在这里插入图片描述
@After和@AfterReturning的区别:
@AfterReturning是成功运行完之后调用,成功运行就意味着不能有异常,所以在抛出异常之后After会继续调用,而@AfterReturning不会调用。

@AfterThrowing是抛出异常之后运行,也就是不出问题不运行,出了问题才运行。

在这里插入图片描述
在这里插入图片描述
最终结果:

在这里插入图片描述

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CFuYuan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值