Spring5框架 1.Spring框架介绍
Spring是轻量级的开源的JavaEE框架
Spring有两个核心部分:IOC和Aop
IOC:控制反转,把创建对象的过程交给Spring进行管理。
Aop:面向切面,不修改源代码的情况进行功能增强和扩展。
Spring特点:
方便解耦,简化开发。
Aop编程支持
方便程序测试,支持junit4
方便和其他框架进行整合
方便进行事务的操作
降低API开发难度
Spring使用
创建Spring配置文件,在配置文件配置创建的对象。
2.IOC容器(Inversion of control) IOC(Inversion of control):控制反转,把对象创建和对象之间的调用过程,交给Spring进行管理。这种做的好处可以降低耦合度 。
IOC底层原理 xml解析、工厂模式、反射
过程:
第一步:xml配置文件,配置创建的对象。<bean id="user" class="xhh460.User"></bean>
第二步:创建工厂类(进一步降低耦合度)
1 2 3 4 5 6 7 8 9 10 class UserFactory { public static User getUser () { String classValue = class 属性值 ; Class c1 = Class.forName(ClassValue); return (User)c1.newInstance(); } }
IOC接口(BeanFactory)
IOC思想基于IOC容器完成,IOC容器底层就是对象工厂。
Spring提供IOC容器实现两种方式(两个接口):
BeanFactory :IOC容器基本实现,是Spring内部使用的接口,不提供开发人员使用。加载配置文件的时候不会创建对象,在获取对象时才去创建对象。
ApplicationContext :BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员进行使用。加载配置文件时候,就会对配置文件中的对象进行创建。
ApplicationContext接口实现类
一个以类为根,一个以系统为根的文件系统。
IOC操作Bean管理 Bean管理指的是两个操作:
Bean管理操作有两种方式:
基于xml配置文件方式实现
基于注解方式实现
IOC操作Bean管理(基于xml)
1.在spring配置文件中,使用bean标签,标签里面添加对应属性,就可以实现对象创建。
2.在bean标签有很多属性,介绍常用的属性。
id属性:唯一标识
class属性:类全路径(包类路径)
3.创建对象时,默认也是执行无参构造方法完成对象创建。
4.DI:依赖注入,就是注入属性
第一种注入方式:使用set方法进行注入 (1)创建类,定义属性和对应的set方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package xhh460;public class Book { private String bookName; private String author; public void setBookName (String bname) { this .bookName = bname; } public void setAuthor (String author) { this .author = author; } }
(2)在spring配置文件配置对象创建,配置属性注入
第二种注入方式:使用有参数构造进行注入 (1)创建类,定义属性,创建属性对应有参构造方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package xhh460;public class Orders { private String oName; private String address; public Orders (String oName, String address) { this .oName = oName; this .address = address; } }
(2)在spring配置文件配置对象创建,配置构造参数注入
p名称空间注入
使用p名称空间注入,可以简化基于xml配置。
第一步:添加p名称空间在配置文件中。
第二步:进行属性注入,在bean标签里面进行操作。
IOC操作Bean管理(xml注入其他类型属性)
字面量 (1)null值
(2)属性值包含特殊符号
注入属性-外部bean (1)创建两个类:service类和dao类
UserDao.java
1 2 3 4 5 6 7 8 9 package xhh460.dao;public interface UserDao { void update () ; }
UserDaoImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 package xhh460.dao;public class UserDaoImpl implements UserDao { @Override public void update () { System.out.println("dao update...." ); } }
UserService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package xhh460.service;import xhh460.dao.UserDao;import xhh460.dao.UserDaoImpl;public class UserService { private UserDao userDao; public void setUserDao (UserDao userDao) { this .userDao = userDao; } public void add () { System.out.println("service add......." ); userDao.update(); } }
(2)在service调用dao类里面的方法
UserService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package xhh460.service;import xhh460.dao.UserDao;import xhh460.dao.UserDaoImpl;public class UserService { private UserDao userDao; public void setUserDao (UserDao userDao) { this .userDao = userDao; } public void add () { System.out.println("service add......." ); userDao.update(); } }
(3)在spring配置文件中进行配置
注入属性-内部bean (1)一对多关系:部门和员工
一个部门对应多个员工
(2)在实体之间表示一对多关系,员工表示所属部门,使用对象类型属性进行表示。
部门类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package xhh460.bean;public class Dept { private String dname; public void setDName (String dName) { this .dname = dName; } @Override public String toString () { return "Dept{" + "dname='" + dname + '\'' + '}' ; } }
员工类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package xhh460.bean;public class Emp { private String ename; private String gender; private Dept dept; public void setDept (Dept dept) { this .dept = dept; } public void setEname (String ename) { this .ename = ename; } public void setGender (String gender) { this .gender = gender; } }
(3)在Spring配置文件中进行配置
注入属性-级联赋值 (1)第一种写法
(2)第二种写法
IOC操作Bean管理(XML注入集合属性) 注入数组类型属性 注入List集合属性 注入Map集合属性 (1)创建类,定义数组,list,map,set类型属性,生成对应set方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 package xhh460.collectiontype;import java.util.List;import java.util.Map;import java.util.Set;public class Stu { private String[] courses; private List<String> list; private Map<String,String> maps; 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; } }
(2)在Spring配置文件进行配置
java文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 package xhh460.collectiontype;import java.util.Arrays;import java.util.List;import java.util.Map;import java.util.Set;public class Stu { private String[] courses; private List<String> list; private Map<String,String> maps; 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(sets); System.out.println(maps); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 <?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" > <bean id ="stu" class ="xhh460.collectiontype.Stu" > <property name ="courses" > <array > <value > java课程</value > <value > python课程</value > </array > </property > <property name ="list" > <list > <value > 张三</value > <value > 李四</value > </list > </property > <property name ="maps" > <map > <entry key ="JAVA" value ="java" > </entry > <entry key ="Python" value ="python" > </entry > </map > </property > <property name ="sets" > <set > <value > PHP</value > <value > C</value > </set > </property > </bean > </beans >
集合中设置对象类型值 Stu.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 package xhh460.collectiontype;import java.util.Arrays;import java.util.List;import java.util.Map;import java.util.Set;public class Stu { private String[] courses; private List<String> list; private Map<String,String> maps; 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(sets); System.out.println(maps); System.out.println(courseList); } }
Course.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package xhh460.collectiontype;public class Course { private String cname; public void setCname (String cname) { this .cname = cname; } @Override public String toString () { return "Course{" + "cname='" + cname + '\'' + '}' ; } }
XML配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 <?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" > <bean id ="stu" class ="xhh460.collectiontype.Stu" > <property name ="courses" > <array > <value > java课程</value > <value > python课程</value > </array > </property > <property name ="list" > <list > <value > 张三</value > <value > 李四</value > </list > </property > <property name ="maps" > <map > <entry key ="JAVA" value ="java" > </entry > <entry key ="Python" value ="python" > </entry > </map > </property > <property name ="sets" > <set > <value > PHP</value > <value > C</value > </set > </property > <property name ="courseList" > <list > <ref bean ="course1" > </ref > <ref bean ="course2" > </ref > </list > </property > </bean > <bean id ="course1" class ="xhh460.collectiontype.Course" > <property name ="cname" value ="Spring5框架课程" > </property > </bean > <bean id ="course2" class ="xhh460.collectiontype.Course" > <property name ="cname" value ="SpringBoot框架课程" > </property > </bean > </beans >
把集合注入部分提取出来(作为公共部分) (1)在spring配置文件中引入名称空间util
(2)使用util标签完成list集合注入提取
Book.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package xhh460.collectiontype;import java.util.List;public class Book { private List<String> list; public void setList (List<String> list) { this .list = list; } public void test () { System.out.println(list); } }
xml配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <?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:util ="http://www.springframework.org/schema/util" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd" > <util:list id ="bookList" > <value > 零基础学java</value > <value > 零基础学c</value > <value > 零基础学python</value > </util:list > <bean id ="book" class ="xhh460.collectiontype.Book" > <property name ="list" ref ="bookList" > </property > </bean > </beans >
IOC操作Bean管理(FactoryBean) Spring有两种类型bean,一种是bean,另一种是工厂bean(FactoryBean)
普通bean:在配置文件中定义bean类型就是返回类型
工厂bean:在配置文件定义bean类型可以和返回类型不一样
步骤:
创建类,让这个类作为工厂bean,实现接口FactoryBean
实现接口里面的方法,在实现的方法中定义返回的bean类型
bean3.xml
1 2 3 4 5 6 7 8 9 <?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" > <bean id ="myBean" class ="xhh460.factorybean.MyBean" > </bean > </beans >
MyBean.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package xhh460.factorybean;import org.springframework.beans.factory.FactoryBean;import xhh460.collectiontype.Course;public class MyBean implements FactoryBean <Course > { @Override public Course getObject () throws Exception { Course course = new Course(); course.setCname("数据结构" ); return course; } @Override public Class<?> getObjectType() { return null ; } @Override public boolean isSingleton () { return false ; } }
Test.java
1 2 3 4 5 6 @Test public void testMyBean1 () { ApplicationContext context = new ClassPathXmlApplicationContext("bean3.xml" ); Course course = context.getBean("myBean" , Course.class ) ; System.out.println(course.toString()); }
输出:
IOC操作Bean管理(Bean作用域)
在Spring里面,设置创建bean实例单实例还是多实例
在Spring里面,默认情况下,bean是一个单实例对象
如何设置单实例和多实例
(1)在Spring配置文件bean标签里面有属性用于设置单实例还是多实例
(2)scope属性值:singleton(默认值),表示单实例对象 。prototype:表示多实例对象 。
配置多实例:
(3)scope的prototype的区别
singleton
:加载spring配置文件时候就会创建单实例对象。
prototype
:调用getBean方法时创建多实例对象。
IOC操作Bean管理(Bean生命周期) 生命周期是指对象创建到对象销毁的过程
bean生命周期
通过构造器创建bean实例(无参数构造)
为bean的属性设置值和对其他bean引用(调用set方法)
调用bean的初始化方法(需要进行配置初始化的方法)
获取bean实例对象
当容器关闭时候,调用bean的销毁的方法(需要进行配置销毁的方法)
bean生命周期演示
bean的后置处理器 生命周期:
通过构造器创建bean实例(无参数构造)
为bean的属性设置值和对其他bean引用(调用set方法)
把bean实例传递给bean后置处理器的方法(postProcessBeforeInitialization)
调用bean的初始化方法(需要进行配置初始化的方法)
把bean实例传递给bean后置处理器的方法(postProcessAfterInitialization)
获取bean实例对象
当容器关闭时候,调用bean的销毁的方法(需要进行配置销毁的方法)
演示:
(1)创建类,实现接口BeanPostProcessor
,创建后置处理器
MyBeanPost.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package xhh460.bean;import org.springframework.beans.BeansException;import org.springframework.beans.factory.config.BeanPostProcessor;public class MyBeanPost implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization (Object bean, String beanName) throws BeansException { System.out.println("在初始化之前执行的方法" ); return bean; } @Override public Object postProcessAfterInitialization (Object bean, String beanName) throws BeansException { System.out.println("在初始化之后执行的方法" ); return bean; } }
spring配置文件
1 2 3 4 5 6 7 8 9 10 11 12 <?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" > <bean id ="orders" class ="xhh460.bean.Orders" init-method ="initMethod" destroy-method ="destroyMethod" > <property name ="oname" value ="跑步机" > </property > </bean > <bean id ="myBeanPost" class ="xhh460.bean.MyBeanPost" > </bean > </beans >
Test.java
1 2 3 4 5 6 7 8 9 10 11 public class TestSpring { @Test public void testMyBean2 () { ApplicationContext context = new ClassPathXmlApplicationContext("bean4.xml" ); Orders orders = context.getBean("orders" , Orders.class ) ; System.out.println("第四步:获取创建bean实例对象" ); System.out.println(orders); ((ClassPathXmlApplicationContext) context).close(); } }
IOC操作Bean管理(xml自动装配) 自动装配:根据指定装配规则(属性名称或者属性类型),Spring自动将匹配的属性值进行注入。
Emp.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package xhh460.autowire;public class Emp { private Dept dept; public void setDept (Dept dept) { this .dept = dept; } @Override public String toString () { return "Emp{" + "dept=" + dept + '}' ; } public void test () { System.out.println(dept); } }
Dept.java
1 2 3 4 5 6 7 8 9 10 11 12 package xhh460.autowire;public class Dept { @Override public String toString () { return "Dept{}" ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?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" > <bean id ="emp" class ="xhh460.autowire.Emp" autowire ="byName" > </bean > <bean id ="dept" class ="xhh460.autowire.Dept" > </bean > </beans >
IOC操作Bean管理(外部属性文件) 1.配置连接池
1 2 3 4 5 6 7 8 9 10 11 12 <?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" > <bean id ="dataSource" class ="com.alibaba.druid.pool.DruidDataSource" > <property name ="driverClassName" value ="com.mysql.jdbc.Driver" > </property > <property name ="url" value ="jdbc:mysql://localhost:3306/userDb" > </property > <property name ="username" value ="root" > </property > <property name ="password" value ="admin@123" > </property > </bean > </beans >
2.引入外部属性文件配置数据库连接池
(1)创建外部属性文件,properties格式文件,写上数据库信息。
(2)把外部properties属性文件引入到spring配置文件中
引入context名称空间
1 2 3 4 5 6 7 <?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" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/beans/spring-context.xsd" ></beans >
IOC操作Bean管理(基于注解) 注解:
1.注解是代码特殊标记,格式:@注解名称(属性名称=属性值,属性民初=属性值)
2.注解作用在类上面,方法上面,属性上面。
3.使用注解目的:简化xml配置
Spring针对Bean管理中创建对象提供注解
@Component
@Service
@Controller
@Repository
上面四个注解的功能是一样的,都可以用来创建bean实例
基于注解方式实现对象的创建 第一步 引入依赖jar包
spring-aop-5.2.6.RELEASE.jar
第二步 开启组件扫描
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?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" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd" > <context:component-scan base-package ="xhh460.dao,xhh460.service" /> </beans >
第三步:创建类,在类上面添加对象注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package xhh460.service;import org.springframework.stereotype.Component;@Component (value = "userService" ) public class UserService { public void add () { System.out.println("service add......" ); } }
Test.java
1 2 3 4 5 6 7 8 9 public class TestSpring5 { @Test public void testService () { ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml" ); UserService userService = context.getBean("userService" , UserService.class ) ; System.out.println(userService); userService.add(); } }
开启组件扫描细节配置 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 <?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" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd" > <context:component-scan base-package ="xhh460.dao,xhh460.service" /> <context:component-scan base-package ="xhh460" use-default-filters ="false" > <context:include-filter type ="annotation" expression ="org.springframework.stereotype.Controller" /> </context:component-scan > <context:component-scan base-package ="xhh460" > <context:exclude-filter type ="annotation" expression ="org.springframework.stereotype.Controller" /> </context:component-scan > </beans >
基于注解方式实现属性注入 @AutoWired :根据属性类型 进行自动装配
1.把service和dao对象创建,在service和dao类添加创建对象注解
UserDao.java
1 2 3 4 5 6 7 8 9 10 package xhh460.dao;public interface UserDao { public void add () ; }
UserDaoImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package xhh460.dao;import org.springframework.stereotype.Repository;@Repository public class UserDaoImpl implements UserDao { @Override public void add () { System.out.println("dao add.." ); } }
2.在service注入dao对象,在service类添加dao类型属性,在属性上面使用注解
UserService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package xhh460.service;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import org.springframework.stereotype.Service;import xhh460.dao.UserDao;@Service public class UserService { @Autowired private UserDao userDao; public void add () { System.out.println("service add......" ); userDao.add(); } }
bean1.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <?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" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd" > <context:component-scan base-package ="xhh460.dao,xhh460.service" />
TestSpring5.java
1 2 3 4 5 6 7 8 9 public class TestSpring5 { @Test public void testService () { ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml" ); UserService userService = context.getBean("userService" , UserService.class ) ; System.out.println(userService); userService.add(); } }
输出:
@Qualifier :根据属性名称 进行注入
@Qualifier
注解的使用要和@AutoWired
一起使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package xhh460.service;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Component;import org.springframework.stereotype.Service;import xhh460.dao.UserDao;@Service public class UserService { @Autowired @Qualifier (value = "userDaoImpl" ) private UserDao userDao; public void add () { System.out.println("service add......" ); userDao.add(); } }
其他代码跟上面一样。
@Resource :可以根据类型注入,可以根据名称注入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package xhh460.service;import org.springframework.stereotype.Service;import xhh460.dao.UserDao;import javax.annotation.Resource;@Service public class UserService { @Resource (name = "userDaoImpl" ) private UserDao userDao; public void add () { System.out.println("service add......" ); userDao.add(); } }
@Value :注入普通类型属性
直接给属性name赋值abc
完全注解开发 (1)创建配置类,用来替代xml配置文件
SpringConfig.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 package xhh460.config;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;@Configuration @ComponentScan (basePackages = {"xhh460" })public class SpringConfig {}
(2)编写测试类
TestSpring5.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 package xhh460.testdemo;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.annotation.AnnotationConfigApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import xhh460.config.SpringConfig;import xhh460.service.UserService;public class TestSpring5 { @Test public void testService2 () { ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class ) ; UserService userService = context.getBean("userService" , UserService.class ) ; System.out.println(userService); userService.add(); } }
3.Aop(Aspect Oriented Programing) Aop(面向切面编程):利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高开发的效率。
以登录功能为例:
底层原理 Aop底层使用动态代理
创建接口实现类代理对象,增强类的方法
创建子类的代理对象,增强类的方法
JDK动态代理 调用newProxyInstance
方法
该方法有三个参数:
第一个参数:类加载器
第二个参数:增强方法所在的类,这个类实现的接口,支持多个接口
第三个参数:实现这个接口InvocationHandler,创建代理对象,写增强的方法
编写JDK动态代理代码
(1)创建接口,定义方法
UserDao.java
1 2 3 4 5 6 7 8 9 10 11 package xhh460;public interface UserDao { public int add (int a,int b) ; public String update (String id) ; }
(2)创建接口实现类
UserDaoImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package xhh460;public class UserDaoImpl implements UserDao { @Override public int add (int a, int b) { return a+b; } @Override public String update (String id) { return id; } }
(3)使用Proxy类创建接口代理对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 package xhh460;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.util.Arrays;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); } } class UserDaoProxy implements InvocationHandler { private Object obj; public UserDaoProxy (Object obj) { this .obj = obj; } @Override public Object invoke (Object proxy, Method method, Object[] args) throws Throwable { System.out.println("方法之前执行..." +method.getName()+"传递的参数=>" + Arrays.toString(args)); Object res = method.invoke(obj, args); System.out.println("方法之后执行..." +obj); return res; } }
输出结果:
AOP术语 连接点 :类里面的哪些方法可以被增强,这些方法称为连接点。
切入点 :实际被真正增强的方法,称为切入点。
通知(增强) :实际增强的逻辑部分称为通知(增强)。通知有五种类型:
前置通知
后置通知
环绕通知
异常通知
最终通知
切面 :是个动作,把通知应用到切入点过程。
AOP操作(准备) Spring框架一般基于AspectJ 实现AOP操作。
什么是AspectJ?
AspectJ不是Spring组成部分,独立AOP框架,一般把AspectJ和Spring框架一起使用,进行AOP操作。
Aspect实现AOP操作
基于xml配置文件实现
基于注解方式实现(常用)
1.在项目工程中引入AOP相关依赖
2.切入点表达式 (1)切入点表达式作用:知道对哪个类里面的哪个方法进行增强。
(2)语法结构:
execution([权限修饰符][返回类型][类全路径][方法名称][参数列表])
1 2 3 4 5 6 7 8 execution(* xhh460.BookDao.add(..)) execution(* xhh460.BookDao.*(...)) execution(* xhh460.*.*(...))
AOP操作(AspectJ注解) 1.创建类,在类里面定义方法 User.java
1 2 3 4 5 6 7 8 9 10 11 package xhh460.aopanno;public class User { public void add () { System.out.println("add..." ); } }
2.创建增强类(编写增强逻辑) 在增强类里面创建方法,让不同的方法代表不同的通知类型。
UserProxy.java
1 2 3 4 5 6 7 8 9 10 11 12 13 package xhh460.aopanno;public class UserProxy { public void before () { System.out.println("before......." ); } }
3.进行通知的设置 (1)在spring的配置文件中,开启注解扫描
bean1.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <?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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" > <context:component-scan base-package ="xhh460.aopanno" /> </beans >
(2)使用注解创建User和UserProxy对象
(3)在增强类上面添加注解@Aspect
(4)在spring配置文件中开启生成代理对象
bean1.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" > <context:component-scan base-package ="xhh460.aopanno" /> <aop:aspectj-autoproxy /> </beans >
4.配置不同类型的通知 (1)在增强类的里面,在作为通知的方法上面添加通知类型注解,使用切入点表达式配置。
UserProxy.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 package xhh460.aopanno;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.*;import org.springframework.stereotype.Component;@Component @Aspect public class UserProxy { @Before (value = "execution(* xhh460.aopanno.User.add(..))" ) public void before () { System.out.println("before......." ); } @AfterReturning (value = "execution(* xhh460.aopanno.User.add(..))" ) public void afterReturning () { System.out.println("afterReturning........" ); } @After (value = "execution(* xhh460.aopanno.User.add(..))" ) public void after () { System.out.println("after........" ); } @AfterThrowing (value = "execution(* xhh460.aopanno.User.add(..))" ) public void afterThrowing () { System.out.println("afterThrowing........" ); } @Around (value = "execution(* xhh460.aopanno.User.add(..))" ) public void around (ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("环绕之前........" ); proceedingJoinPoint.proceed(); System.out.println("环绕之后........" ); } }
TestAop.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package xhh460.test;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import xhh460.aopanno.User;public class TestAop { @Test public void testAopAnno () { ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml" ); User user = context.getBean("user" , User.class ) ; user.add(); } }
输出结果:
如果方法有异常,则输出:
5.相同切入点抽取 使用@Pointcut
注解来进行相同切入点抽取。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 package xhh460.aopanno;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.*;import org.springframework.stereotype.Component;@Component @Aspect public class UserProxy { @Pointcut (value = "execution(* xhh460.aopanno.User.add(..))" ) public void printDemo () { } @Before (value = "printDemo()" ) public void before () { System.out.println("before......." ); } @AfterReturning (value = "printDemo()" ) public void afterReturning () { System.out.println("afterReturning........" ); } @After (value = "printDemo()" ) public void after () { System.out.println("after........" ); } @AfterThrowing (value = "printDemo()" ) public void afterThrowing () { System.out.println("afterThrowing........" ); } @Around (value = "printDemo()" ) public void around (ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("环绕之前........" ); proceedingJoinPoint.proceed(); System.out.println("环绕之后........" ); } }
6.多个增强类对同一个方法进行增强,设置增强优先级 (1)在增强类上面添加注解@Order(数字类型值),数字类型值越小优先级越高。
User.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package xhh460.aopanno;import org.springframework.stereotype.Component;@Component public class User { public void add () { System.out.println("add..." ); } }
UserProxy.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 package xhh460.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(* xhh460.aopanno.User.add(..))" ) public void printDemo () { } @Before (value = "printDemo()" ) public void before () { System.out.println("before......." ); } @AfterReturning (value = "printDemo()" ) public void afterReturning () { System.out.println("afterReturning........" ); } @After (value = "printDemo()" ) public void after () { System.out.println("after........" ); } @AfterThrowing (value = "printDemo()" ) public void afterThrowing () { System.out.println("afterThrowing........" ); } @Around (value = "printDemo()" ) public void around (ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("环绕之前........" ); proceedingJoinPoint.proceed(); System.out.println("环绕之后........" ); } }
PersonProxy.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package xhh460.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 PersonProxy { @Before (value = "execution(* xhh460.aopanno.User.add(..))" ) public void afterRetuning () { System.out.println("Person Before......." ); } }
bean1.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <?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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" > <context:component-scan base-package ="xhh460.aopanno" /> <aop:aspectj-autoproxy /> </beans >
TestAop.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package xhh460.test;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import xhh460.aopanno.User;public class TestAop { @Test public void testAopAnno () { ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml" ); User user = context.getBean("user" , User.class ) ; user.add(); } }
输出结果:
7.aop完全注解开发 编写配置文件类(取代xml配置文件)
ConfigAop.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package xhh460.config;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.EnableAspectJAutoProxy;@Configuration @ComponentScan (basePackages = {"xhh460" })@EnableAspectJAutoProxy (proxyTargetClass = true )public class ConfigAop {}
TestAop.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package xhh460.test;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.annotation.AnnotationConfigApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import xhh460.aopanno.User;import xhh460.aopxml.Book;import xhh460.config.ConfigAop;public class TestAop { @Test public void testAopAnno () { ApplicationContext context = new AnnotationConfigApplicationContext(ConfigAop.class ) ; User user = context.getBean("user" ,User.class ) ; user.add(); } }
AOP操作(AspectJ配置文件) 1.创建两个类,增强类和被增强类,创建方法
2.在spring配置文件中创建两个类对象
3.在spring配置文件中配置切入点
4.JdbcTemplate 概念:
Spring框架对JDBC进行了封装,使用JdbcTemplate方便实现对数据库操作。
JdbcTemplate配置 1.引入相关依赖jar包
2.在spring配置文件配置数据库连接池
3.配置JdbcTemplate对象,注入DataSource
4.创建service类,创建dao类,在dao注入jdbcTemplate对象
在配置文件中开启组件扫描
bean1.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 <?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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" > <context:property-placeholder location ="classpath:jdbc.properties" /> <context:component-scan base-package ="xhh460" /> <bean id ="dataSource" class ="com.alibaba.druid.pool.DruidDataSource" destroy-method ="close" > <property name ="driverClassName" value ="${prop.driverClassName}" /> <property name ="url" value ="${prop.url}" /> <property name ="username" value ="${prop.username}" /> <property name ="password" value ="${prop.password}" /> </bean > <bean id ="jdbcTemplate" class ="org.springframework.jdbc.core.JdbcTemplate" > <property name ="dataSource" ref ="dataSource" /> </bean > </beans >
BookService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package xhh460.service;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import xhh460.dao.BookDao;@Service public class BookService { @Autowired private BookDao bookDao; }
BookDao.java
1 2 3 4 5 6 7 8 package xhh460.dao;public interface BookDao {}
BookImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package xhh460.dao;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.stereotype.Repository;@Repository public class BookImpl { @Autowired private JdbcTemplate jdbcTemplate; }
JdbcTemplate操作数据库 增删改操作 项目目录:
(1)对应数据库创建实体类
Book.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 package xhh460.entity;public class Book { private String bookId; private String Bookname; private String Bstatus; public void setBookId (String bookId) { this .bookId = bookId; } public void setBookname (String bookname) { Bookname = bookname; } public void setBstatus (String bstatus) { Bstatus = bstatus; } public String getBookId () { return bookId; } public String getBookname () { return Bookname; } public String getBstatus () { return Bstatus; } }
(2)编写Service和Dao
1.在dao进行数据库添加操作
2.调用JdbcTemplate对象里面的update方法实现添加操作
BookDao.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package xhh460.dao;import xhh460.entity.Book;public interface BookDao { void add (Book book) ; void updateBook (Book book) ; void delete (String id) ; }
BookImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 package xhh460.dao;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.stereotype.Repository;import xhh460.entity.Book;@Repository public class BookImpl implements BookDao { @Autowired private JdbcTemplate jdbcTemplate; @Override public void add (Book book) { String sql = "insert into t_book values(?,?,?)" ; Object[] args = {book.getBookId(), book.getBookname(), book.getBstatus()}; int update = jdbcTemplate.update(sql, args); System.out.println(update); } @Override public void updateBook (Book book) { String sql = "update t_book set username=?,ustatus=? where user_id=?" ; Object[] args = {book.getBookname(),book.getBstatus(),book.getBookId()}; int update = jdbcTemplate.update(sql, args); System.out.println(update); } @Override public void delete (String id) { String sql = "delete from t_book where user_id=?" ; int update = jdbcTemplate.update(sql, id); System.out.println(update); } }
BookService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 package xhh460.service;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import xhh460.dao.BookDao;import xhh460.entity.Book;@Service public class BookService { @Autowired private BookDao bookDao; public void addBook (Book book) { bookDao.add(book); } public void updateBook (Book book) { bookDao.updateBook(book); } public void deleteBook (String id) { bookDao.delete(id); } }
TestBook.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 package xhh460.test;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import xhh460.entity.Book;import xhh460.service.BookService;public class TestBook { @Test public void testJdbcTemplate () { ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml" ); BookService bookService = context.getBean("bookService" , BookService.class ) ; Book book = new Book(); bookService.deleteBook("1" ); } }
结果:
1.数据添加成功
2.数据修改成功
3.数据删除成功
查询操作 (1)查询返回某个值
1.查询表里面有多少条记录,返回是某个值
2.使用JdbcTemplate实现查询返回某个值
dao层的文件:
service层的文件:
TestBook.java文件:
(2)查询返回对象
注意:此方法的有个参数BeanPropertyRowMapper<T> rowMapper
底层默认调用的是set方法,所以在此处我们需要把Book实体的各个成员名字对应数据库中的各个成员名字。
1.场景:查询图书详情
2.JdbcTemplate实现查询返回对象
BookService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 package xhh460.service;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import xhh460.dao.BookDao;import xhh460.entity.Book;@Service public class BookService { @Autowired private BookDao bookDao; public void addBook (Book book) { bookDao.add(book); } public void updateBook (Book book) { bookDao.updateBook(book); } public void deleteBook (String id) { bookDao.delete(id); } public int findCount () { return bookDao.selectCount(); } public Book findOne (String id) { return bookDao.findBookInfo(id); } }
Dao层BookImpl.java
TestBook.java
输出结果:
(3)查询返回集合
1.场景:查询图书列表分页
2.调用JdbcTemplate方法实现查询返回集合
BookService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 package xhh460.service;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import xhh460.dao.BookDao;import xhh460.entity.Book;import java.util.List;@Service public class BookService { @Autowired private BookDao bookDao; public void addBook (Book book) { bookDao.add(book); } public void updateBook (Book book) { bookDao.updateBook(book); } public void deleteBook (String id) { bookDao.delete(id); } public int findCount () { return bookDao.selectCount(); } public Book findOne (String id) { return bookDao.findBookInfo(id); } public List<Book> findAll () { return bookDao.findAllBook(); } }
Dao层的BookImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package xhh460.dao;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jdbc.core.BeanPropertyRowMapper;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.stereotype.Repository;import xhh460.entity.Book;import java.util.List;@Repository public class BookImpl implements BookDao { @Autowired private JdbcTemplate jdbcTemplate; @Override public List<Book> findAllBook () { String sql = "select * from t_book" ; List<Book> bookList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Book>(Book.class )) ; return bookList; } }
TestBook.java
批量操作 批量操作表里面的多条记录
批量增加
批量操作方法:batchUpdate(String sql,List<Object[]> batchArgs)
第一个参数:sql语句
第二个参数:List集合,添加多条记录数据
Dao层BookImpl.java
BookService.java
TestBook.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 package xhh460.test;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import xhh460.entity.Book;import xhh460.service.BookService;import java.util.ArrayList;import java.util.List;public class TestBook { @Test public void testJdbcTemplate () { ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml" ); BookService bookService = context.getBean("bookService" , BookService.class ) ; Book book = new Book(); List<Object[]> batchArgs = new ArrayList<>(); Object[] o1 = {"3" ,"java" ,"a" }; Object[] o2 = {"4" ,"python" ,"b" };; Object[] o3 = {"5" ,"php" ,"a" };; Object[] o4 = {"6" ,"C++" ,"a" };; batchArgs.add(o1); batchArgs.add(o2); batchArgs.add(o3); batchArgs.add(o4); bookService.batchAdd(batchArgs); } }
结果:数据添加成功
批量修改
Dao层BookImpl.java
BookService.java
TestBook.java
结果:修改成功
批量删除操作
Dao层的BookImpl.java
BookService.java
TestBook.java
结果:删除成功
5.事务操作 事务是数据库操作最基本单元,逻辑上的一组操作,要么都超过,如果有一个失败则全部失败。
事务四个特性(ACID)
原子性
一致性
隔离性
持久性
事务搭建环境
1.创建数据库,添加记录
2.创建service,搭建dao,完成对象创建和注入关系
(1)在service注入dao,在dao注入JdbcTemplate,在JdbcTemplate注入DataSource。
3.在dao创建两个方法,多钱的方法和少钱的方法,在service创建方法(转账的方法)
dao层次文件
UserDao.java
1 2 3 4 5 6 7 8 9 10 11 12 13 package xhh460.dao;public interface UserDao { public void addMoney () ; public void reduceMoney () ; }
UserDaoImpl.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 package xhh460.dao;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.stereotype.Repository;@Repository public class UserDaoImpl implements UserDao { @Autowired private JdbcTemplate jdbcTemplate; @Override public void reduceMoney () { String sql = "update t_account set money = money-? where username = ?" ; jdbcTemplate.update(sql,100 ,"lucy" ); } @Override public void addMoney () { String sql = "update t_account set money = money+? where username= ?" ; jdbcTemplate.update(sql,100 ,"mary" ); } }
service层文件:
UserService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package xhh460.service;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import xhh460.dao.UserDao;@Service public class UserService { @Autowired private UserDao userDao; public void accountMoney () { userDao.reduceMoney(); userDao.addMoney(); } }
配置文件:
jdbc.properties
1 2 3 4 prop.driverClassName =com.mysql.jdbc.Driver prop.url =jdbc:mysql://localhost:3306/user_db prop.username =root prop.password =admin@123
bean1.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 <?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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" > <context:property-placeholder location ="classpath:jdbc.properties" /> <context:component-scan base-package ="xhh460" /> <bean id ="dataSource" class ="com.alibaba.druid.pool.DruidDataSource" destroy-method ="close" > <property name ="driverClassName" value ="${prop.driverClassName}" /> <property name ="url" value ="${prop.url}" /> <property name ="username" value ="${prop.username}" /> <property name ="password" value ="${prop.password}" /> </bean > <bean id ="jdbcTemplate" class ="org.springframework.jdbc.core.JdbcTemplate" > <property name ="dataSource" ref ="dataSource" /> </bean > </beans >
测试类文件
TestAccount.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package xhh460.test;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import xhh460.service.UserService;public class TestAccount { @Test public void testAccount () { ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml" ); UserService userService = context.getBean("userService" , UserService.class ) ; userService.accountMoney(); } }
结果:
问题分析:
在上面的代码中,如果正常执行则没有问题,但是如果代码执行过程中出现异常,则有问题。
如果在此处出现异常,那么mary不会收到100块。
结果就是:
大体解决思路:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 package xhh460.service;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import xhh460.dao.UserDao;@Service public class UserService { @Autowired private UserDao userDao; public void accountMoney () { try { userDao.reduceMoney(); int i = 10 /0 ; userDao.addMoney(); }catch (Exception e){ } } }
Spring事务管理介绍 1.事务添加到JavaEE三层结构里面的Service层(业务逻辑层)
2.在Spring进行事务管理操作:编程式事务管理 和声明式事务管理(推荐)
3.声明式事务管理:
(1)基于注解方式(推荐)
(2)基础xml配置方式
4.在Spring进行声明式事务管理,底层使用AOP原理。
5.Spring事务管理API
(1)提供一个接口,代表事务管理器,这个接口针对不同的框架提供不同的实现类。
注解声明式事务管理 1.在spring配置文件配置事务管理器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 <?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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd" > <context:property-placeholder location ="classpath:jdbc.properties" /> <context:component-scan base-package ="xhh460" /> <bean id ="dataSource" class ="com.alibaba.druid.pool.DruidDataSource" destroy-method ="close" > <property name ="driverClassName" value ="${prop.driverClassName}" /> <property name ="url" value ="${prop.url}" /> <property name ="username" value ="${prop.username}" /> <property name ="password" value ="${prop.password}" /> </bean > <bean id ="jdbcTemplate" class ="org.springframework.jdbc.core.JdbcTemplate" > <property name ="dataSource" ref ="dataSource" /> </bean > <bean id ="transactionManager" class ="org.springframework.jdbc.datasource.DataSourceTransactionManager" > <property name ="dataSource" ref ="dataSource" /> </bean > </beans >
2.在spring配置文件,开启事务注解
(1)在spring配置文件引入名称空间tx
1 2 3 4 5 6 7 8 9 10 11 12 13 <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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd" >
(2)开启事务注解
3.在service类上面(获取service类里面方法上面)添加事务注解
(1)@Transactional,这个注解添加到类上面,也可以添加到方法上面。
(2)如果把这个注解添加到类上面,这个类里面所有的方法都默认添加上事务
(3)如果把这个注解添加到方法上面,为这个方法添加事务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 package xhh460.service;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;import xhh460.dao.UserDao;@Service @Transactional public class UserService { @Autowired private UserDao userDao; public void accountMoney () { userDao.reduceMoney(); int i = 10 /0 ; userDao.addMoney(); } }
此处注意数据库的存储引擎要改成InnoDB,否则事务不起作用。
TestAccount.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 package xhh460.test;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import xhh460.service.UserService;public class TestAccount { @Test public void testAccount () { ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml" ); UserService userService = context.getBean("userService" , UserService.class ) ; userService.accountMoney(); } }
结果:控制台报错,数据库信息不变,体现了事务的特点。
声明式事务管理参数配置 1.在service类上面添加注解@Transactional,在这个注解里面可以配置事务相参数。
propagation
:事务传播行为,指的是有事务的方法调用没事务的方法,或者没事务的方法调用有事务的方法,或者有事务的方法调用有事务的方法。
在Spring框架中事务传播行为有七种
传播属性
描述
REQUIRED
如果有事务在运行,当前方法就在这个事务内运行,否则,就启动一个新的事务,并在自己的事务内运行
REQUIRED_NEW
当前的方法必须启动新事物,并在它自己的事务内运行,如果有事务正在运行,应该将它挂起
SUPPORTS
如果有事务在运行,当前的方法就在这个事务内运行,否则它不可以运行在事务中
NOT_SUPPORT
当前的方法不应该运行在事务中,如果有运行的事务,将它挂起
MANDATORY
当前的方法必须运行在事务内部,如果没有正在运行的事务,就抛出异常
NEVER
当前的方法不应该运行在事务中,如果有运行的事务,就抛出异常
NESTED
如果有事务在运行,当前的方法就应该在这个事务的嵌套事务内运行。否则,就启动一个新事务,并在它自己的事务内运行。
isolation
:事务隔离级别
(1)事务隔离性:多事务操作时,它们之间不会产生影响。不考虑隔离性会产生很多问题。
(2)脏读:一个未提交事务读取到另一个未提交事务的数据
(3)不可重复读:一个未提交事务读取到另一个提交事务修改后提交的数据
(4)虚读:一个未提交事务读取到另一个事务添加的数据。
通过设置事务隔离性级别,可以解决以上读的问题。
脏读
不可重复读
幻读
READ UNCOMMITTED(读未提交)
有
有
有
READ COMMITTED(读已提交)
无
有
有
REPEATABLE READ(可重复读)
无
无
有
SERIALIZABLE(串行化)
无
无
无
timeout
:超过时间
(1)事务需要在一定的时间内进行提交,如果不提交进行回滚
(2)默认值是-1,时间以秒为单位
readOnly
:是否只读
(1)读:查询操作。写:添加修改操作
(2)readOnly:默认值false,表示可以查询,可以进行添加修改删除操作。
(3)设置readOnly值是true的话,只能查询
rollbackFor
:回滚
(1)设置出现哪些异常进行事务回滚
noRollbackFor
:不回滚
(1)设置出现哪些异常不进行事务回滚
XML声明式事务管理 1.在Spring配置文件中进行配置
2.配置通知
3.配置切入点和切面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 <?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" xmlns:tx ="http://www.springframework.org/schema/tx" xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd" > <context:property-placeholder location ="classpath:jdbc.properties" /> <context:component-scan base-package ="xhh460" /> <bean id ="dataSource" class ="com.alibaba.druid.pool.DruidDataSource" destroy-method ="close" > <property name ="driverClassName" value ="${prop.driverClassName}" /> <property name ="url" value ="${prop.url}" /> <property name ="username" value ="${prop.username}" /> <property name ="password" value ="${prop.password}" /> </bean > <bean id ="jdbcTemplate" class ="org.springframework.jdbc.core.JdbcTemplate" > <property name ="dataSource" ref ="dataSource" /> </bean > <bean id ="transactionManager" class ="org.springframework.jdbc.datasource.DataSourceTransactionManager" > <property name ="dataSource" ref ="dataSource" /> </bean > <tx:advice id ="txadvice" > <tx:attributes > <tx:method name ="accountMoney" propagation ="REQUIRED" /> </tx:attributes > </tx:advice > <aop:config > <aop:pointcut id ="pt" expression ="execution(* xhh460.service.UserService.*(..))" /> <aop:advisor advice-ref ="txadvice" pointcut-ref ="pt" /> </aop:config > </beans >
完全注解开发 1.创建配置类,使用配置类替代xml配置文件
TxConfig.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 package xhh460.config;import com.alibaba.druid.pool.DruidDataSource;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.ComponentScan;import org.springframework.context.annotation.Configuration;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.jdbc.datasource.DataSourceTransactionManager;import org.springframework.transaction.annotation.EnableTransactionManagement;import javax.sql.DataSource;@Configuration @ComponentScan (basePackages = "xhh460" ) @EnableTransactionManagement public class TxConfig { @Bean public DruidDataSource getDruidDataSource () { DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver" ); dataSource.setUrl("jdbc:mysql://localhost:3306/user_db" ); dataSource.setUsername("root" ); dataSource.setPassword("admin@123" ); return dataSource; } @Bean public JdbcTemplate getJdbcTemplate (DataSource dataSource) { JdbcTemplate jdbcTemplate = new JdbcTemplate(); jdbcTemplate.setDataSource(dataSource); return jdbcTemplate; } @Bean public DataSourceTransactionManager getDataSourceTransactionManager (DataSource dataSource) { DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(); transactionManager.setDataSource(dataSource); return transactionManager; } }
TestAccount.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 package xhh460.test;import org.junit.Test;import org.springframework.context.ApplicationContext;import org.springframework.context.annotation.AnnotationConfigApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;import xhh460.config.TxConfig;import xhh460.service.UserService;public class TestAccount { @Test public void testAccount3 () { ApplicationContext context = new AnnotationConfigApplicationContext(TxConfig.class ) ; UserService userService = context.getBean("userService" , UserService.class ) ; userService.accountMoney(); } }
6.Spring5框架新功能 日志封装功能 1.Spring5.0框架自带了通用的日志封装
(1)Spring5已经移除了Log4jConfigListener,官方建议使用Log4j2
(2)Spring5框架整合了Log4j2
第一步:引入相关的jar包
第二步:创建log4j2.xml
配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <?xml version="1.0" encoding="UTF-8"?> <Configuration status ="DEBUG" > <Appenders > <Console name ="Console" target ="SYSTEM_OUT" > <PatternLayout pattern ="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" /> </Console > </Appenders > <Loggers > <Root level ="info" > <AppenderRef ref ="Console" /> </Root > </Loggers > </Configuration >
自定义输出日志
UserLog.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package xhh460.test;import org.slf4j.Logger;import org.slf4j.LoggerFactory;public class UserLog { private static final Logger log = LoggerFactory.getLogger(UserLog.class ) ; public static void main (String[] args) { log.info("hello log4j2" ); log.warn("hello log4j2" ); } }
@Nullable注解 Spring5框架核心容器支持@Nullable注解
(1)@Nullable注解可以使用在方法上面,属性上面,参数上面,表示方法返回可以为空,属性值可以为空,参数值可以为空。
(2)注解用在方法上面,方法返回值可以为空
(3)注解使用在方法参数里面,表示方法参数可以为空
(4)注解使用在属性上面,属性值可以为空。
函数式风格GenericApplicationContext
支持整合JUnit5 整合JUnit4 第一步:引入Spring相关针对测试依赖
第二步:创建测试类,使用注解方式完成
JUnit4.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 package xhh460.test;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import xhh460.service.UserService;@RunWith (SpringJUnit4ClassRunner.class ) //指定单元测试框架 @ContextConfiguration("classpath:bean1.xml") //加载配置文件 public class JUnit4 { @Autowired private UserService userService; @Test public void test1 () { userService.accountMoney(); } }
整合JUnit5 第一步:引入相关jar包
第二步:创建测试类,使用注解方式完成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package xhh460.test;import org.junit.jupiter.api.Test;import org.junit.jupiter.api.extension.ExtendWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit.jupiter.SpringExtension;import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;import xhh460.service.UserService;@SpringJUnitConfig (locations = "classpath:bean1.xml" )public class JUnit5 { @Autowired private UserService userService; @Test public void test1 () { userService.accountMoney(); } }
SpringWebflux 1.SpringWebflux介绍
2.响应式编程
3.Webflux执行流程和核心API