1.创建maven项目
2.添加依赖
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-contextartifactId>
<version>5.2.5.RELEASEversion>
dependency>
dependencies>
3.创建对象
package com.xjggb.demo;
public class HelloSpring {
public void show(){
System.out.println("来了老弟");
}
}
4.编写配置文件
<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="helloSpring" class="com.xjggb.demo.HelloSpring">bean>
beans>
5.编写测试类
package com.xjggb;
import com.xjggb.demo.HelloSpring;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class HelloTest {
public static void main(String[] args) {
//加载配置文件
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
//获取配置文件对象
HelloSpring helloSpring = context.getBean("helloSpring", HelloSpring.class);
//调用对象方法
helloSpring.show();
}
}
1.IOC容器(IOC:实体类确定好类间的关系, 使用xml文件按照实体类配置对象的各种属性,工厂根据XML文件创建对象。 )
2.什么是ioc ?
1.ioc注入两种方式
1.创建类,定义属性,创建属性的有参构造
package com.xjggb.entity;
public class Student {
private int num;
private String name;
//无参构造
public Student(){
}
//有参构造
public Student(int num ,String name){
this.num=num;
this.name=name;
}
@Override
public String toString() {
return "Student{" +
"num=" + num +
", name='" + name + '\'' +
'}';
}
}
2.Spring配置文件配置
<bean id="student" class="com.xjggb.entity.Student">
<constructor-arg name="name" value="行健乖乖霸">constructor-arg>
<constructor-arg name="num" value="1">constructor-arg>
bean>
小结:
有参构造注入:一定要记得写无参构造
1.在配置文件钟添加p命名空间
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
beans>
2.进行属性的注入
<bean id="student" class="com.xjggb.entity.Student" p:num="1" p:name="来了老弟">bean>
3.测试
public static void show(){
//加载配置文件
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("demo01.xml");
Student student = context.getBean("student", Student.class);
System.out.println("student = " + student);
}
1.编写类
package com.xjggb.entity;
public class Book {
private String name;
private String author;
private String address;
public void setName(String name) {
this.name = name;
}
public void setAuthor(String author) {
this.author = author;
}
public void setAddress(String address) {
this.address = address;
}
public void show(){
System.out.println(name+":"+author+":"+address);
}
}
2.编写配置文件(默认也是null)
<bean id="book" class="com.xjggb.entity.Book">
<property name="name">
<null/>
property>
bean>
3.属性包含特殊字符( <北京> )
<bean id="book" class="com.xjggb.entity.Book">
<property name="name" value="<北京 <">property>
<property name="address">
<value>]]]>value>
property>
bean>
4.测试
public static void show1(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("demo02.xml");
Book book = context.getBean("book", Book.class);
book.show();
}
1.创建两个类service类和dao类
创建接口
public interface Dao {
void add();
}
实现接口
package com.xjggb.dao.impl;
import com.xjggb.dao.Dao;
public class DaoImpl implements Dao {
@Override
public void add() {
System.out.println("\"来了老弟\" = " + "来了老弟");
}
}
编写Userservice
package com.xjggb.service;
import com.xjggb.dao.impl.DaoImpl;
public class UserService {
private DaoImpl dao;
public void setDao(DaoImpl dao) {
this.dao = dao;
}
public void show(){
dao.add();
}
}
2.spring配置文件钟进行配置
<!--创建service-->
<bean id="userService" class="com.xjggb.service.UserService">
<!--注入dao对象-->
<property name="dao" ref="dao"/>
</bean>
<!--创建dao实现类-->
<bean id="dao" class="com.xjggb.dao.impl.DaoImpl"></bean>
3.测试
//注入对象
public static void show3(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("demo03.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.show();
}
1.创建类
package com.xjggb.entity;
import org.springframework.scheduling.concurrent.ScheduledExecutorTask;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Student {
//数组类型
private String[] course;
//注入List类型
private List list;
//map类型
private Map map;
//set类型
private Set sets;
public void setSets(Set sets) {
this.sets = sets;
}
public void setCourse(String[] course) {
this.course = course;
}
public void setList(List list) {
this.list = list;
}
public void setMap(Map map) {
this.map = map;
}
@Override
public String toString() {
return "Student{" +
"course=" + Arrays.toString(course) +
", list=" + list +
", map=" + map +
", sets=" + sets +
'}';
}
}
2.编写配置文件
<bean id="student" class="com.xjggb.entity.Student">
<!--注入数组-->
<property name="course" >
<array>
<value>c</value>
<value>c++</value>
<value>java</value>
<value>python</value>
</array>
</property>
<!--注入map-->
<property name="map">
<map>
<entry key="JAVA" value="java"></entry>
<entry key="PHP" value="php"></entry>
</map>
</property>
<!--注入list-->
<property name="list">
<list>
<value>中山路美食街</value>
<value>建政路小吃街</value>
<value>农院路美食街</value>
<value>南铁美食街</value>
</list>
</property>
<!--注入set-->
<property name="sets">
<set>
<value>张三</value>
<value>李四</value>
<value>王五</value>
<value>马六</value>
</set>
</property>
</bean>
3.测试
//注入集合
public static void show5(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("demo05.xml");
Student student = context.getBean("student", Student.class);
System.out.println("student = " + student);
}
1.创建类
package com.xjggb.entity;
public class Course {
private String CourseName;
public void setCourseName(String courseName) {
CourseName = courseName;
}
public String getCourseName() {
return CourseName;
}
}
package com.xjggb.entity;
import org.springframework.scheduling.concurrent.ScheduledExecutorTask;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class Student {
private List<Course> courses;
public void setCourses(List<Course> courses) {
this.courses = courses;
}
public List<Course> getCourses() {
return courses;
}
@Override
public String toString() {
return "Student{" +
"courses=" + courses +
'}';
}
}
2.配置文件
<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="student" class="com.xjggb.entity.Student">
<property name="courses">
<list>
<ref bean="course1">ref>
<ref bean="course2">ref>
list>
property>
bean>
<bean id="course1" class="com.xjggb.entity.Course">
<property name="courseName" value="来了老弟">property>
bean>
<bean id="course2" class="com.xjggb.entity.Course">
<property name="courseName" value="我是行健乖乖霸">property>
bean>
beans>
1.编写配置文件
<util:list id="bookList">
<value>三国演value>
<value>水浒传value>
<value>西游记value>
<value>红楼梦value>
util:list>
<bean id="book" class="com.xjggb.entity.Book">
<property name="list" ref="bookList">property>
bean>
2.编写类
public class Book {
private List<String> list;
public void setList(List<String> list) {
this.list = list;
}
public List<String> getList() {
return list;
}
}
1.Spring有两种Bean,一种普通Bean,另一种是 工厂Bean
普通bean,在配置文件中,定义bean类型就是返回类型
工厂bean,在配置文件中定义bean类型可以和返回类型不一样
第一步创建类,让这个类作为工厂Bean,实现接口FactoryBean
第二步实现接口里的方法,在实现方法中定义返回的bean类型。
实现接口类
public class MyBean implements FactoryBean<Course>{
@override
public Course getObject() throws Exceptions{
Course course = new Course();
course.setCourse("java");
return course;
}
@override
public Class<?> getObjectType(){
return NULL;
}
@override
public Boolean isSingleton(){
return false;
}
}
配置文件
//配置类
<bean id = "mybean" class="com.zhh.entity.MyBean">bean>
测试
//测试类
@test
public void test2(){
ApplicationContext application = new classPathXpthXmlApplicationContext("bean4.xml");
Course course = context.getBean("MyBean",Course.class);
}
在spring里,设置创建Bean实例是单实例还是多实例。
在spring里,默认设置创建Bean实例是单实例。
如何设置单实例还是多实例。
spring配置文件bean标签里scope属性用于设置单实例还是多实例。
scope属性值:第一个,默认值,singleton,表示单实例对象;第二个值:prototype,表示多实例对象。
//配置
<bean id="book" class="com.zhh.entity.Book" scope="prototype">
<property name="list" ref = "booklist"></property>
</bean>
第一: singleton表示单实例,prototype表示多实例。
第二: 设置Scope是singleton时,加载spring配置文件时侯就会创建单实例对象; 设置Scope是prototype时,不是加载spring配置文件时侯创建对象,而是在调用getBean方法时创建多实例对象。 request,表示一次请求,每次创建对象放到request域对象中。 session,表示一次会话,每次创建对象放到session域对象中。
1.从对象创建到对象销毁的过程
2.Bean的生命周期
1.编写实体类
package com.xjggb.demo;
public class Orders {
public Orders(){
System.out.println("第一步,调用无参构造方法");
}
private String order_name;
public void setOrder_name(String order_name) {
this.order_name = order_name;
System.out.println("第二步,调用see方法,设置属性值");
}
//创建初始化方法
public void initMethod(){
System.out.println("第三步执行初始化方法");
}
//创建执行初始化方法
public void destoryMethod(){
System.out.println("第五步:执行销毁方法");
}
}
2.编写配置
<bean id="orders" class="com.xjggb.demo.Orders" init-method="initMethod" destroy-method="destoryMethod">
<property name="order_name" value="来了老弟">property>
bean>
3.测试
//生命周期
public static void show9(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("demo09.xml");
Orders orders = context.getBean("orders", Orders.class);
System.out.println("第四步:获取创建Bean实例"+ orders);
//手动销毁
context.close();
}
编写实现类
package com.xjggb.demo;
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;
}
}
添加配置
<bean id="myBeanPost" class="com.xjggb.demo.MyBeanPost">bean>
1.什么是自动装配
2.实体类
package com.xjggb.autowie;
public class Emp {
private Dep dep;
public void setDep(Dep dep) {
this.dep = dep;
}
@Override
public String toString() {
return "Emp{" +
"dep=" + dep +
'}';
}
}
package com.xjggb.autowie;
import javafx.scene.DepthTest;
public class Dep {
private String Dept;
public void setDept(String dept) {
Dept = dept;
}
@Override
public String toString() {
return "Dep{" +
"Dept='" + Dept + '\'' +
'}';
}
}
配置文件
<bean id="dep" class="com.xjggb.autowie.Dep">
<property name="dept" value="来了老弟">property>
bean>
<bean id="emp" class="com.xjggb.autowie.Emp" autowire="byName">
bean>
<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/day10">property>
<property name="username" value="root">property>
<property name="password" value="root">property>
bean>
编写jdbc.properties文件引入到spring配置文件中
prop.driverClass = com.mysql.jdbc.Driver
prop.url = jdbc:mysql://localhost:3306/userDataBase
prop.user = root
prop.password = root
引入配置文件
<context:property-placeholder location="classpath:jdbc.properties">context:property-placeholder>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${prop.driverClass}"/>
<property name="url" value="${prop.url}"/>
<property name="username" value="${prop.user}"/>
<property name="password" value="${prop.password}"/>
bean>
格式: @注解名称(属性名=属性值,属性名=属性值)
使用注解:注解作用在类(方法,属性)上
使用目的:简化xml配置
1.创建对象注解(4个)
上面四个注解功能一样,都可以用来创建bean对象
基于对象注解方式实现对象创建例子
1.编写类
@Controller
public class HelloController {
public void show(){
System.out.println("来了老弟");
}
}
2.编写配置
<context:component-scan base-package="com.xjggb.controller">context:component-scan>
3.编写测试
//基于注解实现对象创建
public static void show11(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("demo12.xml");
HelloController helloController = context.getBean("helloController", HelloController.class);
helloController.show();
}
编写类
package com.xjggb.autowie.controller;
import com.xjggb.autowie.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class Hello {
@Autowired
private UserDao userDao;
public void show(){
userDao.add();
}
}
编写接口
package com.xjggb.autowie.dao;
public interface UserDao {
void add();
}
编写实现类
package com.xjggb.autowie.dao.impl;
import com.xjggb.autowie.dao.UserDao;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;
@Component
public class UserDaoImpl implements UserDao {
@Override
public void add() {
System.out.println("来了老弟");
}
}
配置文件
<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 https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.xjggb.autowie">context:component-scan>
beans>
1.编写配置类
//完全注解开发
@Configuration
//配置类,代替配置文件
@ComponentScan(basePackages = {
"com.xjggb.completely"})
public class SpringCongif {
}
2.编写业务类
@Component(value = "user")
public class UseService {
public void show(){
System.out.println("来了老弟");
}
}
3.编写测试
//完全注解配置
public static void show13(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringCongif.class);
UseService useService = context.getBean("user", UseService.class);
useService.show();
}
无接口,使用CGLIB动态代理,创建子类的代理对象,增强类的方法
1.AOP:面向切面编程,对业务逻辑的各个部分进行隔离,从而降低耦合,提高代码可用性和开发效率,将日志记录,事务处理,异常处理,性能统计,安全控制等代码从业务逻辑代码中划分出来,改变这些行为的时候不影响业务逻辑代码
也就是说,:在不修改源代码的情况下,在主干功能里面添加新的功能
2.AOP原理
有接口,使用JDK动态代理,创建接口实现类的代理对象,增强类的方法
JDK动态代理 ,使用Proxy类 java.lang.reflect.Proxy代理类。
newProxyInstance(Classloader loader, 类>[ ]… interfaaces,InvocationHandler h)
1.编写接口
public interface UserDao {
void add();
}
2.实现类
package com.xjggb.proxy;
public class UserDaoImpl implements UserDao {
@Override
public void add() {
System.out.println(" 我是Add方法");
}
}
3.代理方法
package com.xjggb.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Arrays;
public class UserDaoProxy implements InvocationHandler {
private Object object;
public UserDaoProxy(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//方法执行前
System.out.println("方法执行前"+method.getName()+"传递参数"+ Arrays.toString(args));
//被增强的方法执行
Object invoke = method.invoke(object, args);
//方法执行后
System.out.println("方法执行后"+invoke);
return invoke;
}
}
4.测试
package com.xjggb.proxy;
import java.lang.reflect.Proxy;
public class Demo {
public static void main(String[] args) {
UserDaoImpl userDao = new UserDaoImpl();
Object o = Proxy.newProxyInstance(
Demo.class.getClassLoader(),
new Class[]{
UserDao.class},
new UserDaoProxy(userDao));
//真实对象调用方法
userDao.add();
System.out.println("o = " + o);
}
}
无接口,使用CGLIB动态代理,创建子类的代理对象,增强类的方法
1.spring框架中一般都是基于AspectJ实现AOP操作 AspectJ,本身是单独的框架,不属于Spring组成部分,独立于AOP框架,一般把AspectJ和Spring框架一起使用,进行AOP操作
2.基于AspectJ实现AOP操作
1.创建类,类里面定义方法
package com.xjggb.aop;
import org.springframework.stereotype.Component;
@Component
public class User {
public void show(){
System.out.println("add");
}
}
2.增强类
package com.xjggb.aop;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class UserProxy {
//前置通知
@Before("execution(* com.xjggb.aop.User.show(..))")
public void before(){
System.out.println("Before 我是前置通知");
}
//返回通知,有异常不执行
@AfterReturning(value = "execution(* com.xjggb.aop.User.show(..))")
public void afterReturning(){
System.out.println("返回通知");
}
//后置通知,有没有异常都会执行
@After(value = "execution(* com.xjggb.aop.User.show(..))")
public void after(){
System.out.println("我是后置通知");
}
//异常通知
@AfterThrowing(value = "execution(* com.xjggb.aop.User.show(..))")
public void afterThrowing(){
System.out.println("我是异常通知");
}
//环绕通知
// @Around(value = "execution(* com.xjggb.aop.User.show(..))")
public void around(){
System.out.println("我是环绕通知");
}
}
3.测试
@Test
public void show(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("aop.xml");
User user = context.getBean("user", User.class);
user.show();
}
相同接入点抽取
//相同的接入点抽取
@Pointcut(value = "execution(* com.xjggb.aop.User.show(..))")
public void pointcut(){
System.out.println();
}
//前置通知
//使用公共方法
@Before("pointcut()")
public void before(){
System.out.println("Before 我是前置通知");
}
有多个增强类对同一个方法进行增强,设置增强类的优先级,在增强类上面添加@Order(数字类型),数字类型值越小优先级越高,
@Component
@Aspect
@Order(1)
public class UserProxy {
}
1.编写配置类
//完全注解开发
@Configuration
//配置类,代替配置文件
@ComponentScan(basePackages = {
"com.xjggb.aop"})
@EnableAspectJAutoProxy(proxyTargetClass = true) //开启代理自动创建代理类
public class SpringCongif {
}
2.测试
@Test
public void show(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("aop.xml");
User user = context.getBean("user", User.class);
user.show();
}
1.编写类
package com.xjggb.bookaop;
public class UserBook {
public void show(){
System.out.println("来了老弟");
}
}
2.增强类
package com.xjggb.bookaop;
public class BookProxy {
public void before(){
System.out.println("你好呀");
}
}
3.xml配置
<bean id="userBook" class="com.xjggb.bookaop.UserBook">bean>
<bean id="bookProxy" class="com.xjggb.bookaop.BookProxy">bean>
<aop:config>
<aop:pointcut id="p" expression="execution(* com.xjggb.bookaop.UserBook.show(..))"/>
<aop:aspect ref="bookProxy" >
<aop:before method="before" pointcut-ref="p" >aop:before>
aop:aspect>
aop:config>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>5.0.2.RELEASEversion>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.47version>
dependency>
CREATE TABLE `payment` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`serial` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
-- 添加数据
insert into payment values(1,"来了老弟")
package com.xjggb.jdbc.dao;
import com.xjggb.jdbc.entity.Payment;
public interface PaymentDao {
//添加方法
void add(Payment payment);
//删除方法
void delete(int id);
//修改方法
void update(Payment payment);
}
实现类
package com.xjggb.jdbc.dao.impl;
import com.xjggb.jdbc.dao.PaymentDao;
import com.xjggb.jdbc.entity.Payment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
@Repository
public class PaymentDaoImpl implements PaymentDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void add(Payment payment) {
String sql="insert into payment values(?,?)";
Object[] args={
payment.getId(),payment.getSerial()};
int update = jdbcTemplate.update(sql, args);
System.out.println("update = " + update);
}
@Override
public void delete(int id) {
//编写sql
String sql="DELETE FROM payment WHERE id=?";
jdbcTemplate.update(sql,id);
}
@Override
public void update(Payment payment) {
String sql="update payment set serial =? where id=?";
Object [] args={
payment.getSerial(),payment.getId()};
int update = jdbcTemplate.update(sql, args);
System.out.println("update = " + update);
}
}
package com.xjggb.jdbc.service;
import com.xjggb.jdbc.dao.PaymentDao;
import com.xjggb.jdbc.entity.Payment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class PaymentService {
@Autowired
private PaymentDao paymentDao;
//删除数据
public void delete(int id){
paymentDao.delete(id);
}
//添加数据
public void add(Payment payment){
paymentDao.add(payment);
}
//根据id修改数据
public void update(Payment payment){
paymentDao.update(payment);
}
}
//jdbc
@Test
public void show4(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("jdbc.xml");
PaymentService paymentService = context.getBean("paymentService", PaymentService.class);
//paymentService.delete(1); 删除
Payment payment = new Payment();
payment.setId(20);
payment.setSerial("你好啊小老弟");
//paymentService.add(payment); 添加元素
// paymentService.update(payment); //修改元素
}
两个参数一个是sql语句另一个是返回类型的Class
//接口
//返回某个值
Integer selectCount();
//实现类
//查询某个返回值
public Integer selectCount(){
String sql="select count(*) from payment";
Integer integer = jdbcTemplate.queryForObject(sql, Integer.class);
return integer;
}
1.使用jdbc查询返回对象
queryForObject(String sql, RowMapper rowMapper, Object… args)
三个参数
//接口
//返回查询对象
Payment findPayment(int id);
//实现类
@Override
public Payment findPayment(int id) {
String sql="select * from payment where id=?";
Payment payment = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(Payment.class), id);
return payment;
}
1.使用jdbc Template实现查询饭返回集合
query(String sql, RowMapper rowMapper, Object… args )
三个参数
//接口
//返回集合
List<Payment> findAllBook();
//实现类
//返回全部数据
@Override
public List<Payment> findAllBook() {
String sql="select * from payment";
List<Payment> query = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Payment.class));
return query;
}
业务类
//返回一个集合
public List<Payment> findAllBook(){
List<Payment> allBook = paymentDao.findAllBook();
return allBook;
}
事务时数据库操作的最近本单元,逻辑上一组操作,要么都成功,如果有一个失败所有的操作都失败
典型场景:银行转账
1.创建数据库,添加记录
2.创建service 搭建dao 完成对象创建和注入关系
1.接口
package com.xjggb.jdbc.dao;
public interface UserDao {
void addMoney();
void reduceMoney();
}
2.实现类
package com.xjggb.jdbc.dao.impl;
import com.xjggb.jdbc.dao.UserDao;
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 addMoney() {
String sql="update user set mary=mary+ ? where name=?";
jdbcTemplate.update(sql, 100, "小明");
}
@Override
public void reduceMoney() {
String sql="update user set mary=mary- ? where name=?";
jdbcTemplate.update(sql, 100, "小红");
}
}
3.测试
//jdbc
@Test
public void show4(){
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("jdbc.xml");
//PaymentService paymentService = context.getBean("paymentService", PaymentService.class);
UserService userService = context.getBean("userService", UserService.class);
userService.show();
4.上面代码,如果正常秩序没有问题,但是代码执行过程中出现异常,就会有问题
模拟异常
@Service
public class UserService {
@Autowired
private UserDao userDao;
public void show(){
userDao.addMoney();
//模拟异常
int i=10/0;
userDao.reduceMoney();
}
}
5.代码出现异常 问题就是小明加了,小红却没有减
6.解决
提供一个接口,代表事务管理器,这个接口针对不同的框架提供不同的实现类
编写配置
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
bean>
<tx:annotation-driven transaction-manager="transactionManager">tx:annotation-driven>
业务类添加注解
@Transactional
public void show(){
userDao.addMoney();
//模拟异常
int i=10/0;
userDao.reduceMoney();
}
事务的传播行为可以由传播属性指定,Spring定义了7种类传播行为
事务有特性称为隔离级别,多事务操作之间不会产生影响,不考虑隔离性产生很多问题
有三个读问题:脏读,不可重复读,幻读
脏读指事务A读取到了事务B更新了但是未提交的数据,然后事务B由于某种错误发生回滚,那么事务A读取到的就是脏数据。
一个未提交事务读取到另一提交事务修改数据
不可重复读指在数据库访问时,一个事务在前后两次相同的访问中却读到了不同的数据内容。
幻读指的是事务A在查询完记录总数后,事务B执行了新增数据的操作,事务A再次查询记录总数,发现两次查询的结果不一致,平白无故的多了几条记录,这种现象称为幻读。
// 添加事务注解
@Transactional(propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ)
timeout:超时时间
事务需要在一定时间内进行提交,如果不提交就进行回滚
默认值为-1设置时间以秒为单位计算
@Transactional(timeout = -1,propagation = Propagation.REQUIRED,isolation = Isolation.REPEATABLE_READ)
readOnly:是否只读
@Transactional(readOnly = true,timeout = -1,propagation = Propagation.REQUIRED,isolation =Isolation.REPEATABLE_READ)
第一步配置事务管理器
<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.xjggb.jdbc.service.*(..)))"/>
<aop:advisor advice-ref="txadvice" pointcut-ref="pt">aop:advisor>
aop:config>
package com.xjggb.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 = "com.xjggb.jdbc")
@EnableTransactionManagement //开启事务
public class TxConfig {
// 创建数据库连接池
@Bean
public DruidDataSource getDruidDataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/cloud");
dataSource.setUsername("root");
dataSource.setPassword("root");
return dataSource;
}
//创建JdbcTemplate对象
@Bean
public JdbcTemplate getJdbcTemplate(DataSource dataSource){
JdbcTemplate jdbcTemplate = new JdbcTemplate();
// 注入DataSource
jdbcTemplate.setDataSource(dataSource);
return jdbcTemplate;
}
// 创建事务管理器
@Bean
public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource){
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
}
测试
//测试全注解
@Test
public void show6(){
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TxConfig.class);
UserService userService = context.getBean("userService", UserService.class);
userService.show();
}
添加依赖
<dependency>
<groupId>org.slf4jgroupId>
<artifactId>slf4j-apiartifactId>
<version>1.7.21version>
dependency>
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-apiartifactId>
<version>2.6.2version>
dependency>
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-coreartifactId>
<version>2.6.2version>
dependency>
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-slf4j-implartifactId>
<version>2.6.2version>
dependency>
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-jclartifactId>
<version>2.6.2version>
dependency>
<dependency>
<groupId>com.lmaxgroupId>
<artifactId>disruptorartifactId>
<version>3.3.5version>
dependency>
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-webartifactId>
<version>2.6.2version>
dependency>
<dependency>
<groupId>org.apache.logging.log4jgroupId>
<artifactId>log4j-1.2-apiartifactId>
<version>2.6.2version>
dependency>
编写xml文件
<configuration status="DEBUG">
<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>
是Spring5添加的新的模块,用于web开发的,功能和SpringMVC类似的,Webflux使用当前一种比较流行程响应式编程出现的框架
使用传统web框架,比如SpringMVC,这些机遇Servlet容器,Webflux是一种异步非阻塞的框架,异步非阻塞的框架在Servlet3.1以后才支持,核心是基于Reactor的相关API实现的
什么是异步非阻塞模
Webflux特点
比较SpringMVC
响应式编程
响应式编程式一种面向数据流和变化传播的编程范式。这意味着可以在编程语言中很方便地表达静态或动态的数据流二相关的计算模型会自动将变化的值通过数据流进行传播
提供的观察这模式两个类Observer和Observable
public class ObserverDemo extends Observable {
public static void main(String[] args) {
ObserverDemo observerDemo = new ObserverDemo();
// 添加观察者
observerDemo.addObserver((o,arg)->{
System.out.println("发生变化"+arg);
});
observerDemo.addObserver((o,arg)->{
System.out.println("收到被观察者通知,准备改变"+arg);
});
observerDemo.setChanged();// 数据变化
observerDemo.notifyObservers();//通知
}
}
响应式编程(Reactor实现)
代码演示Flux和Mono
// 第一步 引入依赖
<dependencies>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
<version>3.1.5.RELEASE</version>
</dependency>
</dependencies>
12345678
public static void main(String[] args) {
// just方法直接声明
Flux.just(1,2,3,4);
Mono.just(1);
// 其他方法
Integer[] array = {
1,2,3,4};
Flux.fromArray(array);
List<Integer> list = Arrays.asList(array);
Flux.fromIterable(list);
Stream<Integer> stream = list.stream();
Flux.fromStream(stream);
}
三中信号特点
错误信号和完成信号都是终止信号,不能共存的
如果没有发送任何信号元素值,而是直接发送错误或者完成信号,表示是空数据流
如果没有错误信号,没有完成信号,表示是无限数据流
调用just或者其他方法只是声明数据流,数据流并没有发出,只有进行订阅之后才会触发数据流,不订阅声明都不会发生的
public static void main(String[] args) {
// just方法直接声明
Flux.just(1,2,3,4).subscribe(System.out::print);
Mono.just(1).subscribe(System.out::println);
}
SpringWebflux就Reactor,默认使用容器Netty,Netty是高性能的NIO框架,异步非阻塞的框架
SpringWebflux 里面 DispatcherHandler,负责请求的处理
1.创建SpringBoot项目
2.引入依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webfluxartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
dependency>
3.实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private String name;
private String gender;
private Integer age;
}
4.编写业务类
接口
package com.xjggb.service;
import com.xjggb.entuty.User;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
public interface UserService {
/*根据id查询用户*/
Mono<User> findById(int id);
/*查询所有用户*/
Flux<User> getAllUser();
/*添加用户*/
Mono<Void> saveUserInfo(Mono<User> user);
}
实现类
@Service
public class UserServiceImpl implements UserService {
/*创建map集合存储数据*/
private final HashMap<Integer, User> userMap = new HashMap<>();
public UserServiceImpl(){
this.userMap.put(1, new User("lucy","nan",20));
this.userMap.put(2, new User("mary","nv",30));
this.userMap.put(3, new User("jack","nan",40));
this.userMap.put(4, new User("WeiSanJin","nan",50));
}
@Override
public Mono<User> findById(int id) {
//根据id查询
return Mono.justOrEmpty(this.userMap.get(id));
}
/*返回多个用户*/
@Override
public Flux<User> getAllUser() {
//查询多个
return Flux.fromIterable(this.userMap.values());
}
/** 添加用户*/
@Override
public Mono<Void> saveUserInfo(Mono<User> user) {
return user.doOnNext(p->{
int id=userMap.size()+1;
userMap.put(id,p);
}).thenEmpty(Mono.empty());
}
5.编写控制器
@RestController
public class UserController {
@Autowired
private UserService userService;
/** id查询*/
@GetMapping("/user/{id}")
public Mono<User> getUserId(@PathVariable int id){
return userService.findById(id);
}
/** 查询所有*/
@GetMapping("/user")
public Flux<User> getUser(){
return userService.getAllUser();
}
/** 添加*/
@PostMapping("/saveUser")
public Mono<Void> saveUser(@RequestBody User user){
Mono<User> userMono = Mono.just(user);
return userService.saveUserInfo(userMono);
}
6.访问
1)在使用函数式编程模型操作时候,需要自己初始化服务器
(2)基于函数式编程模型时候,有两个核心接口:RouterFunction(实现路由功能,请求转发给对应的 handler)和 HandlerFunction(处理请求生成响应的函数)。核心任务定义两个函数式接口的实现并且启动需要的服务器。
( 3 ) SpringWebflux 请 求 和 响 应 不 再 是 ServletRequest 和 ServletResponse , 而 是ServerRequest 和 ServerResponse
创建 Handler(具体实现方法)
public class UserHandler {
private final UserService userService;
public UserHandler(UserService userService){
this.userService = userService;
}
/** 根据id查询*/
public Mono<ServerResponse> getUserById(ServerRequest request){
/* 获取id*/
int userId = Integer.valueOf(request.pathVariable("id"));
/* 空值处理*/
Mono<ServerResponse> notFound = ServerResponse.notFound().build();
/* 调用service方法得到数据*/
Mono<User> userMono = this.userService.getUserById(userId);
/* userMono进行转换返回*/
/* 使用Reactor操作符fluxMap*/
return userMono
.flatMap(person -> ServerResponse.ok().contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromObject(person)))
.switchIfEmpty(notFound);
}
/** 查询所有*/
public Mono<ServerResponse> getAllUser(){
/* 调用service得到结果*/
Flux<User> userFlux = this.userService.getAllUser();
return ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).body(userFlux,User.class);
}
/** 添加*/
public Mono<ServerResponse> saveUser(ServerRequest request){
/* 得到user对象*/
Mono<User> userMono = request.bodyToMono(User.class);
return ServerResponse.ok().build(this.userService.saveUserInfo(userMono));
}
初始化服务器,编写 Router
创建路由的方法
public class Server {
/** 创建Router路由*/
public RouterFunction<ServerResponse> routerFunction(){
/* 创建hanler对象*/
UserService userService = new UserServiceImpl();
UserHandler handler = new UserHandler(userService);
/* 设置路由*/
return RouterFunctions.route(
GET("/user/{id}").and(accept(APPLICATION_JSON)),handler::getUserById)
.andRoute(GET("/user").and(accept(APPLICATION_JSON)),handler::getAllUser);
}
}
创建服务器完成适配
public class Server {
/** 创建服务器完成配置*/
public void createReactorServer(){
/*路由和handler适配*/
RouterFunction<ServerResponse> route = routerFunction();
HttpHandler httpHandler = RouterFunctions.toHttpHandler(route);
ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(httpHandler);
/* 创建服务器*/
HttpServer httpServer = HttpServer.create();
httpServer.handle(adapter).bindNow();
}
}
使用 WebClient 调用
public class Client {
public static void main(String[] args) {
/* 调用服务器地址*/
WebClient webClient = WebClient.create("http://127.0.0.1:8080");
/* 根据ID查询*/
String id = "1";
User userResult = webClient.get().uri("/user/{id}",id)
.accept(MediaType.APPLICATION_JSON).retrieve().bodyToMono(User.class)
.block();
System.out.println(userResult.getName());
/* 查询所有*/
Flux<User> results = webClient.get().uri("/user").accept(MediaType.APPLICATION_JSON).retrieve().bodyToFlux(User.class);
results.map(stu ->stu.getName()).buffer().doOnNext(System.out::println).blockFirst();
}
}
使用JdbcTemplate操作数据库实现crud
(1)整合日志框架
(2)@Nullable 注解
(3)函数式注册对象
(4)整合 JUnit5 单元测试框架
(5)SpringWebflux 使用