1 Spring框架概述
1 Spring是轻量级的开源的JavaEE框架
2 Spring可以解决企业应用开发的复杂性
3 Spring有两个核心部分:IOC和Aop
IOC :控制反转,创建对象过程交给Spring进行管理
Aop : 面向切面,不修改源代码进行功能增强
4 Spring特点
- 方便解耦,简化开发
- Aop编程支持
- 方便程序测试
- 方便和其他框架进行整合
- 方便进行事务操作
- 降低API开发难度
下载地址:https://repo.spring.io/ui/native/release/org/springframework/spring/
2 IOC容器
1 IOC 底层原理
1 什么是IOC Inversion of Control
- 控制反转,把对象创建个对象之间的调用过程,交给Spring进行管理
- 使用IOC目的:为了耦合度的降低
2 IOC底层原理
- xml解析,工厂模式,反射
2 IOC接口(BeanFactory)
-
ioc 思想基于IOC容器完成,IOC容器底层就是对象工厂 -
Spring提供IOC容器实现两种方式:(两个接口)
-
BeanFactory: IOC 容器基本实现,Spring内部的使用接口,不提供开发人员试用 加载配置文件时不会创建对象,在获取(使用)对象时才会创建对象 -
ApplicationContext: BeanFactory 接口的子接口,提供更多更强大的功能一般由开发者使用 加载配置文件时就会创建对象 -
ApplicationContext接口有实现类
3 IOC操作Bean管理(基于xml)
1 什么是Bean管理
Bean管理是指两个操作
- Spring创建对象
- Spring注入
2 Bean管理操作有两种方式
- 基于xml配置文件方式
- 基于注解方式实现
1 基于xml方式创建对象
<!--配置User对象创建-->
<bean id="user" class="com.spring.User"></bean>
- 在Spring配置文件中,使用bean标签,标签里面添加相对应属性,就可以实现对象创建
- 在bean标签有很多属性
- id属性:唯一表述
- class属性:类的路径(包类路径)
- 创建对象时默认也是执行无惨构造函数完成对象创建
2 基于xml方式注入属性
-
DI:依赖注入,就是注入属性
-
set方法注入 创建类,定义属性和对应的set方法 在Spring配置文件配置对象创建,配置属性注入
-
使用有参构造函数注入
-
创建类,定义属性,创建属性对应有参构造函数方法 -
在Spring文件中配置
3. p名称空间注入(了解)
1. ? 使用p名称空间注入,可以简化xml配置方式
3 xml注入其他类型属性
1 字面量
- null值
- 特殊符号
4 注入属性-外部bean
? 1 创建两个类service类和dao类
? 2 在service调用dao里面的方法
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配置文件中进行配置
5 注入属性-内部bean
- 一对多关系:部门和员工
- 在实体类之间表示一对多关系
public class Dept {
private String dname;
public void setDname(String dname) {
this.dname = dname;
}
@Override
public String toString() {
return "Dept{" +
"dname='" + dname + '\'' +
'}';
}
}
public class Emp {
private String ename;
private String gender;
private Dept dept;
public Dept getDept() {
return 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;
}
public void add(){
System.out.println(ename+"::"+gender+"::"+dept);
}
}
3.在Spring配置文件中进行配置
6 注入属性——级联赋值
第一种
第二种
7 注入集合属性
? 1.注入数组类型属性
? 2.注入list集合类型属性
? 3.注入Map集合类型属性
public class Stu {
private String[] course;
private List<String> list;
private Map<String,String> map;
private Set<String> sets;
public void setList(List<String> list) {
this.list = list;
}
public void setSets(Set<String> sets) {
this.sets = sets;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setCourse(String[] course) {
this.course = course;
}
}
<bean id="stu" class="com.spring5.collectiontype.Stu">
<property name="course">
<array>
<value>Java</value>
<value>C#</value>
</array>
</property>
<property name="list">
<list>
<value>zhang san</value>
<value>li si</value>
</list>
</property>
<property name="map">
<map>
<entry key="Java" value="java"></entry>
<entry key="PHP" value="php"></entry>
</map>
</property>
<property name="sets">
<set>
<value>MySQL</value>
<value>Redis</value>
</set>
</property>
</bean>
? 4.在集合里面设置对象类型值
<property name="courseList">
<list>
<ref bean="course1"></ref>
<ref bean="course2"></ref>
</list>
</property>
<bean id="course1" class="com.spring5.collectiontype.Course">
<property name="cname" value="Spring5"></property>
</bean>
<bean id="course2" class="com.spring5.collectiontype.Course">
<property name="cname" value="MyBatis"></property>
</bean>
? 5.把集合注入部分提取出来
-
在Spring配置文件中引入名称命名空间util -
<?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.xsd">
</beans>
<util:list id="bookList">
<value>java</value>
<value>php</value>
<value>c</value>
</util:list>
<bean id="book" class="com.spring5.collectiontype.Book">
<property name="list" ref="bookList"></property>
</bean>
4 IOC操作Bean管理(FactoryBean)
-
Spirng有两种类型的bean,一种是普通bean,另一种工厂bean(factorybean) -
普通bean:在配置文件中定义bean类型就是返回类型 -
工厂bean:在配置文件中定义bean类型可以与返回类型不一样 ? 创建类,让这个类作为工厂bean,实现接口factorybean ? 实现接口里面的方法,在实现的方法中定义返回的bean类型 public class MyBean implements FactoryBean<Course> {
@Override
public Course getObject() throws Exception {
Course course = new Course();
course.setCname("abc");
return course;
}
@Override
public Class<?> getObjectType() {
return null;
}
@Override
public boolean isSingleton() {
return FactoryBean.super.isSingleton();
}
}
@Test
public void test3(){
ApplicationContext context =new ClassPathXmlApplicationContext("bean3.xml");
Course course = context.getBean("myBean", Course.class);
System.out.println(course);
}
}
5 IOC操作Bean管理(Bean作用域)
-
在Spring里面,设置创建bean实例是单实例还是多实例 -
在Spring里面,默认情况下,bean是单实例对象
@Testpublic
void testCollection2(){
ApplicationContext context =new ClassPathXmlApplicationContext("bean2.xml");
Book book = context.getBean("book", Book.class);
Book book1 = context.getBean("book", Book.class);
System.out.println(book);
System.out.println(book1);
}
3.如何设置是单实例还是多实例
-
在Spring配置文件bean标签里面有属性scope用于设置单实例还是多实例 -
scope属性值 第一个值默认值,singleton,表示是单实例对象 第二个值prototype,表示是多实例对象 <bean id="book" class="com.spring5.collectiontype.Book" scope="prototype">
<property name="list" ref="bookList">
</property>
</bean>
@Testpublic
void testCollection2(){
ApplicationContext context =new ClassPathXmlApplicationContext("bean2.xml");
Book book = context.getBean("book", Book.class);
Book book1 = context.getBean("book", Book.class);
System.out.println(book);
System.out.println(book1);
}
3. singleton和prototype区别
1. singleton是单实例,prototype是多实例
2. 设置scope值是sington时,加载Spring配置文件时候就会创建单实例对象
3. 设置scope值是prototype时,不是在加载Spring文件时候创建对象,在调用getBean方法时创建多实例对象
## 6 IOC操作Bean管理(bean生命周期)
1. 声明周期
1. 从对象的创建到对象的销毁过程
2. bean生命周期
1. 通过构造器创建bean实例(无惨构造)
2. 为bean的属性设置和其他bean引用(调用set方法)
3. 调用bean的初始化方法
4. bean可以使用了
5. 当容器关闭时候,调用bean的销毁的方法
3. 演示bean生命周期
```java
public class Orders {
public Orders() {
System.out.println("第一步,调用无参构造");
}
private String oname;
public void setOname(String oname){
this.oname=oname;
System.out.println("第二步,调用set方法设置属性值");
}
//创建执行初始化的方法
public void initMethod(){
System.out.println("第三步,执行初始化方法");
}
//销毁的方法
public void destroyMethod(){
System.out.println("第五步,销毁");
}
}
@Test
public void testBean3(){
ClassPathXmlApplicationContext context =new ClassPathXmlApplicationContext("bean4.xml");
Orders orders = context.getBean("orders", Orders.class);
System.out.println("第四步,获取创建bean实例对象");
System.out.println(orders);
context.close();
}
<bean id="orders" class="com.spring5.bean.Orders" init-method="initMethod" destroy-method="destroyMethod">
<property name="oname" value="shouji">
</property>
</bean>
4.bean声明周期后置处理
-
通过构造器创建bean实例(无惨构造) -
为bean的属性设置和其他bean引用(调用set方法) -
把bean实例传递给bean后置处理器 postProcessBeforeInitialization -
调用bean的初始化方法 -
把bean实例传递bean后置处理器的方法 postProcessAfterInitialization -
bean可以使用了 -
当容器关闭时候,调用bean的销毁的方法 -
演示添加后置处理器效果
- 创建类,实现接口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;
}
}
7 IOC操作Bean管理(XML方式自动装配)
1 什么是自动装配
-
根据指定装配规则(属性名称或者属性类型),Spring自动将匹配的属性值进行注入 -
演示自动装配过程
根据名称注入
<bean id="emp" class="com.spring5.aotowire.Emp" autowire="byName">
</bean>
<bean id="dept" class="com.spring5.aotowire.Dept"></bean>
根据类型注入
<bean id="emp" class="com.spring5.aotowire.Emp" autowire="byType">
</bean>
<bean id="dept" class="com.spring5.aotowire.Dept"></bean>
8 IOC操作Bean管理(外部属性文件)
-
直接配置数据库信息
- 配置德鲁伊连接池
- 引入德鲁伊连接池依赖jar包
<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="root"></property>
</bean>
-
引入外部文件配置数据库连接池
- 创建外部属性文件,properties格式文件,写数据库信息
prop.driverClass=com.mysql.jdbc.Driverprop.url=jdbc:mysql://localhost:3306/userDbprop.userName=rootprop.password=root
-
把外部properties属性文件引入到Spring配置文件中 引入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: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">
在Spring配置文件中使用标签引入外部属性文件
<context:property-placeholder location="jdbc.properties"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${prop.driverClass}"></property>
<property name="url" value="${prop.url}"></property>
property name="username" value="${prop.userName}"></property>
<property name="password" value="${prop.password}"></property>
</bean>
9 IOC操作Bean管理(基于注解方式)
-
什么是注解
- 注解是代码特殊标记,格式:@注解名称
- 使用注解,注解作用在类,方法,属性
- 使用目的:简化xml配置
-
Spring针对Bean管理中创建对象提供注解
- @Component
- @Service
- @Controller
- @Repository
上述四个注解功能是一样的,都可以用来创建bean实例 -
基于注解方式实现对象创建
- 引入依赖
- 开启组件扫描
<context:component-scan base-package="com.spring5"></context:component-scan>
3.创建类,在类上面创建对象注解
@Service(value = "userService")
public class UserService {
public void add(){
System.out.println("service add........");
}
}
-
开启组件扫描的细节
<context:component-scan base-package="com.spring5" use-default-filters="false">
<context:include-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<context:component-scan base-package="com.spring5">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
5.基于注解方式属性注入
-
@AutoWired: 根据属性类型进行自动装配
- 把service和dao 对象创建,在service和dao类添加创建对象注解
- 在service注入dao对象,在service类添加dao类型属性,在属性上面使用注解
@Service(value = "userService")
public class UserService {
@Autowired
private UserDao userDao;
public void add(){
System.out.println("service add........");
userDao.add();
}
}
-
@Qualifier:根据属性名称进行注入
- @Qualifier注解的使用,和@AutoWired一起使用
@Autowired
@Qualifier(value = "userDaoImpl1")
private UserDao userDao;
-
@Resource:根据类型注入,可以根据名称注入
@Resource(name = "userDaoImpl1")
private UserDao userDao;
-
@Value:注入普通类型 @Value(value = "zhangsan")
private String name ;
6.完全注解开发
-
创建配置类,替代xml配置文件 @Configuration
@ComponentScan(basePackages = {"com.spring5"})
-
编写测试类 @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
1 什么是AOP
- 面向切面编程(方面),利用aop可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用行,同时提高了开发的效率。
- 通俗描述:不通过修改源代码方式,在主干功能里面添加新功能
- 使用登录例子说明aop
2 AOP底层原理
1 AOP底层使用了动态代理
-
有两种情况的动态代理
-
有接口,使用JDK动态代理 创建接口实现类代理对象,增强类的方法
- 没有接口,使用CGLIB动态代理
2 AOP(JDK动态代理)
-
使用jdk动态代理,使用proxy类里面的方法创建代理对象
-
调用newProxyInstance方法 ? 有三个参数: ? 第一个参数,类加载器 ? 第二个参数,增强方法所在的类,这个类实现的接口,支持多个接口 ? 第三个参数,实现这个接口InvocaHandler,创建代理对象,写增强的方法 -
编写JDK动态代理代码
- 创建接口,定义方法
public interface UserDao {
public int add(int a,int b);
public String update(String id);
}
-
创建接口实现类,实现方法 public class UserDaoImpl implements UserDao{
@Override
public int add(int a, int b) {
return a+b;
}
@Override
public String update(String id) {
return id;
}
}
- 使用Proxy类创建接口代理对象
package com.spring5;
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));
String ni = dao.update("ni");
System.out.println("id为:"+ni);
}
}
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;
}
}
3 AOP(术语)
-
连接点 类里面哪些方法可以被增强,这些方法称为连接点 -
切入点 实际被正真增强的方法,称为切入点 -
通知(增强)
- 实际增强的逻辑部分称为通知(增强)
- 通知有多种类型
- 前置通知
- 后置通知
- 环绕通知
- 异常通知
- 最终通知 类似于try catch中的finally
-
切面 是动作,把通知应用到切入点过程
4 AOP操作(准备)
-
Spring框架中一般都只基于AspectJ实现AOP操作
-
什么是AspeJ AspeJ不是Spring组成部分,独立AOP框架,一般把AspectJ和Spring框架一起使用,进行AOP操作 -
基于AspectJ实现AOP操作
- 基于xml配置文件实现
- 基于注解方式实现(使用)
-
在项目工程里面引入AOP相关依赖 -
切入点表达式
-
切入点表达式作用:知道对哪个类里面的哪个方法进行增强 -
语法结构: execution([权限修饰符] [返回类型] [类全路径] [方法名称] ([参数列表])) -
举例
-
对com.dao.BookDao类里面的add进行增强 execution(*com.dao.BookDao.add(…)) -
对com.dao.BookDao类里面的所有方法进行增强 execution(*com.dao.BookDao.(…)) -
对com.dao包里面所有类,所有方法进行增强 execution( com.dao . . *(…) )
5 AOP操作(AspectJ注解)
-
创建类,在类里面定义方法 public class User {
public void add(){
System.out.println("add......");
}
}
-
创建增强类(编写增强逻辑)
-
在增强类里面,创建方法,让不同方法代表不同的通知类型
public class UserProxy {
public void before(){
System.out.println("before....");
}
}
-
进行通知配置
-
在Spring配置文件中,开启注解扫描 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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
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="com.spring5.aopanno"></context:component-scan>
</beans>
-
使用注解创建User和UserProxy对象 @Component
public class User {
public void add(){
System.out.println("add......");
}
}
@Component
public class UserProxy {
public void before(){
System.out.println("before....");
}
}
-
在增强类上面添加注解@Aspect @Component
@Aspect
public class UserProxy {
public void before(){
System.out.println("before....");
}
}
4. 在Spring配置文件中开启生成代理对象
```xml
<!--开启Aspect生成代理对象-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
-
配置不同类型的通知
-
在增强类的里面,在作为通知方法上面,添加通知类型注解,使用切入点表达式配置 @Component
@Aspect
public class UserProxy {
@Before(value = "execution(* com.spring5.aopanno.User.add(..))")
public void before(){
System.out.println("before....");
}
}
```java
*///增强的类
@Component
@Aspect
//生成代理对象
public class UserProxy {
//前置通知
//@Before注解表示作为前置通知
@Before(value = "execution(* com.spring5.aopanno.User.add(..))")
public void before(){
System.out.println("before....");
}
//最终通知
@After(value = "execution(* com.spring5.aopanno.User.add(..))")
public void after(){
System.out.println("after.....");
}
//后置通知(返回通知)
@AfterReturning(value = "execution(* com.spring5.aopanno.User.add(..))")
public void afterReturning(){
System.out.println("afterReturning.....");
}
//异常通知
@AfterThrowing(value = "execution(* com.spring5.aopanno.User.add(..))")
public void afterThrowing(){
System.out.println("afterThrowing.....");
}
//环绕通知
@Around(value = "execution(* com.spring5.aopanno.User.add(..))")
public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
System.out.println("环绕之前.....");
//被增强方法执行
proceedingJoinPoint.proceed();
System.out.println("环绕之后.....");
}
}
-
相同切入点抽取
@Pointcut(value = "execution(* com.spring5.aopanno.User.add(..))")
public void pointdemo(){ }
@Before(value = "pointdemo()")
public void before(){
System.out.println("before....");
}
-
有多个增强类对同一个方法进行增强,设置增强类优先级
-
在增强类上面添加注解@Order(数字类型值),数字类型值越小优先级越高 @Component@Aspect@Order(1)public class PersonProxy @Component@Aspect
7.完全使用注解开发
? 创建配置类,不需要创建xml配置文件
@Configuration
@ComponentScan(basePackages = {"com"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop {}
6 AOP操作(AspectJ配置文件)
-
创建两个类,增强类和被增强类,创建方法 public class Book {
public void buy(){
System.out.println("buy.......");
}
}
public class BookProxy {
public void before(){
System.out.println("before.......");
}
}
-
在Spring配置文件中创建两个类对象
<bean id="book" class="com.spring5.aopxml.Book"></bean><bean id="bookProxy" class="com.spring5.aopxml.BookProxy"></bean>
-
在Spring配置文件中配置切入点
<aop:config>
<aop:pointcut id="p" expression="execution(* com.spring5.aopxml.Book.buy(..))"/>
<aop:aspect ref="bookProxy">
<aop:before method="before" pointcut-ref="p"/>
</aop:aspect>
</aop:config>
4 JdbcTemplate
1 JdbcTemplate(概念和准备工作)
-
什么是JdbcTemplate
- Spring框架对jdbc进行了封装,使用JdbcTemplate方便实现对数据库操作
-
准备工作
-
引入相关jar包 -
在spring配置文件配置数据库连接池
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="url" value="jdbc:mariadb://localhost:3306/user_db" />
<property name="username" value="root" />
<property name="password" value="Xy072548." />
<property name="driverClassName" value="org.mariadb.jdbc.Driver" />
</bean>
-
配置JdbcTemplate对象,注入DataSource
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
-
创建service类,创建dao类,在dao注入jdbcTemplate对象
-
配置文件中
<context:component-scan base-package="com"></context:component-scan>
-
service @Service
public class BookService {
@Autowired
private BookDao bookDao;
}
-
dao @Repository
public class BookDaoImpl implements BookDao{
@Autowired
private JdbcTemplate jdbcTemplate;
}
2 JdbcTemplate操作数据库
1 添加操作
-
对应数据库创建实体类 -
编写service和dao
-
在dao进行数据库添加操作 @Repository
public class BookDaoImpl implements BookDao{
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void add(Book book) {
String sql="insert into t_book values(?,?,?)";
Object[] args ={book.getUserId(), book.getUsername(), book.getUstatus()};
int update = jdbcTemplate.update(sql,args);
System.out.println(update);
}
}
?
2. 测试类
```java
@Test
public void testJdbcTemplate(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
BookService bookService = context.getBean("bookService", BookService.class);
Book book = new Book();
book.setUserId("1");
book.setUsername("zhangsan");
book.setUstatus("a");
bookService.addBook(book);
}
2 JdbcTemplate操作数据库(修改和操作)
@Override
public void updateBook(Book book) {
String sql="update t_book set username=?,ustatus=?, where user_id=?";
Object[] args ={ book.getUsername(), book.getUstatus(),book.getUserId()};
int update = jdbcTemplate.update(sql, args);
System.out.println(update);}
@Override
public void deleteBook(String id) {
String sql="delete from t_book where user_id=?";
int del = jdbcTemplate.update(sql, id);
System.out.println(del);
}
3 JdbcTemplate操作数据库(查询)
-
查询返回某个值
-
查询表里有多少条记录,返回值是某个值 @Override
public int selectCount() {
String sql="select count(*) from t_book";
Integer count = jdbcTemplate.queryForObject(sql,Integer.class);
return count;
}
-
查询返回对象
-
查询图书详情 -
JdbcTemplate实现查询返回对象 @Override
public Book findBookInfo(String id) {
String sql="select * from t_book where user_id=?";
Book book = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Book>(Book.class), id);
return book;
}
-
返回集合
-
查询图书列表分页 @Override
public List<Book> findAllBook() {
String sql = "select * from t_book";
List<Book> books = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Book>(Book.class));
return books;
}
4 JdbcTemplate操作数据库(批量操作)
-
批量操作:操作表里面多条记录 -
JdbcTemplate实现批量添加操作 batchUpdate(String sql,List<Object[]> batchArgs) 第一个参数:sql语句 第二个参数:list集合,添加多条记录数据 @Override
public void batchAddBook(List<Object[]> batchArgs) {
String sql = "insert into t_book values(?,?,?)";
int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
System.out.println(Arrays.toString((ints)));
}
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1 ={"3","java","q"};
Object[] o2 ={"4","c++","w"};
Object[] o3 ={"5","javascript","e"};
batchArgs.add(o1);
batchArgs.add(o2);
batchArgs.add(o3);
bookService.batchAdd(batchArgs);
-
JdbcTemplate实现批量修改操作 @Override
public void batchUpdateBook(List<Object[]> batchArgs) {
String sql = "update t_book set username=?,ustatus=? where user_id=?";
int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
System.out.println(ints);
}
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1 ={"java","s","3"};
Object[] o2 ={"c#","z","4"};
Object[] o3 ={"javascript","v","5"};
batchArgs.add(o1);
batchArgs.add(o2);
batchArgs.add(o3);
bookService.batchUpdate(batchArgs);
4.JdbcTemplate实现批量删除操作
@Override
public void batchDeleteBook(List<Object[]> batchArgs) {
String sql = "delete from t_book where user_id=?";
int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
System.out.println(ints);
}
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1 ={"3"};
Object[] o2 ={"5"};
batchArgs.add(o1);
batchArgs.add(o2);
bookService.batchDelete(batchArgs);
5 事务操作
1 场景引入
-
创建数据库表添加记录 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YzlKxH2g-1637331724199)(C:\Users\asus\AppData\Roaming\Typora\typora-user-images\image-20211116192512569.png)] -
创建service,搭建dao,完成对象创建和注入
-
在service注入dao,在dao注入JdbcTemplate,在JdbcTemplate注入DataSource @Service
public class UserService {
@Autowired
private UserDao userDao;
}
@Repository
public class UserDaoImpl implements UserDao{
@Autowired
private JdbcTemplate jdbcTemplate;
}
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="url" value="jdbc:mariadb://localhost:3306/user_db" />
<property name="username" value="root" />
<property name="password" value="Xy072548." />
<property name="driverClassName" value="org.mariadb.jdbc.Driver" /></bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
-
在dao创建两个方法:多钱和少钱的方法,在service创建方法(转账的方法) @Override
public void addMoney() {
String sql="update t_account set money=money+? where username=?";
jdbcTemplate.update(sql,100,"marry");
}
@Override
public void reduceMoney() {
String sql="update t_account set money=money-? where username=?";
jdbcTemplate.update(sql,100,"lucy");
}
@Service
public class UserService {
@Autowired
private UserDao userDao;
public void accountMoney(){
userDao.reduceMoney();
userDao.addMoney();
}
}
-
上述代码正常执行,不会产生问题,出现异常就会有问题
public void accountMoney(){
userDao.reduceMoney();
int i =10/0;
userDao.addMoney();
}
2 Spring事务管理介绍
-
事务添加到JavaEE service层 -
在Spring进行事务操作
- 有两种方式:编程式事务管理和声明式事务管理(使用)
-
声明式事务管理
- 基于注解方式(使用)
- 基于xml配置文件方式
-
在Spring进行声明式事务管理,底层使用AOP原理 -
Spring事务管理API
- 提供了接口,代表事务管理器
3 注解声明式事务管理
-
在Spring:配置事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource">
</property>
</bean>
-
在Spring配置文件,开启事务注解
-
在Spring配置文件引入名称空间 -
开启事务注解
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
-
在service类上面(或者service类里面方法上面)添加事务注解
-
@Transactional,可以添加到类上面,也可以添加到方法上面 -
添加到类上面,表示类里面所有方法都添加了事务 -
添加到方法上面,只有此方法添加了事务 @Service
@Transactional
public class UserService
4 注解声明式事务管理参数配置
- 在service类上面添加注解@Transactional,在这个注解里面可以配置事务相关参数
-
名称 | 解释 |
---|
isolation:事务隔离级别 | 多事务操作之间不会产生影响 | timeout:超时时间 | 事务在一定时间内进行提交,如果不提交就回滚,默认值是-1,设置时间以秒为单位 | readOnly:是否只读 | 默认值false,可以查询,可以添加修改删除操作设置为:true后,只能查询 | rollbackFor:回滚 | 设置出现哪些异常进行回滚 | noRollbackFor:不回滚 | 设置出现哪些异常不进行回滚 | 更多操作propagation:事务传播行为 | 多事务方法之间进行调用,事务如何进行管理@Transactional(propagation = Propagation.REQUIRED) |
5 XML声明式事务管理
-
在Spring配置文件中进行配置
-
配置事务 -
配置通知(增强的地方叫通知) -
配置切入点和切面
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</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(* com.spring5.service.UserService.*(..))"/>
<aop:advisor advice-ref="txadvice" pointcut-ref="pt"/>
</aop:config>
6 完全注解声明事务管理
-
创建配置类,使用配置类代替xml配置文件 @Configuration
@ComponentScan(basePackages = "com.spring5")
@EnableTransactionManagement
public class TxConfig {
@Bean
public DruidDataSource getDDruidDataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("org.mariadb.jdbc.Driver");
dataSource.setUrl("jdbc:mariadb://localhost:3306/user_db");
dataSource.setUsername("root");
dataSource.setPassword("Xy072548.");
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;
}
}
5 Spring框架新功能
- 整个Spring5框架的代码基于java8,运行时兼容JDK9,许多不建议使用的类和方法在整个代码库中删除
Spring5 框架自带了通用的日志封装
- Spring5已经移除了Log4jConfigListener,官方建议使用Log4j2
- Spring框架整合Log4j2
引入jar包
创建Log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="INFO">
<appenders>
<console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</console>
</appenders>
<loggers>
<root level="info">
<appender-ref ref="Console"/>
</root>
</loggers>
</configuration>
Spring框架核心容器支持@Nullable注解
-
@Nullable注解可以使用在方法上面,属性上面,参数上面,表示方法返回,属性值,参数值可以为空 -
注解用在方法上面,返回值可以为空 @Nullable
String getId();
-
注解使用在方法参数里面,方法参数可以为空 -
注解使用在属性值上面,属性值可以为空 @Nullable
private String name;
Spring5 核心容器支持函数式风格GenericApplicationContext
@Test
public void testGenericApplicationContext(){
GenericApplicationContext context = new GenericApplicationContext();
context.refresh();
context.registerBean("user1",User.class,() -> new User());
User user = (User) context.getBean("user1");
System.out.println(user);
}
Spring5支持整合Junit5
-
整合Junit4 @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:bean1.xml")
public class JTest4 {
@Autowired
private UserService userService;
@Test
public void test1(){
userService.accountMoney();
}
}
-
整合Junit5 引入jar包 @ExtendWith(SpringExtension.class)
@ContextConfiguration("classpath:bean1.xml")
class JTest5 {
@Autowired
private UserService userService;
@Test
public void test1(){
userService.accountMoney();
}
}
|