Spring框架详解

article/2025/10/27 22:48:19

简介

Spring5框架

内容介绍:

1.Spring概念

2.IOC容器

3.Aop

4.JDBCTEmplate

5.事物管理

6.Spring5新特性



一.Spring框架概述


1.概述


1.Spring框架是轻量级的JavaEE框架

2.Spring可以解决企业应用开发的复杂性

3.Spring有两个核心部分:IOC和Aop

(1)IOC:控制反转,把创建对象的过程交给Spring进行管理

(2)Aop:面向切面,不修改源代码进行功能增强

4.Spring特点

(1)方便解耦,简化开发

(2)Aop变成支持

(3)方便程序测试

(4)方便和其他框架进行整合

(5)方便进行事物操作

(6)降低API开发难度

5.Spring5



2.入门案例

(1)下载spring

image-20220314143447272

image-20220314143522845

image-20220314143622695

image-20220314144841240

image-20220314144949337

最后是这个网址

https://repo.spring.io/ui/native/release/org/springframework/spring/

image-20220314150504340

下载解压

image-20220314151754577

(2)创建新的项目

(3)导入jar包

image-20220314153934649

image-20220314212314473

把所需的jar包导入其中

导入流程:

在项目文件夹中建立lab文件夹

把jar包放入文件夹中

image-20220314213114546

image-20220314213129097

(4)创建普通类

在这个类中创建普通方法

(5)创建Spring配置文件

在配置文件中配置创建的对象

1.Spring配置文件使用xml文件格式

(6)测试代码编写

二.IOC容器

1.IOC底层原理

(1)什么是IOC

控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。

one:控制反转,把对象的创建和对象的调用过程交给Spring进行管理

two:使用IOC的目的:为了耦合度降低

three:做入门案例就是IOC的实现

(2)IOC底层原理

(1)xml解析,工厂模式,反射

(3)画图讲解IOC底层原理

image-20220316111726329

IOC过程

(1)配置xml文件,配置创建的对象

image-20220316112411751

(2)有service类和dao类,创建工厂类

image-20220316112721282


2.IOC接口(BeanFactory)

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

