spring
2022-04-02 17:33:11 206 举报AI智能生成
spring
Spring
模版推荐
作者其他创作
大纲/内容
建议
建议使用多配置文件
使用多配置文件就是spring中管理类的applicationContext.xml文件<br> 1、多配置文件,每个单独的文件就很小了,读取的效率也会提高<br> 2、避免了冲突,已经多人开发带来的竞争<br><br> 如果项目有多个模块,一个模块一个配置文件<br> 比如:之前写的学生管理系统<br> - 学生信息管理使用一个配置文件<br> - 班级管理使用一个配置文件<br> 按照类的功能进行分配,数据库相关的类放在一个配置文件,做事务管理的一个配置文件<br> service的一个配置文件等;
多配置文件的包含关系
学生模块和学校模块分开<br> spring-student.xml<br> spring-school.xml<br> 需要一个主配置文件进行包含,当我们加载主配置文件的时候,会把主配置文件中包含的配置文件<br> 加载到spring容器中<br> total.xml<br> 包含必须用到的东西:classPath:<br> 规定的是target/classes/作为根目录
1、直接指定路径包含<br> <import resource="classPath:demo04/spring-student.xml"/><br> <import resource="classPath:demo04/spring-school.xml"/>
2、使用通配符的形式<br> <import resource="classPath:demo04/spring-*.xml" />
【注意】
【注意】:这个通配符包含的文件不能包括主配置文件本身,否则会出现加载死循环<br> 并且使用这个通配符的形式,这些xml文件必须放在一个目录之下,否则无法加载<br> 这是官方文档中的声明
小知识点
1、spring配置文件读取properties配置文件
<context:property-placeholder location="classpath:student.properties"/>
spring简介
出现在2003年左右,是为了解决企业级开发的难度,减轻对项目模块之间的管理<br> 类与类之间的管理,帮助开发人员创建对象,管理对象之间的关系<br> spring的核心是ioc和aop,能实现模块之间,类之间的解耦合 <br>
官网:spring.io
spring-ioc:控制反转
1、 关于ioc的概念
<span style="font-size: inherit;">控制反转(Inversion of control):<br>原本是程序员自己创建对象, 给属性赋值。并且管理类与类之间的关系。<br>现在是spring框架,也就是spring容器来创建对象,给属性赋值,管理类与类<br>之间的关系,实现类与类之间,模块与模块之间解耦合 </span><br>
2、IOC的技术实现,就是使用DI(Dependency Injection)<br>
就是依赖注入:只需要在程序中提供需要创建的对象的名称即可<br><br> 其他的操作都是容器完成的
3、spring创建对象的步骤
1、在maven中添加依赖<br>
<dependency><br> <groupId>org.springframework</groupId><br> <artifactId>spring-context</artifactId><br> <version>5.2.5.RELEASE</version><br> </dependency><br>
2、编写spring的配置文件,也就是ApplicationContext.xml<br>
直接使用xml-configuration File<br> 然后选择spring-config,创建一个applicationContext.xml的spring配置文件
告诉spring创建对象,声明bean,告诉spring,我们需要创建哪个对象<br> id:自定义名称,唯一<br> class:创建的类的全限定名称<br> 底层需要反射机制实例化对象,因此,不能使用接口<br> 这个时候spring就会执行这样的代码<br> SomeService someService = new SomeServiceImpl();<br> 然后将这个对象放进map集合中<br> map.put("SomeService",someService);<br> 就是map.put(id,对象);
在根标签<beans>下加入类配置信息<br><bean id="唯一的标识" class="需要创建的类对象的全限定名称" />
3、在程序中使用spring来完成对象的创建
1、声明配置文件位置:target/classes是根目录。
2、spring容器加载配置文件,ApplicationContext ac = new ClassPathXmlApplicationContext(配置文件);
3、使用ac.getBean(对应的那个配置文件的bean的ID);<br>
4、获取对象以后强制类型转换成自己需要的,然后调用方法
关于spring的执行时机
1、在执行读取配置文件信息的时候就会创建对象,创建对象会调用无参构造
2、关于spring中获取创建对象的数量以及创建对象的名称
获取创建对象的数量:ac.getBeanDefinintionCount();<br>
获取所有对象的名称: String [] names = ac.getBeanDefinitionNames();
4、spring容器创建对象进行属性赋值
DI
概念
di:依赖注入,表示创建对象,给对象赋值<br> di的实现方式有两种<br> 1、在spring配置文件中,使用标签和属性完成,叫做基于XML的di实现<br> 2、使用spring中的注解,完成属性赋值,叫做基于注解的di实现
1、set注入(设值注入):spring调用类的set方法进行属性的赋值。<br> 2、构造注入:spring调用类的有参数构造方法。创建对象。创建时完成赋值;
基于xml配置文件的DI实现
set注入,设值注入
1、spring调用类的set方法进行属性的赋值。
基本类型的设值注入:(基本数据类型和String)
<bean id="user" classes="com.javase.User" ><br> <property name="id" value="1001" /><br> <property name="name" value="张三" /><br></bean><br>
1、实际上是spring底层调用了set方法进行赋值,因此必须有set方法,没有会报错!<br> 2、这个name不是指类中的属性,他底层肯定是通过反射机制找到哪个对应的set方法<br> 比如:id 就会去找setId<br> 因此:他是根据set方法进行访问的<br> 如果此时<property name="email" value="lisi@qq.com" /><br> 这个时候即使没有email这个属性,只要有setEmail方法就不会出错<br> 【那个set方法必须有参数】
引用类型的设值注入
User{id=123, name='李四', school=School{name='清华大学', address='大兴区'}}<br> 通过ref进行指向<br> User 对象中有个属性是引用数据类型 School<br> 这个时候<br> <property name="" value="" />没法直接赋值<br> 需要通过ref指向另一个对象<br> <property name="school" ref="school" />
自动注入
byName
1、 在进行set注入的时候,有的属性值是一个引用数据类型<br> 我们对于引用数据类型需要使用<property name="school" ref="myschool" /><br> 的形式,让他找到这个引用数据类型<br>
2、 现在,使用byName命名规则,spring会自动查找进行赋值,不需要手动赋值<br>给当前bean声明autowire属性:autowire="byName",这个时候,这个javabean就会<br> 自己去寻找需要的引用数据类型<br> 但是条件是:这个引用数据类型的id,必须和这个声明的属性值一样<br> 也就是:<br> private School school; 这个引用数据类型的javabean的id必须是school
byType
<bean id="user" class="com.javase.demo03.User" autowire="byType" ><br> <property name="id" value="1001" /><br> <property name="name" value="李四" /><br> </bean><br> <bean id="myschool" class="com.javase.demo03.School" ><br> <property name="name" value="北京大学" /><br> <property name="address" value="大兴区" /><br> </bean>
如果autowire属性值是:byType,这个时候,spring就会根据这个引用数据类型<br> 去查找这个数据<br> 比如说:private School school; 他就会去beans中查找这个School引用数据类型<br> 说白了就是,private School school = new School();
同源关系有三种,都可以符合 <br>1、当前javabean对应的类中的引用数据类型和beans中的某个class相同 <br>2、当前javabean对应的类中的引用数据类型在beans中有个class是他的子类 <br>2、当前javabean对应的类中的引用数据类型在beans中有个接口实现类 <br> 1、private School school = new School(); <br> 2、private School school = new SmallSchool; <br> 3、private School school = new SchoolImpl();
构造注入
构造注意前提就是必须有构造方法
1、直接使用name和value的形式,name就对应类中的属性名<br>
<bean id="user" class="com.javase.demo03.User"><br> <constructor-arg name="id" value="1001" /> <br> <constructor-arg name="name" value="李四"/> <br> <constructor-arg name="school" ref="school" /><br> </bean>
2、使用index下标的形式,从0开始,指代每个位置上的参数
<constructor-arg index="0" value="1002"/><br> <constructor-arg index="1" value="王五"/><br> <constructor-arg index="2" ref="school"/>
3、默认按照位置进行赋值<br>
<constructor-arg value="1002"/><br> <constructor-arg value="王五"/><br> <constructor-arg ref="school"/>
基于注解色DI实现
1、@Component,创建对象的注解,一般用在不是三层架构的普通类中
2、@Repository,创建对象,用在持久层中,dao接口实现的上面
3、@Service,创建对象,用在业务逻辑层,在service实现类的上面,有事务处理的功能
4、@Controller,控制层对象,用来接收用户输入,进行结果展示
5、@Value,进行属性注入,也就是属性赋值,可以用在属性上,也可以用在set方法上
6、@Autowired,自动注入,针对的是引用类型,有两种注入的方式
1、byName
通过id,也就是名字来进行查找
2、byType
默认的是这种方式,通过数据类型来进行查找,只要符合同源类型即可
当使用byName的时候,有一个注解叫做@Qualifier<br><br>是用来赋值的
7、@Resource。自动注入,这个不是spring自带的,是JDK中自带的注解
1、byName
通过javabean中的id,和属性值进行匹配
1、没有手动给这个引用数据类型附上值,则如果没有找,就会使用byType
2、手动赋值以后,没有找到就会报错
2、byType
根据类型来进行查找,同源关系
注解的实现步骤
1、在maven中加入依赖,spring-context,加入这个依赖会自动的加入spring-aop依赖,注解使用的就是srping-aop.jar
2、在类中加入注解
3、在配置文件中声明组件扫描器,通知spring去扫描哪些包寻找对象,并创建对象,<cotext:component-scan > base-package="包名"<br>
加入扫描包的三种方式
1、一次加入多个
把每个包都写出来<br><context:component-scan base-package="com.javase.domain" /><br> <context:component-scan base-package="com.javase.dao" /><br> <context:component-scan base-package="com.javase.service" />
2、通过;或者,进行包与包之间的分割
<context:component-scan base-package="com.javase.service;<br> com.javase.domain;<br> com.javase.dao" />
3、扫描父包
<context:component-scan base-package="com.javase" /><br><br> 这里建议时不要使用在高一级的包,因为文件夹越深效率越低
4、使用配置文件进行赋值操作
1、编写properties配置文件
2、在spring配置文件中声明这个属性配置文件
<context:property-placeholder location="classpath:student.properties"/><br>
3、在需要的地方比如说属性上
@(value="${name}")<br>private String name;<br>
5、通过Value("#{属性}")获取值
@Value("#{}")<br> 其实是SpEL表达式的值,可以表示常量的值,或者获取bean中的属性
目的:实现业务逻辑之间的解耦合,比如:service和dao
spring-aop:面向横切面编程
1、spring中的动态代理
1、使用JDK动态代理<br>
使用Proxy,Method,InvocationHandle来创建代理对象,条件是必须有接口
2、使用CGlib第三方工具库动态代理
要求就是他的方法不能是final的,属性不能是final的,实际底层通过继承的原理实现代理类
动态代理的优点,功能
1、在不修改源代码的情况下,对某个类中的方法进行功能的增强
2、减少重复代码<br>
3、让程序员专注于业务逻辑代码的编写<br>
4、让程序解耦合,业务功能,日志功能,事务处理功能等都分开了,互相之间的联系不紧密
2、aop是什么?
1、aop就是(Aspect Orient Programming),面向切面编程,是基于动态代理实现的<br>可以使用jdk自带的动态代理,也可以使用cglib第三方工具库。aop就是动态代理的规范化<br>他把动态代理的实现步骤已经完成了,开发人员只需要通过一定的规范就行为和使用即可<br>
2、 怎么理解面向切面编程:
1、在分析业务功能的时候,分析出哪些功能是切面功能,找到合适的切面<br>
2、合理的安排切面的执行时机,在目标方法的前面还是目标方法的后面
3、合理的安排切面的执行位置,在哪个类上,在哪个方法上<br>
切入点表达式
比如说有一个业务逻辑是这样的。需要在用户进行购买商品的时候记录下的操作的时间,token等信息的时候。就可以使用AOP,分析出一个切面,创建一个切面增强方法,完成业务逻辑。
3、aop的作用<br>
1、在不修改源代码的情况下,增强功能
2、减少代码的重复
3、程序员可以专注于业务逻辑的实现<br>
4、解耦合,业务逻辑。事务处理,日志管理等之间解耦合
4、什么时候考虑使用aop
1、给系统中已经存在的一个类增加功能,在不修改源代码的情况下增加功能<br>
2、项目中多个类都需要实现同一个功能<br>
3、给业务方法增加事务,或者日志输出等<br>
3、相关术语
1、Asepect:切面的,就是一个类,比如:MyAspect.java这个类,这个类中有方法,<br>方法就是切面方法,目的是增强功能的。是给业务逻辑代码,常见的有,日志输出,事<br>务处理,统计信息,参数检查,权限验证等<br>
2、JoinPoint:连接点,就是指某个目标方法,那就是一个切入点,连接业务方法和切面的位置,就是那个业务方法
3、Pointcut:切入点,就是多个连接点的集合,多个方法
4、目标对象,就是需要增强功能的那个类<br>
5、Advice:通知,也可以称之为增强,通知切面的执行时间,是在方法前,还是在方法之后?
4、一个切面必须要有的三要素:
1、必须有切面的功能代码,就是用来增强业务的代码<br>
2、必须有切入点,就是切面的执行位置
3、必须有通知,就是通知切面的执行时间
5、关于aop的实现
1、spring
spring框架内部实现了aop,可以使用aop进行工作,<br>一般都是在事务处理中使用aop,但是spring使用aop比较繁琐,麻烦<br>
2、AspectJ
是另一个框架,是专门用来做aop的,spring框架已经集成了aspectJ框架<br>通过spring,可以使用aspectJ的aop功能
AspectJ的两种使用方式
1、使用xml配置文件,配置全局事务
2、使用注解开发,5个注解
6、AspectJ框架的具体实现
1、aspectJ的实现步骤<br>
1、添加spring依赖
2、添加aspectJ依赖
3、创建接口和接口实现类
4、创建切面类增强功能,执行切面的执行位置,切面的执行时间<br>
5、将对象交给spring容器进行管理
6、声明代理对象的配置信息<br>
<aop:aspectj-autoproxy proxy-target-class="true"/>【必须声明】
2、切入点表达式,确定切面的执行位置
切入点表达式,是使用在注解上的,是声明这个注解,也就是这个切面的执行位置
语法规则:execution(访问控制修饰符 返回值类型 包名.类名.方法名(形参列表)) 抛出异常 )
* 匹配任意一个或者多个字符<br><br> .. 使用在参数上,表示有0个或者多个参数<br> 使用在包上,表示当前包和子包<br><br> + 使用在类上,表示当前类和子类<br> 使用在接口上,表示当前接口及其实现类
execution(public * *(..))<br> 指定切面执行的位置:表示所有公共的方法<br> execution(* set*(..)) 只有连个参数 : 返回值 方法名(参数)<br> 指定切面执行的位置:表示所有以set开头的方法<br> execution(* com.javase.service.*.*(..))<br> 指定切面执行的位置:表示com.javase.service下的所有类中的所有方法,方法参数任意<br> execution(* com.javase.service..*.*(..))<br> 指定切面执行的位置:表示com.javase.service包及其子包下的所有类的所有方法<br> execution(* *..service.*.*(..))<br> 指定切面执行的位置:表示所有路径下的service包中的所有类的所有方法<br> 比如: com.javase.service.<br> com.javase.dao.service.<br> crm.javase.service.
3、通知,Advice,使用5个注解完成,确定切面的执行时间
1、关于参数:JoinPoint jp:每个通知都可以有这个参数,这个参数如果出现必须是第一个位置上<br>2、这个参数是用来获取目标方法的签名的<br>3、使用方法: - 获取签名:Signature sign = jp.getSignature();<br> - 获取方法名:String name = sign.getName();<br> - 获取参数:Object [] args = jp.getArgs();
1、@Before:前置通知
1、必须使用在类上<br>2、必须指定切入点表达式<br>3、返回值为void<br>4、没有参数,有的话只有一个
@Before(value="execution(* *..service.*.do*(..))")<br>public void doBefore(){<br><br>}
2、@AfterReturning:后置通知
1、必须使用在类上<br>2、必须指定切入点表达式<br>3、没有返回值<br>4、有参数,Object res ,如果还有就是jp<br>5、这个参数的名称必须和注解中的returning相同
@AfterReturning(value="execution()",returning="res")<br>public void doAfterReturning(Object res){<br><br><br>} <br>
1、关于基本数据类型和String,在这个类中修改不影响返回值
2、如果是引用数据类型,使用set方法进行了数据的改动,则返回的那个数据就会有变化
3、@Around:环绕通知
1、必须使用在类上<br>2、必须指定切入点表达式<br>3、返回值为Object<br>4、参数只有一个就是ProceedingJoinPoint<br>5、使用pjp.proceed()就是执行目标方法,等价于<br> method.invoke()<br>6、可以改变返回值结果,可以进行中间阶段的判断<br>7、因为pjp的父类是JoinPoint,可以读取参数,进行判断<br>8、几乎就是那个Proxy中的InvocationHanler接口实现类
@Around(value="execution()")<br>public Object doAround(ProceedingJoinPoint pjp){<br> Object res = null;<br> //在前面加强<br> res = pjp.proceed();//执行目标方法<br> //在后面加强<br> return res;<br>}
4、@AfterThrowing:异常通知
1、必须使用在类上<br>2、必须指定切入点表达式<br>3、没有返回值<br>4、有参数,是Exception e,如果还有就是jp<br>5、这个参数的名称必须和注解中的throwing相同<br>6、他的实际意义就是<br>try{<br> 这里是目标方法执行<br>}catch(){<br> 如果目标方法出现异常,则在这里执行并打印异常信息<br>}<br>
@AfterThrowing(value="execution()",throwing="e")<br>public void doAfterThrowing(Exception e){<br> e.getMsg();<br>}
5、@After:最终通知
1、必须使用在类上<br>2、必须指定切入点表达式<br>3、没有返回值<br>4、没有参数,如果有就是jp<br>5、他的实际意义就是<br> try{<br> 目标方法执行<br> }catch (Exception e){<br> 如果出现异常信息,就会e.printStackTrace();<br> }finally{<br> 【总是被执行】<br> }<br>
@After(value="execution()")<br><br>public void doAfter(){<br><br><br><br>} <br>
6、@Pointcut:切入点表达式管理的注解<br>就是省力了,如果有多个一样的切入点表达式<br>直接就用那个别名了
1、使用注解@Pointcut,来对切入点表达式进行定义和管理<br> 2、出现在方法的上面<br> - 这个方法没有返回值<br> - 这个方法的方法体没有代码<br> - 这个方法没有参数<br> 3、这个方法的方法名就是这个定义的切入点表达式的别名<br> 使用的语法规则:<br> @Pointcut(value="execution(表达式)")<br> private void mypt(){<br><br> }<br> 因为这个表达式一般都是在本类中进行使用,因此定义为private<br> 并且,这个方法名mybt就是这个表达式的别名<br>
4、cglib动态代理的实现
1、spring已经集成了cglib代理
2、cglib代理不需要接口就能实现,底层原理是通过集成
3、如果没有使用接口,底层创建代理对象使用的就是cglib
4。如果使用接口也可以使用cglib,需要在配置文件中进行设置
<aop:aspectj-autoproxy proxy-target-class="true" />
spring-mybatis整合开发
1、spring整合mybatis的想法
就是spring框架使用ioc技术将mybatis的对象交给spring来进行统一创建和管理
例如:service对象,dao对象,工具类对象,控制层对象
2、开发步骤
1、在maven中加入依赖
1、加入spring依赖<br> 2、加入mybatis依赖<br> 3、加入mysql驱动依赖<br> 4、加入单元测试junit依赖<br> 5、加入spring事务处理的依赖<br> 6、加入druid连接池的依赖<br> 7、加入spring和mybatis集成的依赖<br> 8、加入pagehelper分页依赖<br> 需要在mybatis配置文件中加入插件信息<br> <plugins><br> <plugin interceptor="com.github.pagehelper.PageInterceptor" /><br> </plugins>
2、创建实体类<br>
3、创建dao接口
4、编写sql映射文件(mapper文件),也就是每个数据库dao对应的xml配置文件
5、编写mybatis主配置文件
6、编写service及其实现类
7、创建spring配置文件,将mybatis中需要的对象交给spring容器管理<br>
1、dataSource数据源对象
就是数据库连接池:druid
<!-- dataSource数据库连接池,我是用的是druid --><br> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><br> <property name="url" value="${jdbc_url}"/><br> <property name="username" value="${jdbc_user}"/><br> <property name="password" value="${jdbc_pwd}"/><br> <property name="maxActive" value="${jdbc_max}"/><br> </bean>
2、mybatis主配置文件加载的SqlSessionFactoryBean对象
就是sqlSessionFactory
<!-- 创建SqlSessionFactoryBean对象 --><br> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"><br> <property name="dataSource" ref="dataSource"/><br> <property name="configLocation" value="classpath:mybatis.xml"/><br> </bean>
3、dao对象,就是数据库操作类的实现类,这里使用的还是代理类的形式<br>
<!--将所有的dao代理对象都创建出来--><br> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><br> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/><br> <property name="basePackage" value="com.javase.dao"/><br> </bean>
4、创建service业务处理
8、创建测试类,获取service对象,通过service调用dao完成数据的处理
3、spring整合的mybatis的事务是自动提交的
4、关于spring配置文件中读取属性配置文件
<context:property-placeholder location="classpath:student.properties"/>
spring-事务处理机制
1、什么是事务?
是指在一个业务中(一个业务划分的最小单元),涉及到多张表,或者是多条DML语句共同参与,并且要求这几条DML语句同时成功,或者同时失败,才能完成业务逻辑。那么几条DML语句捆绑执行,同时成功同时失败,这个整体就是一个事务,比如银行转账,必须两个账户的余额更新同时成功或者同时失败
2、以前怎么处理事务?
1、JDBC中,使用conn连接处理事务,使用的是conn.commit(),或者是conn.rollback()
2、Mybatis中,使用sqlSession处理事务,sqlSession.commit() , sqlSession.rollback()
3、在hibernate中,使用Hibernate.commit() , Hibernate.rollback()处理事务
3、不足之处?
每一种数据库访问技术都有自己的一个事务的处理方式,没有一个统一的规范化,不利于开发
4、spring处理事务有什么优点?
优点:spring将各种不同类型的数据访问技术都集成了,提供了一个事务的统一模型<br> 即使是不同类型的数据访问技术,也可以使用这个步骤
5、spring怎么处理事务?
1、spring使用事务管理器机制,使用事务管理器对象完成事务的提交和回滚
2、事务管理器是由接口和他的众多实现类构成的
3、 接口:PlatformTransactionManager,定义了事务的重要方法,commit和rollback<br> 实现类:spring把每种数据库访问技术的对应的事务处理的实现类都定义好了<br> mybatis访问数据库 ---> DataSourceTransactionManager<br> hibernate访问数据库 ---> HibernateTransactionManager
6、spring怎么使用事务?
1、告诉spring,你需要使用哪种数据库访问技术<br>
2、在spring配置文件中声明这个类型,就是对应的事务的管理器对象的实现类<br>
Mybatis <bean id="transactionManager" class="DataSourceTransactionManager"><br> <property name="dataSource" ref="dataSource" /><br> </bean><br>
7、事务有哪些处理机制,哪些事务类型
事务的属性
1、事务的隔离级别
1、DEFAULT:spring默认的隔离级别,读已提交
默认的
2、READUNCOMMIT:读未提交(脏读)
3、READCOMMIT:读已提交
4、REPEARABLE_READ:可重复读<br>
5、SERIALIZABLE:序列化读
2、事务的传播行为
1、propagation_required
如果已经有事务,则使用当前事务,如果当前没有事务,会新建事务
默认的
2、propagation_supports
当前方法支持事务,就是有事务可以,没有事务也可以,支持:supports
3、propagation_requires_new
当前方法必须有事务,及时他在的这个方法已经有事务,这个事务必须挂起,等待当前的事务
4、propagation_mandatory
你要调用我,你必须有事务,没有事务就报错<br> 支持当前事务;如果不存在当前事务,则抛出异常。<br>
5、propagation_nested
如果存在当前事务,则在嵌套事务中执行,行为如下propagation_required不然的话。
6、propagation_never
不支持当前事务;如果存在当前事务,则抛出异常。
7、propagation_not_supported
不支持当前事务,而是始终以非事务方式执行。
3、事务的超时时长
timeout
- 就是指当前事务执行的最大时间,如果超过了这个时间,事务就会回滚<br> - 一般都是不设置的,单位是s(秒)<br> TIMEOUT_DEFAULT<br> 使用基础事务系统的默认超时,如果不支持超时,则不使用。
默认
8、使用注解的方式进行事务的处理
1、注解方式是spring自带的事务处理的方式,适合中小型项目
2、使用spring注解控制事务的步骤
1、声明事务管理器对象
<bean id="transactionManager" class="DataSourceTransactionManager"><br> <property name="dataSource" ref="dataSource" /><br></bean><br>
- 创建事务管理器对象<br>- 声明使用哪种数据库的数据源
2、告诉spring我们将使用注解的形式进行事务的控制<br>
<!--开启注解的驱动,就是告诉spring,我们要使用注解的形式进行事务的控制--><br><br> <tx:annotation-driven transaction-manager="transactionManager"/><br>
- 声明注解式开发<br>- 指定事务管理器对象<br>- 切记这里是<br> tx:annotation-driven
xmlns:tx="http://www.springframework.org/schema/tx"<br><br>http://www.springframework.org/schema/tx <br><br> http://www.springframework.org/schema/tx/spring-tx.xsd<br>
3、使用注解进行事务控制
1、使用@Transactional注解进行开发
2、这个注解一般都是出现在方法上,就是需要控制事务的那个类,一般不在类上,因为不是所有的方法都需要进行事务的控制
3、@Transactional的属性
1、Propagation(事务的传播方式) -----> Propagation.REQUIRED<br>
2、isolation(事务的隔离级别) -----> Isolation.DEFAULT
3、readOnly(数据库信息是否只读,这个针对于查询,提高效率) -----> false
4、timeout(处理事务的超时时间) -----> -1
5、rollbackFor(指定需要回滚的异常类,是Class[]数组) ----->
6、rollbackForClassName(指定需要回滚的异常类类名) ----->
7、noRollbackFor:指定不需要回滚的异常类。
8、noRollbackForClassName:指定不需要回滚的异常类类名。类型为 String[],
4、底层实现原理
环绕通知实现
@Around()<br> public Object doAfter(ProceedingJoinPoint pjp){<br> spring开启事务<br> try{<br> pjp.目标方法执行()<br> spring提价事务<br> } catch ( Exception e ) {<br> spring回滚事务<br> }finally{<br> spring关闭事务<br> }<br> }
9、使用aspectJ的aop进行事务的处理
1、使用aspectJ框架进行事务的处理,适合于中大型项目的开发
2、开发步骤
1、加入新的依赖,使用aspectJ依赖
新加入 aspectj 的依赖坐标<br> <dependency><br> <groupId>org.springframework</groupId><br> <artifactId>spring-aspects</artifactId><br> <version>5.2.5.RELEASE</version><br> </dependency> <br>
2、创建事务管理器对象,告诉spring我们使用的是那种数据库访问技术
<bean id="transactionManager" class="DataSourceTransactionManager"><br><br> <properties name="dataSource" ref="dataSource" /><br><br> </bean>
3、配置事务通知(就是事务的属性,就是那个注解中的相关参数-->@Transactional(参数信息))
1、通知某个方法使用哪种事务的处理方式(隔离级别,传播行为,超时时间等)
2、id:id是自定义的
3、transaction-manager:事务管理器对象,使用使用上面定义的管理器对象
4、<tx:attributes>:就是设置事务的属性
5、<tx:method name="buy":就是针对某个或者某些方法
6、rollback-for:这个抛出异常必须是全限定名称
<tx:advice id="buyAdvice" transaction-manager="transactionManager"><br> <tx:attributes><br> <tx:method name="buy"<br> propagation="REQUIRED"<br> isolation="DEFAULT"<br> read-only="false"<br> rollback-for="java.lang.NullPointerException,<br> com.javase.execption.NotStockExecption" <br> /><br> </tx:attributes><br> </tx:advice><br>
4、配置增强器
1、上面的事务已经设置完毕,那么这个事务到底是针对于那个方法?那个类中中的方法?
2、需要配置一个增强器:就是指定你配置好的那个事务,到底是给谁用的
3、这个地方需要配置一个aop
<aop:config><br><br> <!--切入点表达式,指定位置--><br><br> <aop:pointcut id="servicept" expression="execution(* *..service..*.*(..))"/><br><br> <!--声明增强器,将切入点表达式和上面声明的事务连接起来--><br><br> <aop:advisor advice-ref="buyAdvice" pointcut-ref="servicept"/><br><br> </aop:config>
xmlns:aop="http://www.springframework.org/schema/aop"<br> http://www.springframework.org/schema/aop<br><br> https://www.springframework.org/schema/aop/spring-aop.xsd<br>
spring-web开发部署
1、环境配置
1、使用模板创建项目,webapp项目
2、增加目录,java,resource等标准的web开发目录结构
3、配置pom文件添加对应依赖
1、自动添加了junit单元测试依赖
2、添加spring-context框架依赖
3、添加spring-tx,事务处理依赖
4、添加spring-jdb,事务处理依赖
5、添加mybatis依赖
6、添加spring-mybatis集成依赖
7、添加mysql驱动依赖
8、添加druid数据库连接池依赖
9、添加aspectJ处理事务的依赖
10、添加java.servlet-api依赖
11 、添加jsp-api依赖
12、添加github中的分页处理工具依赖
13、添加获取spring容器的web依赖
<!-- 用来获取spring容器对象的依赖--><br> <dependency><br> <groupId>org.springframework</groupId><br> <artifactId>spring-web</artifactId><br> <version>5.2.5.RELEASE</version><br> </dependency>
2、业务处理,三层架构配置
4、编写实体类
5、编写dao接口及mapper文件
6、配置mybatis主配置文件
7、编写service及其实现类
8、编写spring配置文件,将对象交给spring容器进行管理
9、创建controller控制层servlet,进行控制层操作
3、spring容器对象的获取的方法
配置spring配置文件的位置,可以被ContextLoaderListener读取到
XML文件中配置<br> <context-param><br><br> <param-name>contextConfigLocation</param-name><br><br> <param-value>classpath:applicationContext.xml</param-value><br><br> </context-param><br>
1、直接获取
String key = WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE;<br><br>// WebApplicationContext ac = (WebApplicationContext) this.getServletContext().getAttribute(key);
2、通过WebApplicationContextUtils工具进行获取
WebApplicationContext ac = WebApplicationContextUtils.getRequiredWebApplicationContext(this.getServletContext()); <br>
Collect
Get Started
Collect
Get Started
Collect
Get Started
Collect
Get Started
评论
0 条评论
下一页