spring是轻量级的开源javaee框架
spring可以解决企业应用开发的复杂性
IOC是控制反转,是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合。把对象创建和对象之间的调用过程,交给Spring进行管理。
原始调用方法的方式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h212ByOL-1661318832244)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220725185523387.png)]
工厂模式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q9ubRSly-1661318832245)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220725191846168.png)]
IOC过程(进一步降低耦合度)
第一步 xml配置文件,配置创建的对象
<bean id="dao" class="com.xue.UserDao">bean>
第二部 有service类和dao类,创建工厂类
class UserFactory{
public static User getDao(){
//使用xml解析+反射做到
String classValue = class属性值;//1.xml解析
class clazz = Class.forName(classValue);//2.通过反射创建对象
return (UserDao)clazz.newInstance();
}
}
1.IOC思想基于IOC容器完成,IOC容器底层就是对象工厂
2.Spring提供IOC容器实现两种方式:(两个接口)
(1)BeanFactory:IOC容器基本实现,spring自带的使用接口,一般不提供给我们这些开发人员使用。加载配置文件的时候不会创建对象,而是在获取对象或使用对象的时候他才去创建对象。
(2)ApplicationContext:Bean Factory的一个子接口,提供了更多更强大的功能,一般由开发人员进行使用。加载配置文件的时候就会把在配置文件中的对象进行创建。(一般用这个)
3.ApplicationContext接口有实现类
他有两个实现类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PbE3yTM7-1661318832245)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220725195223727.png)]
第一个是全路径 第二个是类路径
注:bean管理就是通过set方法实现的,所以如果某个类的属性没有set方法的话在bean里是找不到这个属性的。
<bean id="dao" class="com.xue.UserDao">bean>
在spring配置文件中,使用bean标签,标签里面添加对应的属性,就可以实现对象创建。创建对象的时候,默认走无参构造函数创建。
id:表示给对象起个别名,通过名字可以得到对象,唯一标识
class:创建对象所在类的全路径(包 类路径)
name:早期的属性,里面可以加特殊符号,id里面不可以
DI:依赖注入,就是注入属性,是IOC的一个具体实现。
第一种注入的方式,使用set方法进行注入。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Sv1kfYCr-1661318832246)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220725201309558.png)]
User类
public class User {
// public void add(){
// System.out.println("add()");
// }
private String name;
private String author;
public void setName(String name) {
this.name = name;
}
public void setAuthor(String author) {
this.author = author;
}
public void testDemo(){
System.out.println(name+"::"+author);
}
}
注入属性xml
<bean id="user" class="xue.User">
<property name="name" value="bbb">property>
<property name="author" value="ccc">property>
bean>
测试类
public class springTest {
@Test
public void testAdd(){
// ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml")类路径
// 2、获取配置创建的对象k
// "user"是xml文件里的id
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
User user = context.getBean("user", User.class);
// user.add();
System.out.println(user);
user.testDemo();
}
}
(1) 创建类,定义属性,创建属性对应的有参数的构造方法
(2) 在spring文件中进行配置
注意
无参构造注入属性
<bean id="orders" class="xue.Orders">bean>
有参构造注入属性
<bean id="orders" class="xue.Orders">
<constructor-arg name="oname" value="abc">constructor-arg>
<constructor-arg name="address" value="china">constructor-arg>
bean>
<constructor-arg index="0" value="">constructor-arg>
(1) 使用p名称空间注入,可以简化基于xml配置方式
第一步 添加p名称空间在配置文件中
xmlns:p="http://www.springframework.org/schema/p"
<bean id="user" class="xue.User" p:name="aaa" p:author="bbb">bean>
向属性里注入空值
<bean id="user" class="xue.User">
<property name="name">
<null>null>
property>
bean>
属性值包含特殊符号:把特殊符号内容写到CDATA中去
<bean id="user" class="xue.User">
<property name="name" >
<value>
value>
value>
property>
bean>
(1)创建两个类service类和dao类
(2)在service调用dao里面的方法
(3)在spring配置文件中进行配置
配置文件bean.xml
<bean id="userService" class="xue.service.UserService">
<property name="userDao" ref="userDao">property>
bean>
<bean id="userDao" class="xue.dao.UserDaoImpl">bean>
UserDao接口
public interface UserDao {
public void update();
}
UserDaoImpl实现类
public class UserDaoImpl implements UserDao{
@Override
public void update() {
System.out.println("update");
}
}
UserService
public class UserService {
private UserDao userDao;
public void setUserDao(UserDao userDao){
this.userDao=userDao;
}
public void add(){
System.out.println("add()");
userDao.update();
}
}
测试类
@Test
public void testUser(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
UserService userService = context.getBean("userService", UserService.class);
userService.add();
}
(1)一对多关系:部门和员工
一个部门有多个员工,一个员工属于一个部门
部门是一,员工是多
(2)在实体类之间表示一对多关系,员工表示所属部门,使用对象类型属性进行表示
Dept类
public class Dept {
private String name;
public void setName(String name) {
this.name = name;
}
// 如果这里不重写toString方法的话,那么在输出dept的时候输出的就是一个对象的地址
// 如果写了toString那么她就会按照toString里返回的东西输出
@Override
public String toString() {
return "Dept{" +
"name='" + name + '\'' +
'}';
}
}
Emp类
//员工
public class Emp {
private String name;
private String gender;
// 员工属于某一个部门,使用对象形式表示
private Dept dept;
public void setName(String name) {
this.name = name;
}
public void setGender(String gender) {
this.gender = gender;
}
public void setDept(Dept dept) {
this.dept = dept;
}
public void add(){
System.out.println("emp=====add()");
System.out.println(name+"=="+gender+"=="+dept);
}
}
配置文件bean.xml
<bean id="emp" class="xue.bean.Emp">
<property name="name" value="lucy" >property>
<property name="gender" value="nv">property>
<property name="dept">
<bean id="dept" class="xue.bean.Dept">
<property name="name" value="安保部">property>
bean>
property>
bean>
测试类
@Test
public void testEmp(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
Emp emp = context.getBean("emp", Emp.class);
emp.add();
}
<bean id="emp" class="xue.bean.Emp">
<property name="name" value="lucy" >property>
<property name="gender" value="nv">property>
<property name="dept" ref="dept">property>
bean>
<bean id="dept" class="xue.bean.Dept">
<property name="name" value="级联赋值">property>
bean>
或
<bean id="emp" class="xue.bean.Emp">
<property name="name" value="lucy" >property>
<property name="gender" value="nv">property>
<property name="dept" ref="dept">property>
<property name="dept.name" value="aaa">property>
bean>
getDet方法:返回dept对象
public Dept getDept() {
return dept;
}
1.注入数组类型的属性
2.注入List集合类型的属性
3.注入Map集合类型的属性
Stu类
public class Stu {
private String[] courses;
private List<String> list;
private Map<String,String> maps;
private Set<String> sets;
public void setSets(Set<String> sets) {
this.sets = sets;
}
public void setList(List<String> list) {
this.list = list;
}
public void setMaps(Map<String, String> maps) {
this.maps = maps;
}
public void setCourses(String[] courses) {
this.courses = courses;
}
public void test(){
System.out.println("courses:"+ Arrays.toString(courses));
System.out.println("list:"+list);
System.out.println("map:"+maps);
System.out.println("set:"+sets);
}
}
bean.xml
<bean id="stu" class="xue.collectionType.Stu">
<property name="courses">
<array>
<value>语文value>
<value>数学value>
array>
property>
<property name="list">
<list>
<value>张三value>
<value>小三value>
list>
property>
<property name="maps">
<map>
<entry key="0" value="aaa">entry>
<entry key="1" value="bbb">entry>
map>
property>
<property name="sets">
<set>
<value>mysqlvalue>
<value>redisvalue>
<value>mysqlvalue>
set>
property>
bean>
测试类
@Test
public void testStu(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
Stu stu = context.getBean("stu", Stu.class);
stu.test();
}
输出
courses:[语文, 数学]
list:[张三, 小三]
map:{0=aaa, 1=bbb}
set:[mysql, redis]
Stu类多加属性
// 学生所学的多门课程
private List<Course> courseList;
public void setCourseList(List<Course> courseList) {
this.courseList = courseList;
}
xml配置文件
<bean id="stu" class="xue.collectionType.Stu">
<property name="courseList">
<list>
<ref bean="course1">ref>
<ref bean="course2">ref>
list>
property>
bean>
<bean id="course1" class="xue.collectionType.Course">
<property name="name" value="spring5框架课程">property>
bean>
<bean id="course2" class="xue.collectionType.Course">
<property name="name" value="mybatis框架课程">property>
bean>
在spring配置文件中引入名称空间util
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/beans/spring-util.xsd">
book类
public class Book {
private List<String> list;
public void setList(List<String> list) {
this.list = list;
}
}
配置文件
<util:list id="bookList">
<value>book1value>
<value>book2value>
<value>book3value>
util:list>
<bean id="book" class="xue.collectionType.Book">
<property name="list" ref="bookList">property>
bean>
1、Spring有两种类型Bean,一种普通bean,另外一种工厂bean(FactoryBean)
2、普通bean:在配置文件中定义bean类型就是返回类型
3、工厂bean:在配置文件定义bean类型可以和返回类型不一样
第一步 创建类,让这个类作为工厂bean,实现接口FactoryBean
第二步 实现接口里面的方法,在实现的方法中定义返回的bean类型
MyBean类
public class MyBean implements FactoryBean<Course> {
// 定义返回bean的对象
// 虽然是MyBean类但是通过重写getObject方法,可以返回一个course对象 这样就更改了他的返回值类型
@Override
public Course getObject() throws Exception {
Course course = new Course();
course.setName("aaa");
return course;
}
}
配置文件
<bean id="myBean" class="xue.factoryBean.MyBean">bean>
测试类
@Test
public void testBean(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
//这里的getBean的第二个参数也要改成需要返回的对象的类型
Course course = context.getBean("myBean", Course.class);
System.out.println(course);
}
1、在spring里面,设置创建bean实例是单例还是多例
2、在spring里默认情况下,bean是一个单实例对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-choWbhjI-1661318832247)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220727133607086.png)]
3、如何设置单实例还是多实例
(1)spring配置文件bean标签里面有属性(scope)用于设置单实例还是多实例
(2)scope属性值
第一个值 默认值,singleton,表示单实例对象
第二个值 prototype,表示是多实例对象
<bean id="myBean" class="xue.factoryBean.MyBean" scope="prototype">bean>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ile6uCOi-1661318832247)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220727134202856.png)]
(3)singleton和prototype区别
第一 singleton是单实例,prototype是多实例
第二 设置scope值是singleton时候,加载spring配置文件时候就会创建单实例对象
设置scope的值为prototype时,不是在加载spring配置文件时创建对象,而是在调用getBean方法的时候创建对象
request
session
4、bean生命周期
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ixKBfSP5-1661318832248)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220727135815252.png)]
销毁IOC容器的方法
context.close()
<bean id="myBean" class="xue.factoryBean.MyBean" scope="singleton" init-method="a()" destroy-method="b()">bean>
5、演示添加后置处理器效果
(1)创建类,实现接口BeanPostProcessor,创建后置处理器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BLMZMKum-1661318832248)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220727150217632.png)]
MyBeanPost方法
public class MyBeanPost implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在初始化之前执行的方法 ");
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("在初始化之后执行的方法 ");
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}
}
配置文件
<bean id="myBeanPost" class="xue.bean.MyBeanPost">bean>
1、什么是自动装配
(1)根据指定装配规则(属性名称或者属性类型),spring自动将匹配的属性值进行注入
2、演示自动装配的过程
根据属性名称自动装配
<bean id="emp" class="xue.autowire.Emp" autowire="byName">
bean>
<bean id="dept" class="xue.autowire.Dept">bean>
(2)根据属性类型自动装配
<bean id="emp" class="xue.autowire.Emp" autowire="byType">
bean>
<bean id="dept" class="xue.autowire.Dept">bean>
1、直接配置数据库信息
(1)配置德鲁伊连接池
<bean id="druid" 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>
(2)引入德鲁伊连接池依赖jar包
2、引入外部属性文件配置数据库连接池
(1)创建外部属性文件,properties格式文件,写数据库信息
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JpWrFole-1661318832248)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220727170423854.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bJZIVp8r-1661318832249)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220727173009130.png)]
注解默认是单例
@Component
@Service
@Controller
@Repository
这四个都是一样 的作用,作用在类上面,只是使用的位置不一样,方便使用者分清角色
第一步 引入依赖 aop依赖
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5khjM3er-1661318832249)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220727174043451.png)]
第二步 开启组件的扫描
只有开启组件的扫描,spring才知道哪里有注解
<context:component-scan base-package="xue">context:component-scan>
例如:
//在注解里面value属性值可以不写,默认值是类名称,首字母小写
@Component(value = "userService")// 是等价的
public class UserService {
public void add(){
System.out.println("add()");
}
}
开启组件扫描细节配置
1、配置哪些类扫描哪些类不扫描
use-default-filters="false"表示现在不使用默认filter,自己配置filter context:include-filter,设置扫描哪些内容
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GY7BkWAD-1661318832250)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220728095029130.png)]
只扫描Controller注解
2、设置哪些内容不去扫描[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iMzRYa8u-1661318832250)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220728095224564.png)]
(1)@Autowired
(2)@Qualitiler
@Service
public class UserService {
// 添加注入属性注解 不需要添加set方法
@Autowired
// 一个接口有多个实现类,她不知道该找哪个实现类,所以加个名字
// 如果不写的话,默认就是她首字母小写的实现类
@Qualifier(value = "userDaoImpl")
private UserDao userDao;
public void add(){
System.out.println("service----add()");
userDao.add();
}
}
(3)@Resource
(4)@Value
@Value(value = "aaa")
private String name;
纯注解开发
(1)创建配置类,替代xml配置文件
@Configuration//作为配置类,替代xml配置文件
@ComponentScan(basePackages = "xue")//相当于xml配置扫描某个包
public class SpringConfig {
}
(2)编写测试类
@Test
public void test(){
// 代替了之前的bean.xml文件
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
// 如果不写@Component(value = "userService"),那么getBean的第一个参数就是类名的首字母小写
UserService userservice = context.getBean("userService", UserService.class);
userservice.add();
}
面向切面(方面)编程,可以对业务逻辑的各个部分进行隔离,从而使业务逻辑各个部分进行隔离,从而使业务逻辑各个部分之间的耦合度降低,降低程序的可重用性。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uHyFjYqb-1661318832251)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220728131622563.png)]
通俗描述:不改源代码,添加新功能
AOP底层使用动态代理
第一种 有接口情况,使用JDK动态代理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FQJvPzQx-1661318832252)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220728133122594.png)]
第二种 没有接口情况,
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b9FbyTXv-1661318832253)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220728133633200.png)]
AOP(jdk动态代理)
使用jdk动态代理,使用Proxy类里面的方法创建代理对象 调用newProxyInstance方法
这个方法里有三个参数,第一个类加载器classLoader,第二个增强方法所在的类,这个类实现的接口支持多个接口,第三个InvocationHandler(interface)实现这个接口创建代理的对象,写增强的方法。
编写jdk动态代理代码
(1)创建接口,定义方法
public interface UserDao {
public int add(int a ,int b);
public void update(String id);
}
(2)创建接口实现类,实现方法
@Repository
public class UserDaoImpl implements UserDao{
@Override
public int add(int a, int b) {
return a+b;
}
@Override
public String update(String id) {
return id;
}
}
JDKProxy代理类
public class JDKProxy {
public static void main(String[] args) {
Class[] interfaces = {UserDao.class};
// Proxy.newProxyInstance(
// JDKProxy.class.getClassLoader(),
// interfaces,
// new InvocationHandler() {
// @Override
// public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// return null;
// }
// }
// );
UserDaoImpl userDao = new UserDaoImpl();
Proxy.newProxyInstance(
JDKProxy.class.getClassLoader(),
interfaces,
new UserDaoProxy(userDao)
);
}
}
//创建代理对象的代码
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("qian");
// 被增强的方法执行
// 方法之后
return 1;
}
}
1、连接点
类里面的哪些方法可以被增强,这些方法成为连接点。
2、切入点
实际被真正增强的方法,成为切入点
3、通知(增强)
(1)实际增强的逻辑部分成为通知(增强)
(2)通知有多种类型
4、切面
是动作
(1)把通知应用到切入点的过程
(1)什么是AspectJ
(1)基于xml配置文件实现
(2)基于注解方式实现(使用)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BlOusJPb-1661318832254)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220729105045645.png)]
主要是
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-aopartifactId>
<version>2.7.0version>
dependency>
(1)切入点表达式作用:知道对哪个类里面的哪个方法进行增强
(2)语法结构:
Execution([权限修饰符] [返回类型] [类全路径] ([参数列表]))
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-M3SOeqBX-1661318832254)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220729105816764.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2S4l6r7w-1661318832254)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220729105953869.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-igNHbteF-1661318832255)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220729110131579.png)]
//被增强的类
public class User {
public void add(){
System.out.println("add====");
}
}
(1)在增强类里面创建方法,让不同方法代表不同通知类型
//增强的类
public class UserProxy {
// 前置通知 在add()方法前执行
public void before(){
System.out.println("before======");
}
}
如果切面不起作用的话,在User类上加注解:@EnableAspectJAutoProxy(exposeProxy = true)
(1)在spring的配置文件中,开启注解的扫描
<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="xue.aopanno">context:component-scan>
beans>
(2)使用注解创建User和UserProxy对象
@Component
public class UserProxy {}
@Component
public class User {}
(3)在你的增i强的类上面添加注解@Aspect
@Component
@Aspect
public class UserProxy {}
(4)在spring的配置文件中开启生成代理对象
<aop:aspectj-autoproxy>aop:aspectj-autoproxy>
(1)在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置
//增强的类
@Component
@Aspect
public class UserProxy {
// 前置通知 在add()方法前执行
// @Before表示作为前置通知
// 后置@After
// @AfterReturning在方法返回结果后执行,最终通知
// 异常通知@AfterThrowing
// 环绕通知@Around
@Before(value = "execution(* xue.aopanno.User.add(..))")
public void before(){
System.out.println("before======");
}
}
环绕通知:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hZltFGdA-1661318832255)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220729135254694.png)]
结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ScxQ7z89-1661318832255)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220729135537861.png)]
测试
public class TestAop {
@Test
public void testAopAnno(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
User user = context.getBean("user", User.class);
user.add();
}
}
注意:这个test必须要引入依赖包
<dependency> <groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<version>2.7.0version>
dependency>
输出
before==
add====
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CeuRgLYK-1661318832256)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220729145734408.png)]
(1)在增强类上面添加注释@Order(数组型值),数字型值越小优先级越高
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jZlyYibY-1661318832256)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220729150305371.png)]
AOP操作(AspectJ注解)
ConfigAop.java
@Configuration
@ComponentScan(basePackages = {"xue"})
//开启Aspect生成代理对象
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop {
}
1、什么是事务
(1)事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,如果有一个失败所有操作都失败
(2)典型场景:银行转账
2、事务四个特性ACID
(1)原子性
(2)一致性
(3)隔离性
(4)持久性
转账环境
web:
service:业务操作(创建转账的方法1.调用dao两个方法)
dao:数据库操作不写业务(创建两个方法:1.少钱的方法2.多钱的方法)
spring事务管理api,提供一个接口代表事务管理器,这个接口针对不同的框架提供不同的实现类。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kfQqCg6M-1661318832256)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220801132956230.png)]
1、在spring配置文件中,配置事务管理器
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fOYZ4Jar-1661318832257)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220801133313388.png)]
2、开启事务注解
(1)在spring配置文件引入名称空间
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tgq79NOY-1661318832257)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220801133419035.png)]
(2)开启事务注解
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Kb0HuU3D-1661318832257)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220801133523391.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z6UBAAmU-1661318832258)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220801150948242.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kgYkhBvH-1661318832258)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220801151515618.png)]
3、在service类上面(获取service类里面方法上面)添加事务注解
(1)@Transactional这个注解添加到类上面,也可以添加方法上面
(2)如果把这个注解添加类上面,这个类里面所有的方法都添加事务
(3)如果把这个注解添加方法上面,为这个方法添加事务[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dkvoaksS-1661318832258)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220801133840496.png)]
@Transactional(propagation= Propagation.SUPPORTS)
当一个事务的方法被另外一个事务方法调用的时候,这个事务方法如何执行
REQUIRED:如果有事务在运行,那当前方法就在这个事务内运行,否则,就启动一个新的事务,并在自己的事务内运行
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3amAaU4q-1661318832259)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220801134622879.png)]
REQUIRED_NEW:当前的方法必须启动新事务,并在它自己的事务内运行,如果有事务正在运行,应将他挂起
SUPPORTS:如果有事务在运行,当前的方法就在这个事务内运行,否则它可以不运行在事务中。
https://blog.csdn.net/wojiaoxubo/article/details/85158445
1、事务有特性成为隔离性,多事务操作之间不会产生影响,不考虑隔离性产生很多问题
2、有三个读问题:脏读、不可重复读、虚(幻)读
3、脏读:多事务之间,一个未提交的事务,读取到了另一个未提交事务的数据
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2Mb1z5b2-1661318832260)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220801141215452.png)]
4、不可重复读:在同一次事务中前后查询不一致的问题
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uTWxDWRn-1661318832260)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220801141153029.png)]
5、幻读:一次事务中前后数据量发生变化,用户产生不可预料的问题
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-l1Qu8Z0d-1661318832261)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220801141122224.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3dxYGpG5-1661318832262)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220801141406392.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mSnWcUxg-1661318832262)(C:\Users\28908\AppData\Roaming\Typora\typora-user-images\image-20220801142030428.png)]
(1)事务需要在一定时间内进行提交,如果不提交进行回滚
(2)默认值是-1,设置时间以秒单位进行计算
(1)读:查询操作,写:添加修改删除操作
(2)readOnly默认值false,表示可以查询,可以添加修改删除操作
(3)设置成true,只能查询,不可以添加修改删除操作
(1)设置出现哪些异常进行事务的回滚
(1)设置出现哪些异常进行事务的不进行回滚
整个spring5框架的代码基于java8,运行时兼容jdk9,旭东不建议使用的类和方法在电脑中删除,建议log4j2
整合log4j2日志
片转存中…(img-dkvoaksS-1661318832258)]
@Transactional(propagation= Propagation.SUPPORTS)
当一个事务的方法被另外一个事务方法调用的时候,这个事务方法如何执行
REQUIRED:如果有事务在运行,那当前方法就在这个事务内运行,否则,就启动一个新的事务,并在自己的事务内运行
[外链图片转存中…(img-3amAaU4q-1661318832259)]
REQUIRED_NEW:当前的方法必须启动新事务,并在它自己的事务内运行,如果有事务正在运行,应将他挂起
SUPPORTS:如果有事务在运行,当前的方法就在这个事务内运行,否则它可以不运行在事务中。
https://blog.csdn.net/wojiaoxubo/article/details/85158445
1、事务有特性成为隔离性,多事务操作之间不会产生影响,不考虑隔离性产生很多问题
2、有三个读问题:脏读、不可重复读、虚(幻)读
3、脏读:多事务之间,一个未提交的事务,读取到了另一个未提交事务的数据
[外链图片转存中…(img-2Mb1z5b2-1661318832260)]
4、不可重复读:在同一次事务中前后查询不一致的问题
[外链图片转存中…(img-uTWxDWRn-1661318832260)]
5、幻读:一次事务中前后数据量发生变化,用户产生不可预料的问题
[外链图片转存中…(img-l1Qu8Z0d-1661318832261)]
[外链图片转存中…(img-3dxYGpG5-1661318832262)]
[外链图片转存中…(img-mSnWcUxg-1661318832262)]
(1)事务需要在一定时间内进行提交,如果不提交进行回滚
(2)默认值是-1,设置时间以秒单位进行计算
(1)读:查询操作,写:添加修改删除操作
(2)readOnly默认值false,表示可以查询,可以添加修改删除操作
(3)设置成true,只能查询,不可以添加修改删除操作
(1)设置出现哪些异常进行事务的回滚
(1)设置出现哪些异常进行事务的不进行回滚
整个spring5框架的代码基于java8,运行时兼容jdk9,旭东不建议使用的类和方法在电脑中删除,建议log4j2
整合log4j2日志