Spring
2021-09-19 17:34:32 23 举报
AI智能生成
此导图中含有Spring相关基础知识,从环境搭建,Ioc,DI,到Spring+myBatis的整合,还有Aop,最后还加了一些有关事务的操作,Spring是比较基础的框架,几种方式也有介绍
作者其他创作
大纲/内容
Spring配置文件
spring-context.xml
初始化对象
三种方式
1.get/set方式
当前对象中必须有属性的get/set方法 <property name="属性名" value="值">
<bean id="tbUser" class="com.qf.pojo.TbUser">
<property name="id" value="1"></property>
<property name="name" value="张宁"></property>
<property name="age" value="2"></property>
<property name="tbUserInfo" ref="tbUserInfo2"></property>
</bean>
<property name="id" value="1"></property>
<property name="name" value="张宁"></property>
<property name="age" value="2"></property>
<property name="tbUserInfo" ref="tbUserInfo2"></property>
</bean>
2.构造器
<constructor-arg name="属性名" value="值">
<bean id="tbUser" class="com.qf.pojo.TbUser">
<constructor-arg name="age" value="1"></constructor-arg>
<constructor-arg name="id" value="1"></constructor-arg>
<constructor-arg name="name" value="扎根"></constructor-arg>
<constructor-arg name="tbUserInfo" ref="tbUserInfo2"></constructor-arg>
</bean>
<constructor-arg name="age" value="1"></constructor-arg>
<constructor-arg name="id" value="1"></constructor-arg>
<constructor-arg name="name" value="扎根"></constructor-arg>
<constructor-arg name="tbUserInfo" ref="tbUserInfo2"></constructor-arg>
</bean>
3.p标签
p:属性值=value
<bean id="tbUserInfo2" class="com.qf.pojo.TbUserInfo" p:addr="南窑头国际城" p:idCard="1111" p:phone="134" p:userId="1"></bean>
实体类对象初始化
基本数据类型
String
<property name="password" value="ceshi"></property>
<property name="sex" value="1"></property>
<property name="sex" value="1"></property>
Integer
<property name="age" value="2"></property>
Date
<property name="bornDate" value="2021/09/16"></property>
set
<property name="phones">
<set>
<value>121</value>
<value>123</value>
<value>123</value>
<value>124</value>
</set>
</property>
<set>
<value>121</value>
<value>123</value>
<value>123</value>
<value>124</value>
</set>
</property>
list
<property name="names">
<list>
<value>颤三</value>
<value>王五</value>
<value>赵六</value>
</list>
</property>
<list>
<value>颤三</value>
<value>王五</value>
<value>赵六</value>
</list>
</property>
map
<property name="countries">
<map>
<entry key="bj" value="京"></entry>
<entry key="xa" value="西"></entry>
<entry key="xg" value="香"></entry>
<entry key="tl" value="铁"></entry>
</map>
</property>
<map>
<entry key="bj" value="京"></entry>
<entry key="xa" value="西"></entry>
<entry key="xg" value="香"></entry>
<entry key="tl" value="铁"></entry>
</map>
</property>
properties
<property name="files">
<props>
<prop key="one">one</prop>
<prop key="two">two</prop>
</props>
</property>
<props>
<prop key="one">one</prop>
<prop key="two">two</prop>
</props>
</property>
数组
<property name="hobbys">
<array>
<value>踢足球</value>
<value>踢篮球</value>
<value>踢羽毛球</value>
</array>
</property>
<array>
<value>踢足球</value>
<value>踢篮球</value>
<value>踢羽毛球</value>
</array>
</property>
代理设计模式
概念
将核心功能与辅助功能(事务,日志,性能监控代码)分离,达到核心业务功能更纯粹,辅助业务功能可复用
静态代理设计模式
优点
通过代理类对象,为原始类的对象(目标类对象)添加辅助功能,更容易更换代理实现类,利于维护
代理类
代理类=实现原始类相同接口+添加辅助功能+调用原始类的业务方法
静态代理的问题
1.代理类数量过多,不利于项目的管理
2.多个代理类的辅助功能代码冗余,修改时,维护性差
动态代理设计模式
JDK动态代理实现
基于接口
//目标
final OrderService os = new OrderServiceImpl();
//额外功能
InvocationHandler handler = new InvocationHandler(){//1. 设置回调函数(额外功能代码)
@Override
public object invoke(Object proxy, Method method, object[] args)
throws Throwable {
System . out. print1n("start...");
method . invoke(os,args);
System. out . println("end...");
return null;
}
};
//2.创建动态代理类
object proxy0bj = Proxy . newProxyInstance (ClassLoader,Interfaces ,InvocationHandler) ;
final OrderService os = new OrderServiceImpl();
//额外功能
InvocationHandler handler = new InvocationHandler(){//1. 设置回调函数(额外功能代码)
@Override
public object invoke(Object proxy, Method method, object[] args)
throws Throwable {
System . out. print1n("start...");
method . invoke(os,args);
System. out . println("end...");
return null;
}
};
//2.创建动态代理类
object proxy0bj = Proxy . newProxyInstance (ClassLoader,Interfaces ,InvocationHandler) ;
CGlib动态代理实现
基于继承
final OrderService os = new OrderServiceImpl();
Enhancer cnh = new Enhancer();//1. 创建字节码曾强对象
enh. setSuperclass( os . getClass());//2.设置父类(等价于实现原始类接口)
enh. setCallback( new InvocationHandler(){//3 .设置回调函数(额外功能代码)
@Override
public object invoke(0bject proxy ,Method method, object[] args) throws Throwable{
System. out . println("start...");
object ret = method . invoke(os , args);
System. out . println("end...");
return ret ;
});
OrderService proxy = (OrderService ) enh . create();//4.创建动态代理类
proxy, create0rder();
Enhancer cnh = new Enhancer();//1. 创建字节码曾强对象
enh. setSuperclass( os . getClass());//2.设置父类(等价于实现原始类接口)
enh. setCallback( new InvocationHandler(){//3 .设置回调函数(额外功能代码)
@Override
public object invoke(0bject proxy ,Method method, object[] args) throws Throwable{
System. out . println("start...");
object ret = method . invoke(os , args);
System. out . println("end...");
return ret ;
});
OrderService proxy = (OrderService ) enh . create();//4.创建动态代理类
proxy, create0rder();
Spring+MyBatis
将数据源配置到项目中
1.配置数据源
引入jdbc.properties
#jdbc . properties
jdbc. driverClass=com. mysq1. jdbc . Driver
jdbc . url= jdbc :mysq1 :/ /localhost :3306/mydb?useUnicode=true&characterEncoding=UTF-8
j dbc . username= root
jdbc . password=123456
jdbc. driverClass=com. mysq1. jdbc . Driver
jdbc . url= jdbc :mysq1 :/ /localhost :3306/mydb?useUnicode=true&characterEncoding=UTF-8
j dbc . username= root
jdbc . password=123456
整合Spring配置文件和properties配置文件
spring-context.xml
<!--spring-context . xml-->
<?xml version="1 .0”encoding="UTF-8"?>
<beans xmlns= "http://www. springf ramework . org/schema/beans "
xmlns:context="http: / /www . spr ingf ramework . org/ schema/context"
xmlns:xsi="http:/ /www . w3.org/2001 /XMLSchema - instance"
xsi : schemaLocation='
http:/ /www. spr ingf ramework。org/ schema/beans
http:/ /www. springf ramework . org/ schema/ beans/spring-beans . xsd
http:/ /www. springframework . org/ schema/ context
http :/ /www. springf r amework . org/ schema/ context/ spring-context .xsd
<?xml version="1 .0”encoding="UTF-8"?>
<beans xmlns= "http://www. springf ramework . org/schema/beans "
xmlns:context="http: / /www . spr ingf ramework . org/ schema/context"
xmlns:xsi="http:/ /www . w3.org/2001 /XMLSchema - instance"
xsi : schemaLocation='
http:/ /www. spr ingf ramework。org/ schema/beans
http:/ /www. springf ramework . org/ schema/ beans/spring-beans . xsd
http:/ /www. springframework . org/ schema/ context
http :/ /www. springf r amework . org/ schema/ context/ spring-context .xsd
配置文件参数化
<!--配置文件参数化 (参数占位符) -->
<context :property-placeholder location= " classpath: jdbc. properties" />
<context :property-placeholder location= " classpath: jdbc. properties" />
与PooledDataSource集成
<!--与PooledDataSource集成(二选- -) -->
<bean id= " dataSource" class="org. apache。ibatis . datasource。pooled . PooledDataSource">
<property name= “driver" value=" S{driverClass}"/>
<property name="url" value="${ur1}"/>
<property name= "username" value=" $ {username}" />
<property name= ”password" value="${password}"/>
</bean>
<bean id= " dataSource" class="org. apache。ibatis . datasource。pooled . PooledDataSource">
<property name= “driver" value=" S{driverClass}"/>
<property name="url" value="${ur1}"/>
<property name= "username" value=" $ {username}" />
<property name= ”password" value="${password}"/>
</bean>
与DruidDataSource集成
<!--与DruidDataSource集成(二选- -) -->
<bean id=" dataSource" class= ”com . alibaba . druid . pool. DruidDataSource" init -method=”init" destroy-method= ”close">
<!--基本配置-->
<property name=" driverClassName”value=" S{jdbc . driverClass}"/>
<property name=" ur1" value= ”${jdbc .url}"/>
<property name= " username" value=" ${jdbc .username}"/>
<property name= " password" value=" ${jdbc . password}"/>
</bean>
</bean>
<bean id=" dataSource" class= ”com . alibaba . druid . pool. DruidDataSource" init -method=”init" destroy-method= ”close">
<!--基本配置-->
<property name=" driverClassName”value=" S{jdbc . driverClass}"/>
<property name=" ur1" value= ”${jdbc .url}"/>
<property name= " username" value=" ${jdbc .username}"/>
<property name= " password" value=" ${jdbc . password}"/>
</bean>
</bean>
Druid连接池可选参数
基本配置
<!--基本配置-->
<property name=" driverClassName" value=" ${jdbc . driverClass}"/>
<property name="url" value="${jdbc.url}"/>
<property name= " username”
value=" S{jdbc . username}"/>
<property name=" password" value=" ${jdbc。password}"/>
<property name=" driverClassName" value=" ${jdbc . driverClass}"/>
<property name="url" value="${jdbc.url}"/>
<property name= " username”
value=" S{jdbc . username}"/>
<property name=" password" value=" ${jdbc。password}"/>
配置初始化大小、最小、最大
<!-- 配置初始化大小、最小、最大-->
<property name=" initialSize" value="S{jdbc. init}" />
<property name= ”minIdle" value="S{jdbc . minIdle}"/>
<property name= "maxActive" value=" ${jdbc . maxActive}" />
<property name=" initialSize" value="S{jdbc. init}" />
<property name= ”minIdle" value="S{jdbc . minIdle}"/>
<property name= "maxActive" value=" ${jdbc . maxActive}" />
配置获取连接等待超时的时间
<!--配置获取连接等待超时的时间-->
<property name= " maxWait" value= ”60000"/>
<property name= " maxWait" value= ”60000"/>
配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
<!--配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒-->
<property name=" timeBe tweenEvictionRunsMillis" value= " 60000"/>
<property name=" timeBe tweenEvictionRunsMillis" value= " 60000"/>
配置一个连接在池中最小生存的时间,单位是毫秒
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒-->
<property name= "minEvictableIdleTimeMillis" value= ”300000" />
<property name= "minEvictableIdleTimeMillis" value= ”300000" />
Druid监控中心
web.xml
<!--web . xml-->
<servlet>
<servlet-name>DruidStatView</servlet-name>
<servlet-class>com . alibaba . druid. support。http . StatViewServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DruidStatView</ servlet-name>
<url-pattern> /druid/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>DruidStatView</servlet-name>
<servlet-class>com . alibaba . druid. support。http . StatViewServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DruidStatView</ servlet-name>
<url-pattern> /druid/*</url-pattern>
</servlet-mapping>
测试监控中心
配置Tomcat,并访问
2.整合MyBatis
导入依赖
spring-jdbc
<!-- spring-jdbc -->
<dependency>
<groupId>org. spr ingf ramework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.6. RELEASE</version>
</ dependency>
<dependency>
<groupId>org. spr ingf ramework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.6. RELEASE</version>
</ dependency>
spring+mybatis集成依赖
<!-- spr ing+mybatis集成依赖 -->
<dependency>
<groupId>org . mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>org . mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
配置SqlSessionFactory
工厂bean:生成SqlSessionFactory
<!--工厂bean:生成SqlSessionFactory -->
<bean id=" sqlSessionFactory" class="org . mybatis . spring . SqlSessionF actoryBean">
<bean id=" sqlSessionFactory" class="org . mybatis . spring . SqlSessionF actoryBean">
注入连接池
<!--注入连接池-->
<property name= "dataSource" ref=" dataSource"></property>
<property name= "dataSource" ref=" dataSource"></property>
注入dao-mapper文件信息
<!-- 注入dao-mapper文件信息 ,如果映射文件和dao接口同包且同名,则此配置可省略-->
<property name= " mapperLocations">
<list>
<value>classpath :com/qf/spring/dao/* . xml</value>
</list>
</property>
<property name= " mapperLocations">
<list>
<value>classpath :com/qf/spring/dao/* . xml</value>
</list>
</property>
为dao-mapper文件中的实体定义缺省路径
<!--为dao-mapper文件中的实体定义缺省包路径
如: <select id=" queryAll”resultType="User"> 中User类可以不定义包
<property name=" typeAliasesPackage" value= ”com. qf . entity"></property>
如: <select id=" queryAll”resultType="User"> 中User类可以不定义包
<property name=" typeAliasesPackage" value= ”com. qf . entity"></property>
配置MapperScannerConfigurer
作用
管理DAO实现类的创建,并创建DAO对象,存入工厂管理
配置
1.扫面所有DAO接口,创建DAO实现
2.将DAO实现存入工厂管理
3.DAO实现对象在工厂中的id时:“首字母小写的接口的类名”
代码
<!-- mapperScannerConfigurer -->
<bean id= ”mapperScannerConfigurer9" class=" org . mybatis . spr ing . mapper . MapperScannerConfigurer">
<!-- dao接口所在的包如果有多个包, 可以用逗号或分号分隔
<property name="basePackage" value= "com.a。dao, com. b. dao"></property>
-- >
<property name= ”basePackage" value=" com. qf . spring . dao" ></property>
<!--如果工厂中只有一-个SqlSessionFactory的bean, 此配置可省略-->
<property name= ”sq1SessionFactoryBeanName" value= ”sq1SessionFactory"></property>
< /bean>
<bean id= ”mapperScannerConfigurer9" class=" org . mybatis . spr ing . mapper . MapperScannerConfigurer">
<!-- dao接口所在的包如果有多个包, 可以用逗号或分号分隔
<property name="basePackage" value= "com.a。dao, com. b. dao"></property>
-- >
<property name= ”basePackage" value=" com. qf . spring . dao" ></property>
<!--如果工厂中只有一-个SqlSessionFactory的bean, 此配置可省略-->
<property name= ”sq1SessionFactoryBeanName" value= ”sq1SessionFactory"></property>
< /bean>
配置Service
<bean id= ”userService" class=" com . qf . spring . service .UserServiceImpl">
<!--注意ref中的值是对应DA0接口的首字母小写的接口名-->
<property name="userDA0" ref="userDA0"></property>
</bean>
<!--注意ref中的值是对应DA0接口的首字母小写的接口名-->
<property name="userDA0" ref="userDA0"></property>
</bean>
DI(Dependency Injection)依赖注入
概念
在Spring创建对象的同时,为其属性赋值,称之为依赖注入
Set注入
创建对象时,Spring工厂会通过Set方法为对象的属性赋值
Spring框架
概念
1.Spring是一个项目管理框架,同时也是一套Java EE解决方案
2.Spring是众多优秀设计模式的组合(工厂,单例,代理,适配器,包装器,观察者,模板,策略)
3.Spring并未替代现有框架产品,而是将众多框架进行有机整合,简化企业级开发,俗称"胶水框架"
访问与下载
官方网址
下载地址
架构组成
核心技术
依赖注入,事件,资源,i18n,验证,数据绑定,类型交换,SqEL,AOP
测试
模拟对象,TestContext框架,Spring MVC测试,WebTestClient
数据访问
事务,DAO支持,JDBC,ORM,封装XML
Spring MVC和Spring WebFlux Web框架
集成
远程处理,JMS,JCA,JMX,电子邮件,任务,调度,缓存
语言
Kotlin,Groovy,动态语言
环境搭建
pom.xml中引入Spring常用依赖
<dependency>
<groupId>org. spr ingframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.6. REL EASE</version>
</dependency>
<groupId>org. spr ingframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.6. REL EASE</version>
</dependency>
创建Spring配置文件
Spring工厂特性
饿汉式创建优势
饿汉式
工厂创建之后,会将Spring配置文件中的所有对象都创建完成
优势
提高程序运行效率,避免多次IO,减少对象创建事件
生命周期方法
自定义初始化方法
添加"init-methid"属性,Spring则会在创建对象之后,调用此方法
自定义销毁方法
添加"destory-method"属性,Spring则会在小慧对象之前,调用此方法
销毁
工厂的close()方法被调用之后,Spring会毁掉所有已创建的单例对象
分类
Singleton对象由Spring容器销毁,Prototype对象由JVM销毁
生命周期注解
初始化注解
@PostConstruct / /初始化
public void init(){
System . out. println("init method executed") ;
}
public void init(){
System . out. println("init method executed") ;
}
销毁注解
@PreDestroy / /销毁
public void destroy(){
System . out . println("destroy method executed" ) ;
}
public void destroy(){
System . out . println("destroy method executed" ) ;
}
生命周期阶段
单例bean
创建---->构造方法---->set方法(注入值)---->init(初始化)---->构建完成---->随工厂关闭销毁
多例bean
创建---->构造方法---->set方法(注入值)---->init(初始化)---->构建完成---->JVM垃圾回收销毁
面向切面编程
概念
AOP(Aspect Oriented Programming),即面向切面编程,利用一种称为"横切"的技术,剖开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面,所谓"切面",简单说就是那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性
AOP
开发术语
连接点
连接点是程序类中客观存在的方法,可被Spring拦截并切入内容
切入点
被Spring切入连接点
通知,增强
可以为切入点添加额外功能,分为:前置通知,后置通知,异常通知,最终通知,环绕通知等
目标对象
代理的目标对象
引介
一种特殊的增强,可在运行期为类动态添加Field和Method
织入
把通知应用到具体的类,进而创建新的代理类的过程
代理
被AOP织入通知后,产生的结果类
切面
由切点和通知组成,将横切逻辑织入切面所指定的连接点中
优点
1.通过AOP提供的编码流程,更便利的定制切面,更方便的定制了动态代理
2.进而彻底解决了辅助功能冗余的问题
3.业务类中职责单一性得到更好保障
4.辅助功能也有很好的复用性
作用
Spring的AOP编程即是通过动态代理类为原始类的方法添加辅助功能
环境搭建
引入AOP相关依赖
<dependency>
<groupId>org. springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.1.6. REL EASE</version>
</dependency>
<groupId>org. springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.1.6. REL EASE</version>
</dependency>
spring-context.xml引入AOP命名空间
<?xml version="1 .0" encoding="UTF-8"?>
<beans xmlns= "http:/ /www . springframework . org/ schema/ beans”
xmlns :context= " http:/ /www . springf ramework . org/ schema / context"
xm1ns :aop="http: //www . springf ramework . org/schema/ aop
xmlns :xsi="http:/ /www . w3. org/2001 /XMLSchema- instance”
xsi :schemaLocation="
http:/ /www. springf ramework。org/ schema/beans
http:/ /www. springf ramework . org/ schema /beans / spring-beans .xsd
http:/ /www. springf ramework . org/schema /aop
http:/ /www. springf ramework . org/ schema/aop/spring- aop. xsd
< /beans>
<beans xmlns= "http:/ /www . springframework . org/ schema/ beans”
xmlns :context= " http:/ /www . springf ramework . org/ schema / context"
xm1ns :aop="http: //www . springf ramework . org/schema/ aop
xmlns :xsi="http:/ /www . w3. org/2001 /XMLSchema- instance”
xsi :schemaLocation="
http:/ /www. springf ramework。org/ schema/beans
http:/ /www. springf ramework . org/ schema /beans / spring-beans .xsd
http:/ /www. springf ramework . org/schema /aop
http:/ /www. springf ramework . org/ schema/aop/spring- aop. xsd
< /beans>
开发流程
定义原始类
public interface UserService {
public void save() ;
}
public void save() ;
}
public class UserServiceImpl implements UserService {
public void save() {
System . out. println("save method executed...");
}
}
public void save() {
System . out. println("save method executed...");
}
}
定义通知类(添加额外功能)
public class MyAdvice implements MethodBeforeAdvice { / /实现前置通知接口
public void before(Method method, Object[ ] args, object target) throws Throwable {
System. out . println("before advice executed...");
}
}
public void before(Method method, Object[ ] args, object target) throws Throwable {
System. out . println("before advice executed...");
}
}
定义bean标签
<!--原始对象-->
<bean id="us" class=" com. qf . aaron. aop. basic .UserServiceImpl" />
<!--辅助对象-->
<bean id= "myAdvice" class=" com. qf . aaron. aop . basic . MyAdvice" />
<bean id="us" class=" com. qf . aaron. aop. basic .UserServiceImpl" />
<!--辅助对象-->
<bean id= "myAdvice" class=" com. qf . aaron. aop . basic . MyAdvice" />
定义切入点(PointCut)形成切面(Aspect)
<aop:config>
<!--切点-->
<aop :pointcut id=" myPointCut" expression=" execution(* save())" />
</aop:config>
<!--切点-->
<aop :pointcut id=" myPointCut" expression=" execution(* save())" />
</aop:config>
<aop :config>
<!--组装切面-->
<aop:advisor advice- ref=" myAdvice" pointcut-ref=" myPointCut" />
</aop :config>
<!--组装切面-->
<aop:advisor advice- ref=" myAdvice" pointcut-ref=" myPointCut" />
</aop :config>
通知类
前置通知
MethidBeforAdvice
后置通知
AfterAdvice
异常通知
ThrowsAdvice
终止通知
AfterReturningAdvice
环绕通知
MethodInterceptor
通配切入点
概念
根据表达式通配切入点
匹配参数
<!--匹配参数-->
<aop :pointcut id= " myPointCut" expression=" execution(* *(com. qf . aaron. aop . basic.User))" />
<aop :pointcut id= " myPointCut" expression=" execution(* *(com. qf . aaron. aop . basic.User))" />
匹配方法名(无参)
<!--匹配方法名(无参) -->
<aop :pointcut id= " myPointCut" expression= " execution(* save ( )) ”/>
<aop :pointcut id= " myPointCut" expression= " execution(* save ( )) ”/>
匹配方法名(任意参数)
<!--匹配方法名(任意参数) -->
<aop :pointcut id=" myPointCut" expression=" execution(* save( . . ) ) ”/>
<aop :pointcut id=" myPointCut" expression=" execution(* save( . . ) ) ”/>
匹配返回值类型
<!--匹配返回值类型-->
<aop:pointcut id= " myPointCut' expression=" execution( com . qf . aaron. aop . basic.User *(..))" />
<aop:pointcut id= " myPointCut' expression=" execution( com . qf . aaron. aop . basic.User *(..))" />
匹配类名
<!--匹配类名-->
<aop :pointcut id=" myPointCut" expression= “execution(* com. qf . aaron. aop . basic .UserServiceImp1.*(..))" />
<aop :pointcut id=" myPointCut" expression= “execution(* com. qf . aaron. aop . basic .UserServiceImp1.*(..))" />
匹配包名
<!--匹配包名-->
<aop :pointcut id= " myPointCut" expression=" execution(* com. qf .aaron. aop. basic.*.*(..))" />
<aop :pointcut id= " myPointCut" expression=" execution(* com. qf .aaron. aop. basic.*.*(..))" />
匹配包名,以及子包名
<!--匹配包名、以及子包名-->
<aop :pointcut id=“myPointCut" expression=" execution(* com. qf .aaron.aop..*.*(..))" />
<aop :pointcut id=“myPointCut" expression=" execution(* com. qf .aaron.aop..*.*(..))" />
Ioc(Inversion of Control)控制反转
优点
1.强转了依赖关系的满足方式,由之前的自己创建依赖对象,变为由工厂推送
2.解决了具有依赖关系的组件之间的耦合,使得项目形态更加稳健
项目中强耦合问题
public class UserServiceImpl implements UserService {
// !!! 强耦合了UserDA0Impl!!! ,使得UserServiceImpl变得不稳健!!
private UserDAO userDA0= new UserDA0Impl();
@Override
public User queryUser() {
return userDAO . queryUser();
}
}
// !!! 强耦合了UserDA0Impl!!! ,使得UserServiceImpl变得不稳健!!
private UserDAO userDA0= new UserDA0Impl();
@Override
public User queryUser() {
return userDAO . queryUser();
}
}
解决方案
//不引用任何一个具体的组件(实现类),在需要其他组件的位置预留存取值入口( set/get)
public class UserServiceImpl implements UserService {
// !!!不再耦合任何DAO实现!!!,消除不稳健因素!!
private UserDAO userDAO;
//为userDA0定义set/get, 允许userDA0属性接收spr ing赋值
//Getters And Setters
@Override
public User queryUser() {
return userDAO . queryUser();
}
....
}
public class UserServiceImpl implements UserService {
// !!!不再耦合任何DAO实现!!!,消除不稳健因素!!
private UserDAO userDAO;
//为userDA0定义set/get, 允许userDA0属性接收spr ing赋值
//Getters And Setters
@Override
public User queryUser() {
return userDAO . queryUser();
}
....
}
事务
配置DATASourceTransactionManger
概念
事务管理器,其中持有DataSource,可以控制事务功能
代码实现
<!-- 1.引入一个事务管理器,其中依赖DataSource,借以获得连接,进而控制事务逻辑-->
<bean id="tx" class="org. springframework. jdbc . datasource . DataSourceTransactionManager">
<property name= " dataSource" ref=" dataSource"></property>
< /bean>
<bean id="tx" class="org. springframework. jdbc . datasource . DataSourceTransactionManager">
<property name= " dataSource" ref=" dataSource"></property>
< /bean>
注意事项
DATASourceTransactionManger和SqlSessionFactoryBean要注入同一个DataSource的Bean,否则事务控制失效
配置事务通知
Advice
基于事务管理器,进一步定制,生成一个额外功能:Advice
此Advice可以切入任何需要事务的方法,通过事务管理器为方法控制事务
代码实现
<tx:advice id=" txManager" transaction-manager="tx">
<tx:attributes>
<!--<tx :method name=" insertUser" rollback- for=" Exception" isolation="DEFAULT"
propagation= "REQUIRED" read-only="false" />-->
<!--以User结尾的方法,切入此方法时,采用对应事务实行-->
<tx :method name= “*User" rollback-for=" Exception"/>
<!--以query开头的方法,切入此方法时,采用对应事务实行-->
<tx :method name= ”query*" propagation= ”SUPPORTS" />
<!--剩余所有方法-->
<tx :method name="*"/>
</tx:attributes>
</ tx :advice>
<tx:attributes>
<!--<tx :method name=" insertUser" rollback- for=" Exception" isolation="DEFAULT"
propagation= "REQUIRED" read-only="false" />-->
<!--以User结尾的方法,切入此方法时,采用对应事务实行-->
<tx :method name= “*User" rollback-for=" Exception"/>
<!--以query开头的方法,切入此方法时,采用对应事务实行-->
<tx :method name= ”query*" propagation= ”SUPPORTS" />
<!--剩余所有方法-->
<tx :method name="*"/>
</tx:attributes>
</ tx :advice>
事务属性
隔离级别
概念
default
默认值(采用数据库默认的设置)
read-uncommited
读未提交
read-commited
读提交(Oracle数据库默认的隔离级别)
repeatable-read
可重复读(MySql数据库默认的隔离级别)
serialized-read
序列化读
由低到高排序
read-uncommited<read-commited<repeatable-read<serialized-read
特性
安全性
级别越高,多事务并发时,越安全。因为共享的数据越来越少,事务间彼此干扰减少
并发性
级别越高,多事务并发时,并发越差。因为共享的数据越来越少,事务间阻塞情况增多
并发问题
概念
事务并发时的安全问题
问题
脏读
一个事务读取到另一个事务还未提交的数据。大于等于read-commited可防止
不可重复读
一个事务内多次读取一行数据的相同内容,其结果不一致。大于等于repeatable-read可防止
幻影读
一个事务内多次读取一张表中的相同内容,其结果不一致。serialized-read可防止
传播行为
SUPPORTS
不存在外部事务,则不开启新事务;存在外部事物,则合并到外部事务中
REQUIRED
不存在外部事务,则开启新事物;存在外部事物,则合并到外部事务中
读写性
true
只读,可提高查询效率
false
可读可写
事务超时
100
自定义等待时间100s
-1
由数据库制定等待事间,默认值
事务回滚
如果事务中跑出RuntimeException,则自动回滚
如果事务中抛出CheckException,不会自动回滚,而是默认提交事务
处理方案
将CheckException上抛
编织
概念
将事务管理的Advice切入需要事务的业务方法中
代码实现
<aop :config>
<aop:pointcut expression= ”execution(* com . qf . spring . service . UserServiceImpl.*(..))" id="pc"/>
<!--组织切面
<aop :advisor advice- ref=" txManager" pointcut-ref="pc" />
</aop:config>
<aop:pointcut expression= ”execution(* com . qf . spring . service . UserServiceImpl.*(..))" id="pc"/>
<!--组织切面
<aop :advisor advice- ref=" txManager" pointcut-ref="pc" />
</aop:config>
0 条评论
下一页