2.Spring提供IOC容器实现的两种方式:(两个接口

(1)BeanFactory:

IOC容器中最基本实现方式,时Spring内部使用的接口,不提供开发人员进行使用

**特点:**加载配置文件的时候不会去创建对象,在获取对象(使用)才会去创建对象

(2)ApplicationContext:

BeanFactory接口的子接口,提供更多更强大的功能,一般有开发人员进行使用

**特点:**加载配置文件时候就会把在配置文件的对象进行创建

3.ApplicationContext接口有实现类

image-20220316114527826

FlieSystemXmlApplicationContext对应电脑的盘符路径

ClassPathXmlApplicationContext类路径


3.IOC操作Bean管理(基于xml)

(1)Bean管理定义:

Bean管理指的是两个操作

1.Spring创建对象

2.Spring注入属性

(2)Bean管理操作的两种方式

1.基于xml方式创建对象2.基于注解方式的实现

1.基于xml配置文件方式的实现

<!--配置User对象创建--><bean id = "user" class="com.spring.User"></bean>

(1)在Spring中使用bean标签,在标签里面添加对应的属性,就可以实现对象的创建

(2)在bean标签中有许多的属性,介绍常用的属性

*id属性:唯一标识

*class属性:类全路径(包类路径)

*name属性:和id一样,但是在name中可以加入些特殊符号

(3)创建对象的时候,默认是执行无参数构造方法

2.基于xml方式注入属性

(1)DI:依赖注入,就是注入属性

3.第一种注入方式:使用set方法进行注入

(1)创建类,定义属性和对应的set方法

image-20220316194248500

(2)在Spring配置文件配置对象的创建,配置属性注入

image-20220316194814737

最后测试:

image-20220316202247204

image-20220316202302048

4.第二种注入方式:通过有参构造注入

(1)创建类,定义属性,创建属性对应有参数构造方法

image-20220316202928176

(2)在Spring文件中进行配置

image-20220316204015005

测试:
image-20220316204429603

5.p名称空间注入(了解)

(1)使用P名称空间注入,可以简化基于xml配置方式

第一步:添加p名称空间在配置文件中

image-20220316204924233

第二步:进行属性注入,在bean标签里面进行操作

image-20220316205240433

测试:
image-20220316205335414

(3)IOC操作Bean管理(xml注入其他类型的操作)

字面量

one:null值

eg:
image-20220316220057058

image-20220316220409873

测试:

image-20220316220632665

two:属性值包含特殊符号
1.把<>进行转义&lt;&gt;

image-20220316222400727

2.把带特殊符号内容写到CDATA

image-20220316222546173

测试:(两个的输出结果都一样)

image-20220316222636720

three:注入属性-外部bean

1.创建两个类service和dao类

2.在service调用dao里面的方法

3.在Spring配置文件中进行配置

image-20220317192720503

image-20220317192736845

image-20220317192744546

测试:
image-20220317192825321

four:注入属性-内部bean
  1. 一对多关系:部门和员工

    一个部门有多个员工,一个员工属于一个部门

    部门是一,员工是多

  2. 在实体类之间表示一对多的关系,员工表示所属部门,使用对象类型属性进行表示

  3. 在Spring的配置文件中进行配置

image-20220317195858214

image-20220317195915061

image-20220317195933962

测试:

image-20220317200150961

five:注入属性-级联赋值

1.第一种写法

image-20220317201958522

image-20220317202007299

image-20220317202029413

测试:

image-20220317202126805

2.第二种写法

Dept.java

Testbean.java同上

image-20220317202252115

image-20220317202303036

测试:
image-20220317202334223


(4)IOC操作Bean管理(xml注入集合属性)

  1. 注入数组类型属性

  2. 注入List集合类型属性

  3. 注入Map集合类型属性

1.创建类

定义数组,List,Map,Set类型的属性,生成对应的set方法

image-20220317205936079

package com.spring.collectiontype;import java.nio.MappedByteBuffer;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;/*** @author yanchaochao* @date 2022/3/17 20:34*/
public class Stu {//1.数组类型private String[] courses;//2.list集合类型属性private List<String> list;//3.创建Map集合属性private Map<String,String> maps;//4.set集合类型private Set<String> sets;public void setCourses(String[] courses) {this.courses = courses;}public void setList(List<String> list) {this.list = list;}public void setMaps(Map<String, String> maps) {this.maps = maps;}public void setSets(Set<String> sets) {this.sets = sets;}//测试public void test(){System.out.println(Arrays.toString(courses));System.out.println(list);System.out.println(maps);System.out.println(sets);}
}
2.在spring配置文件进行配置

image-20220317213021028

<?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 http://www.springframework.org/schema/beans/spring-beans.xsd"><!--1.集合类型属性注入--><bean id="stu" class="com.spring.collectiontype.Stu"><!--数组类型属性注入--><property name="courses"><array><value>java</value><value>c</value><value>c++</value><value>算法</value><value>mysql</value></array></property><!--list类型属性注入--><property name="list"><list><value>张三</value><value>小三</value></list></property><!--map类型属性注入--><property name="maps"><map><entry key="JAVA" value="java"></entry><entry key="C" value="c"></entry></map></property><!--set类型属性注入--><property name="sets"><set><value>MySQL</value><value>Redis</value></set></property></bean>
</beans>

测试:

image-20220317213049666

package com.spring.testdemo;import com.spring.collectiontype.Stu;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** @author yanchaochao* @date 2022/3/17 21:19*/
public class Testcollectiontype {@Testpublic void testCollection(){ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");Stu stu = context.getBean("stu", Stu.class);stu.test();}
}
3.在集合里设置对象类型值
<!--创建多个course对象--><bean id="course1" class="com.spring.collectiontype.Course"><property name="cname" value="Spring5框架"></property></bean><bean id="course2" class="com.spring.collectiontype.Course"><property name="cname" value="MySQL数据库"></property></bean>
 <!--注入list集合类型,值是对象--><property name="courseList"><list><ref bean="course1"></ref><ref bean="course2"></ref></list></property>
Course.java
package com.spring.collectiontype;/*** @author yanchaochao* @date 2022/3/17 21:40*/
public class Course {private  String cname;//课程名称public void setCname(String cname) {this.cname = cname;}@Overridepublic String toString() {return "Course{" +"cname='" + cname + '\'' +'}';}
}
Stu.java
package com.spring.collectiontype;import java.nio.MappedByteBuffer;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;/*** @author yanchaochao* @date 2022/3/17 20:34*/
public class Stu {//1.数组类型private String[] courses;//2.list集合类型属性private List<String> list;//3.创建Map集合属性private Map<String,String> maps;//4.set集合类型private Set<String> sets;//学生所学多门课程private List<Course>courseList;public void setCourseList(List<Course> courseList) {this.courseList = courseList;}public void setCourses(String[] courses) {this.courses = courses;}public void setList(List<String> list) {this.list = list;}public void setMaps(Map<String, String> maps) {this.maps = maps;}public void setSets(Set<String> sets) {this.sets = sets;}//测试public void test(){System.out.println(Arrays.toString(courses));System.out.println(list);System.out.println(maps);System.out.println(sets);System.out.println(courseList);}
}
bean1.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:lang="http://www.springframework.org/schema/lang"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd"><!--1.集合类型属性注入--><bean id="stu" class="com.spring.collectiontype.Stu"><!--数组类型属性注入--><property name="courses"><array><value>java</value><value>c</value><value>c++</value><value>算法</value><value>mysql</value></array></property><!--list类型属性注入--><property name="list"><list><value>张三</value><value>小三</value></list></property><!--map类型属性注入--><property name="maps"><map><entry key="JAVA" value="java"></entry><entry key="C" value="c"></entry></map></property><!--set类型属性注入--><property name="sets"><set><value>MySQL</value><value>Redis</value></set></property><!--注入list集合类型,值是对象--><property name="courseList"><list><ref bean="course1"></ref><ref bean="course2"></ref></list></property></bean><!--创建多个course对象--><bean id="course1" class="com.spring.collectiontype.Course"><property name="cname" value="Spring5框架"></property></bean><bean id="course2" class="com.spring.collectiontype.Course"><property name="cname" value="MySQL数据库"></property></bean>
</beans>
Testcollectiontype.java
package com.spring.testdemo;import com.spring.collectiontype.Stu;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** @author yanchaochao* @date 2022/3/17 21:19*/
public class Testcollectiontype {@Testpublic void testCollection(){ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");Stu stu = context.getBean("stu", Stu.class);stu.test();}
}

测试:

image-20220317215214058

4.把集合注入的部分提取出来

(1)在spring配置文件中引入名称空间util

(2)使用util标签完成list集合注入提取

Book.java
package com.spring.collectiontype;
import java.util.List;
/*** @author yanchaochao* @date 2022/3/17 21:55*/
public class Book {private List<String>list;public void setList(List<String> list) {this.list = list;}public void test(){System.out.println(list);}
}
bean2.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:util="http://www.springframework.org/schema/util"xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/util  http://www.springframework.org/schema/util/spring-util.xsd"><!--1.提取list集合类型注入--><util:list id="booklist"><value>JAVA</value><value>C</value><value>MySQL</value><value>C++</value><value>Git</value></util:list><!--2.提取list集合类型属性注入使用--><bean id="book" class="com.spring.collectiontype.Book"><property name="list" ref="booklist"></property></bean>
</beans>

测试:

package com.spring.testdemo;import com.spring.collectiontype.Book;
import com.spring.collectiontype.Stu;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** @author yanchaochao* @date 2022/3/17 22:03*/
public class TestBook {@Testpublic void testBook(){ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");Book book = context.getBean("book", Book.class);book.test();}
}

image-20220317221208513


(5)IOC操作Bean管理(FactoryBean)

  1. Spring有两种类型Bean,一种普通bean,另外一种工厂bean(FactoryBean)

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

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

    第一步:创建类,让这个类作为工厂bean,实现接口FactoryBean

    第二步:实现接口里面的方法,在实现的方法中定义返回的bean类型

MyBean.java
package com.spring.factorybean;import com.spring.collectiontype.Course;
import org.springframework.beans.factory.FactoryBean;/*** @author yanchaochao* @date 2022/3/17 22:21*/
public class MyBean implements FactoryBean<Course> {//定义类型和返回类型不一样//定义返回bean@Overridepublic Course getObject() throws Exception {Course course = new Course();course.setCname("abc");return course;}@Overridepublic Class<?> getObjectType() {return null;}@Overridepublic boolean isSingleton() {return FactoryBean.super.isSingleton();}
}
bean3.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:util="http://www.springframework.org/schema/util"xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/util  http://www.springframework.org/schema/util/spring-util.xsd"><bean id="myBean" class="com.spring.factorybean.MyBean"></bean></beans>

测试:

package com.spring.testdemo;import com.spring.collectiontype.Course;
import com.spring.collectiontype.Stu;
import com.spring.factorybean.MyBean;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** @author yanchaochao* @date 2022/3/17 22:23*/
public class Testfactorybean {@Testpublic void testFactoryBean(){ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml");Course course = context.getBean("myBean", Course.class);System.out.println(course);}
}

image-20220317223348754

(6)IOC操作Bean管理(Bean的作用域)

1.在Spring里面,设置创建Bean实例时单实例还是多实例

2.在Spring里面,默认情况下,bean是单实例对象

image-20220317223812033

由图可得出,输出的两个地址是一样的,所以可以得出在默认情况下bean是单实例对象

3.如何设置单实例还是多实例

(1)在Spring配置文件bean标签里面有属性用于设置单实例还是多实例

(2)scope属性值

第一个值 默认值,singleton,表示单实例对象第二个值 prototype,表示多实例对象

image-20220317224833314

测试:

image-20220317224900140

两个对象的地址不一样

(3)singleton和prototype区别

  1. singleton表示单实例,prototype表示多实例

  2. 设置scope值是singleton时候,加载spring的时候就会创建单实例对象

    设置scope值是prototype时候,不是在加载spring配置文件时候创建对象,在调用getBean方法创建多实例对象

(7)IOC操作Bean管理(生命周期)

1.生命周期

从对象到对象销毁的过程

2.bean生命周期

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

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

(3)调用bean的初始化的方法(需要进行配置)

(4)bean可以直接使用了(对象获取到了)

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

3.演示bean的生命周期
Order.java
package com.spring.bean;/*** @author yanchaochao* @date 2022/3/18 19:48*/
public class Order {private String oname;//无参数构造public Order(){System.out.println("第一步,执行无参构造实例");}public void setOname(String oname) {this.oname = oname;System.out.println("第二步,调用set方法调用初始化值");}//创建执行初始化的方法public void initMethod(){System.out.println("第三部,执行初始化方法");}//执行销毁的方法public void destroyMethod(){System.out.println("第五步执行销毁的方法");}
}
bean4.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:util="http://www.springframework.org/schema/util"xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/util  http://www.springframework.org/schema/util/spring-util.xsd"><bean id="orders" class="com.spring.bean.Order" init-method="initMethod" destroy-method="destroyMethod"><property name="oname" value="手机"></property></bean></beans>

测试:

Testbean.java
package com.spring.testdemo;import com.spring.bean.Order;
import com.spring.collectiontype.Book;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** @author yanchaochao* @date 2022/3/18 19:54*/
public class Testbean {@Testpublic void testBook(){ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");Order order = context.getBean("orders", Order.class);System.out.println("第四步,得到对象");System.out.println(order);//手动销毁context.close();}
}

image-20220318201241405

4.bean的后置处理

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

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

(3)把bean实例传递bean后置处理器的方法

postProcessBeforeInitialization

(4)调用bean的初始化的方法(需要进行配置)

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

postProcessAfterInitialization

(6)bean可以直接使用了(对象获取到了)

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

5.演示添加后置处理器效果

(1)创建类,实现接口BeanPostProcessor,创建后置处理器

MyBeanPost.java
package com.spring.bean;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.lang.Nullable;/*** @author yanchaochao* @date 2022/3/18 20:17*/
public class MyBeanPost implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("在初始化之前执行的方法");return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("在初始化之后执行的方法");return bean;}
}
Order.java
package com.spring.bean;/*** @author yanchaochao* @date 2022/3/18 19:48*/
public class Order {private String oname;//无参数构造public Order(){System.out.println("第一步,执行无参构造实例");}public void setOname(String oname) {this.oname = oname;System.out.println("第二步,调用set方法调用初始化值");}//创建执行初始化的方法public void initMethod(){System.out.println("第三部,执行初始化方法");}//执行销毁的方法public void destroyMethod(){System.out.println("第五步执行销毁的方法");}
}
bean4.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:util="http://www.springframework.org/schema/util"xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/util  http://www.springframework.org/schema/util/spring-util.xsd"><bean id="orders" class="com.spring.bean.Order" init-method="initMethod" destroy-method="destroyMethod"><property name="oname" value="手机"></property></bean><!--配置后置处理器--><bean id="myBeanPost" class="com.spring.bean.MyBeanPost"></bean>
</beans>
Testbean.java
package com.spring.testdemo;import com.spring.bean.Order;
import com.spring.collectiontype.Book;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/*** @author yanchaochao* @date 2022/3/18 19:54*/
public class Testbean {@Testpublic void testBook(){ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml");Order order = context.getBean("orders", Order.class);System.out.println("第四步,得到对象");System.out.println(order);//手动销毁context.close();}
}

image-20220318203035929

(8)IOC操作Bean管理(xml自动装配)

1.什么是自动装配

(1)根据指定装配规则(属性名称或者属性类型),spring自动将匹配的属性值进行注入

2.演示自动装配

(1)根据属性名称自动注入

 <!--实现自动装配bean标签属性autowire,配置自动装配autowire属性常用两个值:byName根据属性名称注入,注入值bean的id值和类属性名称一样byType根据属性类型注入--><bean id="emp" class="com.spring.autowire.Emp" autowire="byName">

根据属性名称注入,注入值bean的id值和类属性名称一样

(2)根据属性类型自动注入

   <!--实现自动装配bean标签属性autowire,配置自动装配autowire属性常用两个值:byName根据属性名称注入,注入值bean的id值和类属性名称一样byType根据属性类型注入--><bean id="emp" class="com.spring.autowire.Emp" autowire="byType">

(9)IOC操作Bean管理(外部属性文件)

1.直接配置数据库信息

(1)配置德鲁伊连接池

 <!--直接配置连接池--><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"destroy-method="close"><property name="driverClassName" value="com.mysql.jdbc.Driver" /><property name="url" value="jdbc:mysql://localhost:3306/userDb" /><property name="username" value="root" /><property name="password" value="root" /></bean>
2.引入外部属性文件配置数据库连接池

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

image-20220318213847931

(2)把外部properties属性文件引入到配置文件

*引入context名称空间

<?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:util="http://www.springframework.org/schema/util"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans  http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/util  http://www.springframework.org/schema/util/spring-util.xsdhttp://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context.xsd">

(3)在spring配置文件中使用标签引入外部属性文件

<!--引入外部属性文件-->
<context:property-placeholder location="classpath*:jdbc.properties"></context:property-placeholder><!--配置连接池--><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"destroy-method="close"><property name="driverClassName" value="${prop.driverClass}" /><property name="url" value="${prop.url}" /><property name="username" value="${prop.username}" /><property name="password" value="${prop.password}" /></bean>

4.IOC操作Bean管理(基于注解)

1.什么是注解

(1)注解是代码特殊标记,格式:@注解名称**(属性名称=属性值,属性名称=属性值)**

(2)使用注解,注解作用在类上面,方法上面,属性上面

(3)使用注解目的:简化xml配置

2.Spring针对Bean管理中创建对象提供注解

(1)@Component

(2)@Service

(3)@Controller

(4)@Repository

*上面四个注解功能是一样的,都可以用来创建bean实例

3.基于注解方式实现对象创建

(1)引入依赖

image-20220318220453709

(2)开启组件扫描

(3)创建类,在类上面添加创建对象注解

package com.atguigu.spring5.testdemo;
import com.atguigu.spring5.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** @author yanchaochao* @date 2022/3/22 14:31*/
public class TestSpring5Demo1 {@Testpublic void testService(){ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");UserService userService = context.getBean("userService", UserService.class);System.out.println(userService);userService.add();}
}

image-20220322160123500

实例一:

image-20220322164728767

实例二:

image-20220322164826813

4.基于注解方式实现属性注入

(1)@AutoWired:根据属性类型自动装配

第一步:把service和dao对象创建,在service和dao类添加创建对象注解

第二步:在service注入dao对象,在service类添加dao类型属性,在属性上面使用注解

@Service
public class UserService {//定义dao类型的属性//不需要添加set方法//添加注入属性注解@Autowiredprivate UserDao userDao;public void add(){System.out.println("service add.....");userDao.add();}
}
UserDao.java
package com.atguigu.spring5.dao;
public interface UserDao {public void add();
}
UserDaoImpl
import org.springframework.stereotype.Repository;
@Repository
public class UserDaoImpl implements UserDao{@Overridepublic void add(){System.out.println("dao add...");}
}
UserService.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
@Service
public class UserService {//定义dao类型的属性//不需要添加set方法//添加注入属性注解@Autowiredprivate UserDao userDao;public void add(){System.out.println("service add.....");userDao.add();}
}

测试:

TestSpring5Demo1.java
package com.atguigu.spring5.testdemo;import com.atguigu.spring5.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestSpring5Demo1 {@Testpublic void testService(){ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");UserService userService = context.getBean("userService", UserService.class);System.out.println(userService);userService.add();}
}

image-20220322173557680

(2)@Qualifier:根据属性名称进行注入

这个@Qualifier注解的使用,和上面@Autowired一起使用

(3)@Resource:可以根据类型注入,可以根据名称注入

(4)@Value:注入普通类型属性

5.完全注解开发

(1)创建配置类,替代xml的配置文件

package com.atguigu.spring5.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration  //作为配置类,替代xml配置文件
@ComponentScan(basePackages = {"com.atguigu"})
public class SpringConfig {
}

(2)编写测试类

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


三.AOP

1.简介

AOP(面向切面编程)

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

主要功能

日志记录,性能统计,安全控制,事务处理,异常处理等等。

主要意图

将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。

eg:

image-20220322201401950

2.底层原理

一,AOP底层使用动态代理

(1)有两种情况

第一种:有接口的情况,使用JDK代理

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

image-20220322201819596

第二种:没有接口的情况,使用CGLIB代理

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

image-20220322202018929

3.AOP(JDK动态代理)

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

image-20220322202338715

调用newProxyInstance方法

image-20220322202417803

方法里有三个参数:

one:类加载器

two:增强方法所在的类,这个类实现的接口,支持多个接口

three:实现这个接口InvocationHandler,创建代理对象,写增强的方法

二,JDK动态代理代码

(1)创建接口,定义方法

package com.study;public interface UserDao {public int add(int a,int b);public String update(String id);}

(2)创建接口实现类,实现方法

package com.study;public class UserDaoImpl implements UserDao{@Overridepublic int add(int a, int b) {System.out.println("add方法执行了......");return a+b;}@Overridepublic String update(String id) {System.out.println("update方法执行了......");return id;}
}

(3)使用Proxy类创建接口代理对象

package com.study;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;/*** @author yanchaochao* @date 2022/3/22 20:39*/
public class JDKProxy {public static void main(String[] args) {//创建接口实现类代理对象Class [] interfaces = {UserDao.class};UserDaoImpl userDao = new UserDaoImpl();UserDao dao =(UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));int result = dao.add(1,2);System.out.println("result:"+result);}
}
//创建代理对象代码
class UserDaoProxy implements InvocationHandler{//1.把创建的是谁的代理对象,把谁传递过来//有参数构造传递private Object object;public UserDaoProxy(Object object){this.object = object;}//增强的逻辑@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//方法之前System.out.println("方法之前执行......"+method.getName()+":传递参数..."+ Arrays.toString(args));//被增强的方法Object res = method.invoke(object, args);//方法之后System.out.println("方法执行之后......"+object);return res;}
}

结果:

image-20220322215312057

4.AOP(术语)

一,连接点

二,切入点

三,通知(增强)

四,切面

image-20220322220325201

5.AOP操作(准备)

1.Spring框架一般基于AspectJ实现AOP操作

(1)什么是AspectJ

*AspectJ不是Spring组成部分,独立AOP框架,一般把AspectJ和Spring框架一起使用,进行AOP操作

2.基于AspectJ实现AOP操作

(1)基于xml配置文件实现

(2)jiyu注解方式实现

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

image-20220323171157660

4.切入点表达式

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


(2)语法结构:

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

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

execution(*com.atguigu.dao.BookDao.add(…方法中的参数))

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

execution(*com.atguigu.dao.BookDao. * (…方法中的参数))

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

execution(*com.atguigu.dao. *. * (…方法中的参数))


6.AOP操作(AspectJ注解)

1.创建类,在类里面定义方法
2.创建增强类(编写增强逻辑)

(1)在增强类里面,创建方法,让不同方法代表不同通知类型

package com.study.aopanno;
import org.springframework.stereotype.Component;
//被增强的类
@Component
public class User {public void add (){System.out.println("add...");}
}
package com.study.aopanno;import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;//增强的类
@Component
@Aspect  //生成代理对象
public class UserProxy {//前置通知public void before(){System.out.println("before......");}
}
3.进行通知的配置

(1)在spring配置文件中,开启注解扫描

bean1.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:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!--开启注解扫描--><context:component-scan base-package="com.study.aopanno"></context:component-scan></beans>

(2)使用注解创建User和UserProxy对象

image-20220323175443242

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

image-20220323175619627

(4)在spring配置文件中开启代理生成对象

<!--开启Aspect生成的代理对象-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
4.配置不用类型的通知

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

package com.study.aopanno;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;/*** @author yanchaochao* @date 2022/3/23 17:34*///增强的类
@Component
@Aspect  //生成代理对象public class UserProxy {//前置通知//Before注解表示为前置通知@Before(value = "execution(* com.study.aopanno.User.add(..))")public void before(){System.out.println("before......");}//最终通知@After(value = "execution(* com.study.aopanno.User.add(..))")public void after(){System.out.println("after......");}//后置通知(返回通知)@AfterReturning(value = "execution(* com.study.aopanno.User.add(..))")public void afterReturning(){System.out.println("afterReturning......");}//异常通知@AfterThrowing(value = "execution(* com.study.aopanno.User.add(..))")public void afterThrowing(){System.out.println("afterThrowing......");}//环绕通知@Around(value = "execution(* com.study.aopanno.User.add(..))")public void around(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{System.out.println("环绕之前......");//被增强的方法proceedingJoinPoint.proceed();System.out.println("环绕之后......");}
}

TestAop.java

package com.study.test;import com.study.aopanno.User;
import jdk.jfr.StackTrace;
import org.springframework.context.ApplicationContext;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestAop {@Testpublic void testAopAnno(){ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");User user = context.getBean("user", User.class);user.add();}
}

image-20220323225111843

5.公共切入点抽取
package com.study.aopanno;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;//增强的类
@Component
@Aspect  //生成代理对象public class UserProxy {//相同切入点抽取@Pointcut(value = "execution(* com.study.aopanno.User.add(..))")public void piontdemo(){}//前置通知//Before注解表示为前置通知@Before(value = "piontdemo()")public void before(){System.out.println("before......");}//最终通知@After(value = "execution(* com.study.aopanno.User.add(..))")public void after(){System.out.println("after......");}//后置通知(返回通知)@AfterReturning(value = "execution(* com.study.aopanno.User.add(..))")public void afterReturning(){System.out.println("afterReturning......");}//异常通知@AfterThrowing(value = "execution(* com.study.aopanno.User.add(..))")public void afterThrowing(){System.out.println("afterThrowing......");}//环绕通知@Around(value = "execution(* com.study.aopanno.User.add(..))")public void around(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{System.out.println("环绕之前......");//被增强的方法proceedingJoinPoint.proceed();System.out.println("环绕之后......");}
}

image-20220323225505972

6.有多个增强类多同一个方法进行增强,设置增强类优先级

(1)在增强类上面添加注解@Order(数字类类值),数字类值越小优先级越高

PersonPerxy.java
package com.study.aopanno;import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Component
@Aspect
@Order(1)
public class PersonPerxy {//后置通知(返回通知)@Before(value = "execution(* com.study.aopanno.User.add(..))")public void afterReturning(){System.out.println("Person Before......");}
}
User.java
package com.study.aopanno;
import org.springframework.stereotype.Component;//被增强的类
@Component
public class User {public void add (){System.out.println("add...");}
}
UserProxy.java
package com.study.aopanno;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;//增强的类
@Component
@Aspect  //生成代理对象
@Order(3)
public class UserProxy {//相同切入点抽取@Pointcut(value = "execution(* com.study.aopanno.User.add(..))")public void piontdemo(){}//前置通知//Before注解表示为前置通知@Before(value = "piontdemo()")public void before(){System.out.println("before......");}//最终通知@After(value = "execution(* com.study.aopanno.User.add(..))")public void after(){System.out.println("after......");}//后置通知(返回通知)@AfterReturning(value = "execution(* com.study.aopanno.User.add(..))")public void afterReturning(){System.out.println("afterReturning......");}//异常通知@AfterThrowing(value = "execution(* com.study.aopanno.User.add(..))")public void afterThrowing(){System.out.println("afterThrowing......");}//环绕通知@Around(value = "execution(* com.study.aopanno.User.add(..))")public void around(ProceedingJoinPoint proceedingJoinPoint)throws Throwable{System.out.println("环绕之前......");//被增强的方法proceedingJoinPoint.proceed();System.out.println("环绕之后......");}
}

测试:

package com.study.test;import com.study.aopanno.User;
import jdk.jfr.StackTrace;
import org.springframework.context.ApplicationContext;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestAop {@Testpublic void testAopAnno(){ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");User user = context.getBean("user", User.class);user.add();}
}

image-20220324163819711

7.AOP操作(AspectJ配置文件)

(1)创建两个类,增强类和被增强类,创建方法

package com.study.aopxml;public class Book {public void buy(){System.out.println("buy.......");}
}
package com.study.aopxml;public class BookProxy {public void Before(){System.out.println("before.......");}
}

(2)在spring配置文件中创建两个类对象

(3)在spring配置文件中配置切入点

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 创建对象 --><bean id="book" class="com.study.aopxml.Book"></bean><bean id="bookProxy" class="com.study.aopxml.BookProxy"></bean><!--配置AOP增强--><aop:config><!--切入点--><aop:pointcut id="p" expression="execution(* com.study.aopxml.Book.buy(..))"/><!--配置切面--><aop:aspect ref="bookProxy"><!--增强作用在具体的方法上--><aop:before method="Before" pointcut-ref="p"></aop:before></aop:aspect></aop:config>
</beans>

测试:

@Testpublic void testBook(){ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");Book book = context.getBean("book", Book.class);book.buy();}

image-20220324170748217


完全使用注解开发

不需要创建xml文件

package com.study.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;@Configuration@ComponentScan(basePackages = {"com.study"})@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop {}


四.JdbcTemplate

1.概念和准备

1.什么是JdbcTemplate

Spring框架对JDBC进行封装,使用JdbcTemplate方便对实现数据库操作

2.准备工作

(1)引入相关的jar包image-20220328152239741

image-20220328152320647

(2)在Spring配置文件中配置数据库的连接池

<!--配置连接池--><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"destroy-method="close"><property name="driverClassName" value="${prop.driverClass}" /><property name="url" value="${prop.url}" /><property name="username" value="${prop.username}" /><property name="password" value="${prop.password}" /></bean>

(3)JdbcTemplate对象,注入DataSource

<!--JdbcTemplate对象--><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><!--注入dataSource数据源信息--><property name="dataSource" ref="dataSource"></property></bean>

(4)创建service类,创建dao类,在dao注入jdbcTemplate对象

配置文件中开启组件扫描

<!--组件扫描--><context:component-scan base-package="com.study"></context:component-scan>

service

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

dao

@Repository
public interface BookDao {}
public class BookDaoImpl implements BookDao{//注入JdbcTemplate@Autowiredprivate JdbcTemplate jdbcTemplate;
}

2.JdbcTemplate操作数据库

(1)添加

1.对应数据库创建实体类

image-20220410104650909

2.编写service和dao

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

(2)调用jdbcTemplate对象里面的update方法实现

image-20220410105159471

*有两个参数

*第一个参数:sql语句

*第二个参数:可变参数,设置sql语句值

public class BookDaoImpl implements BookDao{//注入JdbcTemplate@Autowiredprivate JdbcTemplate jdbcTemplate;@Overridepublic void add(Book book) {//1.创建sql语句String sql = "insert into t_book values(?,?,?)";//2.调用方法实现Object [] args = {book.getUserId(),book.getUsername(),book.getUstatus()};int update = jdbcTemplate.update(sql,args);//用法不一
//      int update = jdbcTemplate.update(sql,book.getUserId(),book.getUsername(),book.getUstatus());System.out.println(update);}
}

测试类Test:

package com.study.test;import com.study.entity.Book;
import com.study.service.BookService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** @author yanchaochao* @date 2022/4/10 10:58*/
public class TestBook {@Testpublic void testJdbcTemplate(){ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");BookService bookService = context.getBean("bookService", BookService.class);Book book = new Book();book.setUserId("1");book.setUsername("java");book.setUstatus("a");bookService.addBook(book);}
}

image-20220410112111306

image-20220410112449907


(2)修改删除

//修改@Overridepublic void update(Book book) {//1.创建sql语句String sql = "update t_book set username=?,ustatus=?where user_id=?";//2.调用方法实现Object [] args = {book.getUsername(),book.getUstatus(),book.getUserId()};int update = jdbcTemplate.update(sql,args);System.out.println(update);}//删除@Overridepublic void delete(String id) {//1.创建sql语句String sql = "delete from t_book where  user_id=?";//2.调用方法实现int update = jdbcTemplate.update(sql,id);System.out.println(update);}

测试Test

源数据库

image-20220410115527148

修改:

@Testpublic void testup(){ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");BookService bookService = context.getBean("bookService", BookService.class);//修改Book book = new Book();book.setUserId("1");book.setUsername("javaupup");book.setUstatus("study");bookService.updateBook(book);}

image-20220410115616868

image-20220410115626964

删除:

 @Test//删除public void testdelete(){ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");BookService bookService = context.getBean("bookService", BookService.class);bookService.deleteBook("2");}

image-20220410115707189

image-20220410115719863

(3)查询

1.查询返回某个值

1.查询表里有多少条记录,返回某个值

image-20220410120637509

2.使用JdbcTemplate实现查询返回某个值代码

//查询表记录数@Overridepublic int selectCount() {//1.创建sql语句String sql = "select count(*) from t_book";//2.调用方法实现Integer count = jdbcTemplate.queryForObject(sql, Integer.class);return count;}
@Test//查询表返回某个值public void testselect(){ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");BookService bookService = context.getBean("bookService", BookService.class);int count = bookService.findCount();System.out.println(count);}

此时数据库中有3条数据

image-20220410121305524

执行程序后返回:3

image-20220410121314652


2.查询返回对象

(1)场景:查询图书详细

(2)JdbcTemplate实现查询返回对象

image-20220410134427727

有三个参数:

第一个参数:sql语句

第二个参数:RowMapper,是接口,返回不同类型数据,使用接口里面实现类完成数据封装

第三个参数:sql语句值

//查询返回对象public Book findCountdx(String id){return bookDao.findBookInfo(id);}
//查询返回对象@Overridepublic Book findBookInfo(String id) {//1.创建sql语句String sql = "select * from t_book where user_id=?";//2.调用方法实现Book book = jdbcTemplate.queryForObject(sql,new BeanPropertyRowMapper<Book>(Book.class),id);return book;}
@Test//查询返回对象public void testselectdx(){ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");BookService bookService = context.getBean("bookService", BookService.class);Book book = bookService.findCountdx("1");System.out.println(book);}

image-20220410135641428

image-20220410135656682


3.查询返回集合

(1)场景:查询图书列表分页

(2)调用JdbcTemplate方法实现查询返回集合

image-20220410140153482

有三个参数:

第一个参数:sql语句

第二个参数:RowMapper,是接口,返回不同类型数据,使用接口里面实现类完成数据封装

第三个参数:sql语句值

//查询返回集合public List<Book> findCountjh(){return bookDao.findAllBook();}
@Overridepublic List<Book> findAllBook() {//1.创建sql语句String sql = "select * from t_book ";//2.调用方法实现List<Book> books = jdbcTemplate.query(sql,new BeanPropertyRowMapper<Book>(Book.class));return books;}
@Test//查询返回集合public void testselectjh(){ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");BookService bookService = context.getBean("bookService", BookService.class);List<Book> all = bookService.findCountjh();System.out.println(all);}

image-20220410140849548

image-20220410140803868


(4)批量添加

1.批量操作:操作表里面多条记录

2.JdbcTemplate实现批量添加操作

image-20220410141040597

有两个参数

第一个参数:sql语句

第二个参数:List集合,添加多条记录数据

//批量添加public void batchAdd(List<Object[]>batchArgs){bookDao.batchAddBook(batchArgs);}
    //批量添加@Overridepublic void batchAddBook(List<Object[]> batchArgs) {//1.创建sql语句String sql = "insert into t_book values(?,?,?)";//2.调用方法实现int [] ints = jdbcTemplate.batchUpdate(sql,batchArgs);System.out.println(Arrays.toString(ints));}
@Test//批量添加public void testbatchAdd(){ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");BookService bookService = context.getBean("bookService", BookService.class);List<Object[]>batchArgs = new ArrayList<>();Object[] o1 = {"3","java","a"};Object[] o2 = {"4","c++","b"};Object[] o3 = {"5","MySQL","c"};batchArgs.add(o1);batchArgs.add(o2);batchArgs.add(o3);bookService.batchAdd(batchArgs);}

image-20220410143416367

image-20220410143403581

image-20220410143428501


(5)批量修改

//批量修改public void batchUpdate(List<Object[]>batchArgs){bookDao.batchUpdate(batchArgs);}
 //批量修改@Overridepublic void batchUpdate(List<Object[]> batchArgs) {//1.创建sql语句String sql = "update t_book set username=?,ustatus=?where user_id=?";//2.调用方法实现int [] ints = jdbcTemplate.batchUpdate(sql,batchArgs);System.out.println(Arrays.toString(ints));}
@Test//批量修改public void testbatchUpdate(){ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");BookService bookService = context.getBean("bookService", BookService.class);List<Object[]>batchArgs = new ArrayList<>();Object[] o1 = {"java0909","a3","3"};Object[] o2 = {"c++1010","b4","4"};Object[] o3 = {"MySQL1111","c5","5"};batchArgs.add(o1);batchArgs.add(o2);batchArgs.add(o3);bookService.batchUpdate(batchArgs);}

image-20220410143938993

image-20220410144357899

image-20220410144425107

(6)批量删除

//批量删除public void batchDelete(List<Object[]>batchArgs){bookDao.batchDelete(batchArgs);}
//批量删除@Overridepublic void batchDelete(List<Object[]> batchArgs) {//1.创建sql语句String sql = "delete from t_book where  user_id=?";//2.调用方法实现int [] ints = jdbcTemplate.batchUpdate(sql,batchArgs);System.out.println(Arrays.toString(ints));}
@Test//批量删除public void testbatchDelete(){ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");BookService bookService = context.getBean("bookService", BookService.class);List<Object[]>batchArgs = new ArrayList<>();Object[] o1 = {"3"};Object[] o2 = {"4"};Object[] o3 = {"5"};batchArgs.add(o1);batchArgs.add(o2);batchArgs.add(o3);bookService.batchDelete(batchArgs);}

image-20220410144926945

image-20220410144954069

image-20220410145006387



五.事物

1.什么是事物

(1)事物是数据库操作最基本单元

(2)典型场景:银行转账

*lucy转账100元给mary

*lucy少100,mary多100

2.事物四个特性(ACID)

(1)原子性

(2)一致性

(3)隔离性

(4)持久性

3.搭建事物操作环境

image-20220410150741560

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

image-20220410151241877

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

service注入dao,在dao注入JdbcTemplate注入DataSource

service

@Service
public class UserService {//注入dao@Autowiredprivate UserDao userDao;
}

dao

public interface UserDao {}
@Repository
public class UserDaoImpl implements UserDao{@Autowiredprivate JdbcTemplate jdbcTemplate;}

3.在dao中创建两个方法,多钱方法和少钱的方法,在service创建(转账的方法)

代码如下

bean2.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:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!--组件扫描--><context:component-scan base-package="com.shiwu"></context:component-scan><!--引入外部属性文件--><context:property-placeholder location="classpath*:jdbc.properties"></context:property-placeholder><!--配置连接池--><bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"destroy-method="close"><property name="driverClassName" value="${prop.driverClass}" /><property name="url" value="${prop.url}" /><property name="username" value="${prop.username}" /><property name="password" value="${prop.password}" /></bean><!--JdbcTemplate对象--><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><!--注入dataSource数据源信息--><property name="dataSource" ref="dataSource"></property></bean>
</beans>
UserService.java
package com.shiwu.service;import com.shiwu.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;/*** @author bcy* @date 2022/4/10 15:17*/
@Service
public class UserService {//注入dao@Autowiredprivate UserDao userDao;//转账的方法public void accountMoney(){//lucy少100userDao.reduceMoney();//mary多100userDao.addMoney();}
}
UserDao.java
package com.shiwu.dao;/*** @author yanchaochao* @date 2022/4/10 15:18*/
public interface UserDao {//多钱public void addMoney();//少钱public void reduceMoney();}
UserDaoImpl.java
package com.shiwu.dao;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;/*** @author yanchaochao* @date 2022/4/10 15:18*/
@Repository
public class UserDaoImpl implements UserDao{@Autowiredprivate JdbcTemplate jdbcTemplate;//少钱@Overridepublic void reduceMoney() {String sql = "update t_account set money = money - ?  where username = ?";jdbcTemplate.update(sql,100,"lucy");}//多钱@Overridepublic void addMoney() {String sql = "update t_account set money = money + ?  where username = ?";jdbcTemplate.update(sql,100,"mary");}}

测试:

test.java

package com.shiwu.test;import com.shiwu.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class test {@Testpublic void testAccount(){ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");UserService userService = context.getBean("userService", UserService.class);userService.accountMoney();}
}

image-20220410153740607

image-20220410153711681

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KNkl0w8m-1649754754248)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20220410153800792.png)]

4.模拟转账过程中异常

在lucy给mary转账的过程lucy可能会出现断网问题,lucy钱少了但是mary钱可能没有多。

image-20220411143031130

image-20220411143046788

出现异常:

image-20220411143115893

image-20220411143124464

(1)上面问题如何解决?

*使用事物进行解决

(2)事物操作过程

image-20220411143419514

5.事务操作(介绍)

(1)事物一般添加到JavaEE三层结构里面Service层(业务逻辑层)

(2)在Spring进行事务管理操作

有两种方式:编程式事务管理和声明式事务管理(使用)

(3)声明式事务管理

1.基于注解方式(使用2.基于xml配置文件方式

(4)在Spring进行声明式事务管理,底层使用AOP原理

(5)Spring事务管理API

1.提供一个接口,代表事务管理器,这个接口针对不同的框架提供不同的实现类

image-20220411145546266

6.事务操作(注解声明式事物管理)

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

<!--创建事物管理器--><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><!--注入数据源--><property name="dataSource" ref="dataSource"></property></bean>

2.在spring中配置文件,开启事务注解

(1)在spring配置文件中引入名称空间tx

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

(2)开启事务注解

<!--开启事物注解-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

(3)在Service类上面(获取service类里面方法上面)添加事务注解

*@Transactional可以添加到类上面,也可以添加到方法上面

*如果把这个注解添加到类上面,这个类里面的所有方法都添加事务

*如果把这个注解添加到方法上面,为这个方法添加事务

@Service
@Transactional
public class UserService {

image-20220411151222090

image-20220411151231304

数据库数据未改变

7.事务操作(声明式事物管理参数配置)

(1)配置

在service类上面添加注解@Transactional,在这个注解里面可以配置事务相关参数

image-20220411151737560

(2)propagation:事务传播行为

多事务方法直接进行调用,这个过程中事务时如何进行管理的

image-20220411153226620

image-20220411152932336

image-20220411153353803

(3)ioslation:事务隔离级别

  1. 事务有特性成为隔离性,多事务操作之间不会产生影响。不考虑隔离性产生很多问题
  2. 有三个读问题:脏读,不可重复读,虚(幻)读
  3. 脏读:一个未提交事务读取到另一个未提交事务的数据

image-20220411153724419

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

image-20220411154552547

  1. 虚(幻)读:一个未提交事务读取另一个提交事务添加数据
  2. 解决:通过设置事务隔离级别,解决读问题

image-20220411154907495

(可重复读为默认隔离级别)

image-20220411155039690

(4)timeout:超时时间

1.事务需要在一定时间内进行提交,如果不提交进行回滚

2.默认值是 -1,设置时间以秒单位进行计算

(5)readOnly:是否只读

1.读:查询操作,写:添加修改删除操作

2.readOnly默认值false,表示可以查询,可以添加修改删除操作

3.设置readOnly值是true,设置成true之后,只能查询

(6)rollbackFor:回滚

设置出现哪些异常不进行回滚

(7)noRollbackFor:不回滚

设置出现哪些异常不进行事务回滚

8.事务操作(xml声明式事务管理)

(1)在Spring配置文件中配置

第一步 配置事务管理器

第二步 配置通知

第三步 配置切入点和切面

9.事务操作(完全注解声明式事务管理)

1.创建配置类,使用配置类代替xml配置文件

注:来源于尚硅谷的学习视频
此博客仅为学习笔记


http://chatgpt.dhexx.cn/article/H4FNWrh8.shtml

相关文章

如何搭建一个Spring框架超详细

如何搭建一个Spring框架&#xff0c;首先我们要先了解Spring的核心构成部分 1.Spring 的构成 IOC 控制反转 spring 框架最核心的部分 DAO spring 对 访问数据库的支持 MVC spring 对 mvc设计模式的支持 ORM 对象关系映射 (数据库中的数据映射成对象的技术) 也有针对其它的ORM的…

Eclipse搭建Spring框架(绝对成功!)

花了许久才把Spring框架搭建完成&#xff0c;一把辛酸泪。。。。。。。。。。 一、首先下载好全部所需要的工具和jar包 1 安装 springsource-tool-suite: &#xff08;1&#xff09;打开eclipse-help-marketplace search中输入spring&#xff0c;下载 按install&#xff0c;…

Spring框架的介绍以及搭建

Spring框架的介绍以及搭建 1、框架和架构1.1、什么是框架1.2 架构的发展历程 2、Spring2.1、Spring框架的优势 3、IOC3.1、什么是IOC 4、Maven4、搭建Spring4.1、基于导入jar包和xml配置4.2、基于maven和xml配置4.2.1、本地搭建一个maven4.2.2、创建一个基于Maven的项目4.2.3、…

Spring 框架搭建

1 Spring 框架搭建 第一步&#xff1a;新建 Maven 项目、设置项目坐标以及Maven环境&#xff1a; 设置项目的名称和存放的工作空间&#xff1a; 第二步&#xff1a; 调整JDK版本 <properties><project.build.sourceEncoding>UTF-8</project.build.sourceEnc…

Spring框架介绍与搭建

文章目录 1. 简介1.1 什么是Spring1.2 为什么用Spring1.3 Spring5的特性 2. Spring框架核心2.1 IOC&#xff08;控制反转&#xff09;2.2 AOP(面向切面编程&#xff09;2.3 Spring 中 bean 的作用域2.4 Spring 中 bean 生命周期 3. Spring快速搭建3.1 官方提供的搭建方式3.2 使…

Spring框架搭建

Spring是一个轻量级的开源的控制反转&#xff08;IOC&#xff09;和面向切面编程&#xff08;AOP&#xff09;的框架&#xff0c;是很多程序员必须学的一个框架&#xff0c;所有我们使用他的第一个步骤就是导入框架&#xff0c;本文使用的是idea导入。 Spring有以下几个优点&am…

Python模块——glob模块详解

本文大纲 glob模块也是Python标准库中一个重要的模块&#xff0c;主要用来查找符合特定规则的目录和文件&#xff0c;并将搜索的到的结果返回到一个列表中。使用这个模块最主要的原因就是&#xff0c;该模块支持几个特殊的正则通配符&#xff0c;用起来贼方便&#xff0c;这个…

python—glob模块函数(搜索目录文件)

目录 glob函数 iglob函数 glob模块函数用于从目录通配符搜索中生成文件列表&#xff0c;可以快速获取一定格式的文件夹或文件路径的列表。glob匹配模式较少&#xff0c;一共有三种通配符&#xff1a;*、?、[]&#xff0c;属于轻量级。路径分隔符(Unix的/&#xff0c;Windows…

pathlib.Path模块下的glob、rglob,glob模块下的glob、iglob

1、导入所需模块 from pathlib2 import Path import glob2 as gb 2、当前所在路径 # D:\02周报 p Path.cwd()3、比较Path模块中的glob(*)、glob(**)、rglob(*)、rglob(**) # from pathlib2 import Path# D:\02周报 # p Path.cwd()type(p.glob(r"*")) print("P…

python中的glob.glob()(包含详细实例)

在网上搜了半天没搜到满意的解释&#xff0c;最终选择去原英文文档里寻找其释义&#xff0c;具体如下&#xff1a; glob.glob(pathname, *, root_dirNone, dir_fdNone, recursiveFalse) 其功能是返回一个与pathname匹配的路径名列表&#xff08;该列表可以为空&#xff0c;必…

python 的标准库模块glob使用教程,主要为glob.glob()使用与glob.iglob()使用

欢迎大家关注笔者&#xff0c;你的关注是我持续更博的最大动力 原创文章&#xff0c;转载告知&#xff0c;盗版必究 python 的标准库模块glob使用教程&#xff0c;主要为glob.glob函数使用与glob.iglob函数使用 文章目录&#xff1a; 1 glob模块介绍2 glob模块的具体使用2.1 查…

glob.glob()

glob.glob()函数 glob.glob()含有的内容非常少&#xff0c;其功能是查找符合特定规则的文件路径。例如&#xff08;F:/Python/Hello&#xff09;。 功能类似于Windows的文件搜索。 查找文件只用到三个匹配符&#xff1a;" “,”?", “[]”。 " "&#x…

glob函数

查找符合自己要求的文件 glob.glob() 返回一个列表&#xff0c;列表里的元素是符合要求的文件名&#xff08;字符串&#xff09; 三个匹配符&#xff1a; ”*”匹配任意0个或多个字符 ”?”匹配任意单个字符 ”[ ]”匹配指定范围内的字符 例子1&#xff1a; glob.glob(&q…

python 中的 glob.glob()

1. glob方法&#xff1a; glob模块的主要方法就是glob,该方法返回所有匹配的文件路径列表&#xff08;list&#xff09;&#xff1b; 该方法需要一个参数用来指定匹配的路径字符串&#xff08;字符串可以为绝对路径也可以为相对路径&#xff09;&#xff0c;其返回的文件名只…

python glob函数_Python glob()函数

Python glob()函数&#xff0c;是种文件通配符&#xff0c;非常常用。glob模块提供了函数用于从目录通配符搜索中生成文件列表: Python glob()函数用法 glob()函数可以查找符合自己要求的文件&#xff0c; 支持通配符操作*,**,?,[]这四个通配符&#xff0c; *代表0个或多个字符…

python glob.glob使用

使用了下thrift&#xff0c;出现了一些路径问题。原来是glob.glob函数捣的鬼。所以扒了下英文文档&#xff0c;有些收获。下面分享。 函数功能&#xff1a;匹配所有的符合条件的文件&#xff0c;并将其以list的形式返回。 一.glob.glob的介绍和一些实现细节 1.glob.glob函数的…

glob.glob() 函数

glob模块是最简单的模块之一&#xff0c;内容非常少。用它可以查找符合特定规则的文件路径名。跟使用windows下的文件搜索差不多。查找文件只用到三个匹配符&#xff1a;””, “?”, “[]”。””匹配0个或多个字符&#xff1b;”?”匹配单个字符&#xff1b;”[]”匹配指定…

python glob.glob()

glob是python的一个标准库函数&#xff0c;它的作用类似于shell的find&#xff0c;但是只能返回一级目录的查找结果&#xff0c;支持通配符来查找某个目录的文件&#xff0c;找到的文件列表以list格式返回&#xff0c;如果目录不存在或者找到结果为空&#xff0c;则返回一个空列…

glob.glob()函数

glob.glob()函数 glob.glob(pathname, *, recursiveFalse) 功能&#xff1a;返回一个某一种文件夹下面的某一类型文件路径列表 pathname:文件路径 例如&#xff1a; 返回某一文件下面的pdf文件 import glob f glob.glob(H:\\paper_of_remote_sensing\\paper_of_lidar\\*.…

Linux杂谈之Glob文件名模式匹配

一 Glob ① 初识 glob 最早是出现在类Unix系统的命令行中,是用来匹配文件路径的1&#xff09;在最新的 CentOS 7 中已经删除了 glob 的相关描述文档2&#xff09;删除的原因由于 glob 已经整合到了 shell 之中,然后就有了 shell 通配符常见&#xff1a; 涉及glob的相关命令…