发布时间:2024-08-30 11:01
集成 整合。
优势:
解耦合
侵入小
轻量级
将控制权(创建对象)从调用方转义到Spring容器。
以前对象的创建是由我们开发人员自己维护,包括依赖关系也是自己注入。使用了spring之后,对象的创建以及依赖关系可以由spring完成创建以及注入,反转控制就是反转了对象的创建方式,从我们自己创建反转给了程序创建(spring)
spring这个容器中,替你管理着一系列的类,前提是你需要将这些类交给spring容器进行管理,然后在你需要的时候,不是自己去定义,而是直接向spring容器索取,当spring容器知道你的需求之后,就会去它所管理的组件中进行查找,然后直接给你所需要的组件.
// 1. 创建 一个 Spring 容器(Map), 装SpringBean
// 2. 根据配置文件application.xml 创建了两个spring bean ,一个叫helloService 一个叫helloController
// 3. 根据配置文件application.xml 将helloService注入到helloController
// 4. 存入spring容器中
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
// 从容器中获取对应的bean并且进行类型转换后返回
HelloController helloController = applicationContext.getBean("helloController", HelloController.class);
<!--创建对象: 对象取个ID;对象的类路径是什么-->
<bean name="helloService" class="com.woniuxy.cq.service.impl.HelloServiceImpl"/>
<!--创建对象: 对象取个ID;对象的类路径是什么-->
<bean id="helloController" class="com.woniuxy.cq.controller.HelloController">
<!--对属性进入注入-->
<property name="helloService" ref="helloService"/>
</bean>
(1) BeanFactory bean工厂 用于创建bean
containsBean(String) : 是否包含这个bean
getAliases
getBean 获取bean
getBean(String name, Object… args) 根据名字及构造器参数来定位一个bean
getType 得到bean的类型
isPrototype 作用域,是否是原型
isSingleton 是否是单例
isTypeMatch
isTypeMatch
FACTORY_BEAN_PREFIX
(2) ApplicationContext 应用上下文
继承了以下接口,比Beanfactory提供更多的能力,包括对国际化的支持,对事件发布的能力,对资源加载的能力,获取环境的能力
MessageSource 对国际化支持
EnvironmentCapable 获取到环境
ApplicationEventPublisher 应用程序事件发布器
ResourcePatternResolver 资源加载器
API:
getId
getApplicationName 应用名字
getDisplayName
getStartupDate 启动时间
getParent 得到父容器
getAutowireCapableBeanFactory
实现类
(1) Property
ref 引用类型: 引用已有的bean
<bean id="HelloService" class="com.woniu.cq.service.impl.HelloServiceImpl">bean>
<property name="HelloService" ref="HelloService"/>
bean 引用类型: 临时新建一个bean
value 基本类型 string
list / set 集合
ref
value
bean
<property name="names" >
<list>
<value> mcf value>
<value> xixi value>
<value> anqila value>
list>
property>
map
<property name="student" >
<map>
<entry key="学生一号" value="吃饱了">entry>
<entry key="学生二号" value="没吃饱">entry>
<entry key="学生三号" value="没有吃">entry>
map>
property>
(参考链接:https://blog.csdn.net/qq_35981996/article/details/89314216)
(1)Setter 注入:需生产set方法
例:比如主板类中(Mainboard)含有Cpu对象(Cpu)和Ram(Ram)对象:先生成此两个对象的set方法,分别注入:
public interface Mainboard extends PCComponent{
private Cpu cpu;
private Ram ram;
public void setCpu(Cpu cpu);
public void setRam(Ram ram);
随后编写Spring的配置文件applicationContext.xml。中的name为类的一个别名,而class为类的完整名称。(ps:name的值需要与在set方法中中名字一直,例如setAaa,那么name就要是aaa)
<bean id="mainboard" class="com.spring.service.pc.Ipml.InterBoard">
<!-- 值类型用value注入 引用类型用ref注入 -->
<property name="grade" value="60"></property>
<property name="cpu">
<bean class="com.spring.service.pc.Ipml.InterCpu"></bean>
</property>
<property name="ram">
<bean class="com.spring.service.pc.Ipml.KingstoneRam"></bean>
</property>
</bean>
(2)构造器注入:(需生产带参数的构造方法)
使用方法:
第一,在类中,不用为属性设置setter方法,但是需要生成该类带参的构造方法。
第二,在配置文件中配置该类的bean,并配置构造器,在配置构造器中用到了节点,该节点有四个属性:
· index是索引,指定注入的属性,从0开始;
· type是指该属性所对应的类型;
· ref 是指引用的依赖对象;
· value 当注入的不是依赖对象,而是基本数据类型时,就用value;
例如:
① 索引注入:
public class car implements Serializable {
private String name;
private String color;
private double price;
public car(String name, String color, double price) {
this.name = name;
this.color = color;
this.price = price;
}
在配置文件中,不再用标签,而是用标签代替,其中索引序号不能乱:
<constructor-arg index="0" value="B驰">constructor-arg>
<constructor-arg index="1" value="红色">constructor-arg>
<constructor-arg index="2" value="66">constructor-arg>
② 类型注入,其中类型顺序不能乱
<constructor-arg type="java.lang.String" value="奥迪" >constructor-arg>
<constructor-arg type="java.lang.Double" value="500000">constructor-arg>
<constructor-arg type="java.lang.String" value="黑色">constructor-arg>
注意:属性中含有List,Array,Map类型时:了解如下写法:
<constructor-arg index="3" >
<list>
<value>张三value>
<value>李四value>
<value>王五value>
list>
<map>
<entry key="id" value="1">entry>
map>
(1) 构造器创建
(2) 静态工厂方法
① 提供一个类,此类中包含一个静态方法,用于创建对象
public class teacherFactory {
public static teacher getInstance(){
return new teacher();
}
}
② 配置的是工厂方法所在的类(teacherFactory)以及静态工厂方法(getInstance),但是返回的是目标类型(teacher)
<bean name="tf" class="com.woniu.cq.Factory.teacherFactory" factory-method="getInstance">bean>
(3) 实例工厂
单独声明一个工厂bean;在目标bean上指定工厂bean以及工厂方法及参数;创建出对象类型是目标类型
<bean name="computer" class="com.woniu.cq.Factory.computerFactory">bean>
<bean name="com" factory-bean="computer" class="com.woniu.cq.Factory.computerFactory" factory-method="getcomputer">
<constructor-arg index="0" value="100"/>
<constructor-arg index="1" value="华为"/>
bean>
(4) 使用FactoryBean创建对象 (实现FactoryBean接口)
public class pigFactory implements FactoryBean {
@Override
public pig getObject() throws Exception {
pig p = new pig();
p.setColor("花猪");
p.setType("中华猪");
return p;
}
<bean name="pig" class="com.woniu.cq.Factory.pigFactory">bean>
(1) 初始化 :有一些 bean需要在初始化做一些操作
(2) 销毁:在销毁之前做一些操作
(3) 配置
① 实现接口 InitializingBean, DisposableBean
②Xml
//实现接口
public class connection implements InitializingBean, DisposableBean {
//自己定义的方法
public void init(){
System.out.println("初始化10个连接池");
}
//自己定义的方法
public void disposable(){
System.out.println("关闭10个连接池");
}
//实现的初始化方法
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("++++++++++++++++++++初始化10个连接池");
}
//实现的关闭方法
@Override
public void destroy() throws Exception {
System.out.println("___________________关闭10个连接池");
}
}
(1)XML配置
优势:
① 依赖关系清楚
② 无须改动代码
劣势:
①配置繁琐
(2)XML + 注解混合方式
优势:
① 减少大量配置
劣势:
①对代码又一定的侵入
如何使用XML+注解配置
① :在XML的Beans中配置:
<context:component-scan base-package="com.woniu.cq">context:component-scan>
②:在类、或者变量上添加注解
//在类上添加注解
@Component
public class HelloController {
//在变量上添加注解
@Autowired
private HelloService helloService ;
XML 配置的相关注解
PS:前四种注解功能一致,只是Spring单独把他列出来了,作为一个分类。
@Value(“10”) => SpEL
详情参看:https://www.jianshu.com/p/e0b50053b5d3
@Resource ≈ @Autowired (Resource 是java官方注解)
NoUniqueBeanDefinitionException()
bean的名字规则:首字母小写
默认不是按照名字装配(byName),按照类型装配(byType)
@Resource
@Configuration 把一个类标记为配置类,相当于配置文件
@ComponentScan 组件扫描
@Bean
依赖注入的两种方式:
① 直接调用:并不是调用方法,而是向spring容器请求一个bean,根据作用域决定是否是同一个
@Bean
public HelloDAO helloDAO(){
return new HelloDAOImpl();
}
@Bean
public HelloService helloService(){
// System.out.println(helloDAO);
HelloServiceImpl helloService = new HelloServiceImpl();
HelloDAO helloDAO1 = helloDAO();//向spring容器请求一个helloDAO的bean
HelloDAO helloDAO2 = helloDAO();
System.out.println(helloDAO1);
System.out.println(helloDAO2);
helloService.setHelloDAO(helloDAO1);
return helloService;
}
②方法参数
@Bean
public HelloService helloService(HelloDAO helloDAO){
HelloServiceImpl helloService = new HelloServiceImpl();
helloService.setHelloDAO(helloDAO);
return helloService;
}
@Component 组件
@Controller 控制器
@Service 服务
@Repository 数据库访问服务DAO —> 加在类上,声明它是一个spring管理的bean,为创建一个对象
@Autowired spring提供, 默认byType
@Resource java标准注解,name type —> 注入依赖
@Value 注入值(spel表达式)
@Qualifier
@Primary —> 存在多个同类型的bean,区分
@Configuration : 声明这个类是一个配置类
@Bean : 加在方法上,配置一个spring的bean,bean名字是方法名,返回值是bean的内容,一般添加到外部的代码上
@Scope : 设置spring的bean的作用域(initMethod destoyMethod)
@ComponentScan : 组件扫描 (可以与@Bean混合使用)
@Imort : 导入另一个配置类
@ImportResource —> 基于java配置
@EnableAspectJAutoProxy 启动Aop(在配置类上加入注解)
@PointCut
@After
@Before
@Around —> AOP
典型应用于
oop :面向对象编程 object oriented programming
纵向调用链路
controller
-> service
-> dao
aop :面向切面编程 aspect oriented programming
AOP技术恰恰相反,它利用一种称为"横切"的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其命名为"Aspect",即切面。
① 添加依赖
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<aspectj.version>1.8.9</aspectj.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--会将其他包传递依赖进来-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<!--aspectj-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>${aspectj.version}</version>
</dependency>
</dependencies>
② 启动aop 在配置类上加入注解 @EnableAspectJAutoProxy
@Configuration//把一个类标记为配置类,相当于配置文件
@ComponentScan("com.woniu.cq")//扫描组件
@EnableAspectJAutoProxy//开启切面的自动代理功能
public class AopConf {
}
③ 编写切面(切入点,通知)
@Component
@Aspect //标识这是一个切面
public class foodAspect {
//切面点
@Pointcut("execution(* com.woniu.cq.service.*.*(..))")
//第一个* 返回值
//第二个* 所有类
//第三个* 所有方法
// (..)所有参数
public void allService(){
}
//通知
@Before("allService()") //前置通知
public void doBefore(JoinPoint joinPoint){
//方法签名
Signature methodName = joinPoint.getSignature();
//参数
Object[] args = joinPoint.getArgs();
//目标对象
String name = joinPoint.getTarget().getClass().getName();
System.out.println("访问"+name+"----"+methodName);
}
}
@Around("allService()")//环绕通知
public void doAround(ProceedingJoinPoint proceedingJoinPoint){
//前面
long before = System.currentTimeMillis();
//执行
try {
//调用连接点所在的方法
Object[] args = proceedingJoinPoint.getArgs();
proceedingJoinPoint.proceed(args);
} catch (Throwable throwable) {
throwable.printStackTrace();
}
long after = System.currentTimeMillis();
//后面
Signature signature = proceedingJoinPoint.getSignature();
System.out.println(signature.getName()+"执行耗时"+(after-before)+"毫秒");
}
@Before
前置通知(Before advice)在某连接点(JoinPoint)——核心代码(类或者方法)之前执行的通知,但这个通知不能阻止连接点前的执行。
为什么不能阻止线程进入核心代码?
因为@Before注解的方法入参不能传ProceedingJoinPoint,而只能传入JoinPoint。要知道从aop走到核心代码就是通过调用ProceedingJionPoint的proceed()方法。而JoinPoint没有这个方法。
这里牵扯区别这两个类:Proceedingjoinpoint 继承了 JoinPoint 。是在JoinPoint的基础上暴露出 proceed 这个方法。proceed很重要,这个是aop代理链执行的方法。暴露出这个方法,就能支持 aop:around 这种切面(而其他的几种切面只需要用到JoinPoint,这跟切面类型有关), 能决定是否走代理链还是走自己拦截的其他逻辑。建议看一下 JdkDynamicAopProxy的invoke方法,了解一下代理链的执行原理。这样你就能明白 proceed方法的重要性。
@After
后通知(After advice)当某连接点退出的时候执行的通知(不论是正常返回还是异常退出)。
@AfterReturning
返回后通知(After return advice) **在某连接点正常完成后执行的通知,不包括抛出异常的情况。
@Around
环绕通知(Around advice)包围一个连接点的通知,类似Web中Servlet规范中的Filter的doFilter方法。可以在方法的调用前后完成自定义的行为,也可以选择不执行。这时aop的最重要的,最常用的注解。用这个注解的方法入参传的是ProceedingJionPoint pjp,可以决定当前线程能否进入核心方法中——通过调用pjp.proceed();
抛出异常后通知(After throwing advice) : 在方法抛出异常退出时执行的通知。
(1)代理模式
目标类和代理类 实现了同一个接口
表示有共性,可以互换
共同的方法
proxy持有target的引用
调用target的方法来实现一些内容
(2)动态代理
(3)动态代理的两种实现方式
① jdk动态代理 通过接口实现动态代理
//JDK 使用接口的方式实现动态代理
public class DynamicProxy {
//目标对象
private Object target;
public Object getProxy(Object target){
this.target=target;
//target.getClass().getClassLoader() , target.getClass().getInterfaces() 这两个是在动态创建代理
return Proxy.newProxyInstance(target.getClass().getClassLoader(),//获取目标对象的类加载器
target.getClass().getInterfaces(),//获取目标对象的接口
//这个是在执行方法
//方法拦截器invocationHandler 提供需要加入的功能
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开始执行方法---"+method.getName());
Object result = method.invoke(target, args);//执行方法
System.out.println("执行完方法了");
return result;
}
}
);
}
}
在重写 InvocationHandler()中的invoke方法时 ,各个参数的含义
public Object invoke(Object proxy, Method method, Object[] args)
proxy :代理的实例
method :需要被执行的方法
args :参数
//JDK动态代理测试
public class ProxyTest {
public static void main(String[] args) {
//Buy为一个接口 Tuhao是实现Buy这个接口的一个类 重写了Buy这个接口的buy方法
Buy tt = (Buy) new DynamicProxy().getProxy(new Tuhao());
//这个时候输出的Class 类型已经不是Buy了,而是$Proxy0,是动态代理返回的代理类型
System.out.println(tt.getClass().getSimpleName());
//使用代理类型去执行buy方法,会自动在方法前后加上你在动态代理invoke 中加入的内容
tt.buy();
}
}
//JDK动态代理测试最后输出的结果为:
$Proxy0 //输出tt的classname
开始执行方法---buy //执行 invoke()方法中,目标方法前的内容
为所欲为的买买买!!!!!!!! //执行目标方法 buy()
执行完方法了 //执行 invoke()方法中,目标方法后的内容
②cglib动态代理 支持通过继承实现动态代理
//cglib 继承实现动态代理
public class cglib {
public Object getProxy(Object target){
//增强器
Enhancer enhancer = new Enhancer();
//生成父类
enhancer.setSuperclass(target.getClass());
//添加方法拦截机
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("执行目标方法前做的事情");
Object result = method.invoke(target, args);
System.out.println("执行目标方法后做的事情");
return result;
}
});
//返回创建好的proxy
return enhancer.create();
}
}
注意点
//Cglib动态代理测试
public class ProxyTest {
public static void main(String[] args) {
tuhao cg =(tuhao) new cglib().getProxy(new tuhao());
cg.buy();
}
}
//Cglib动态代理测试最后输出的结果为:
执行目标方法前做的事情
为所欲为的买买买!!!!!!!!
执行目标方法后做的事情
PS:输出这个结果的原因可以参考JDK动态代理
(1) 配置依赖(在pro.xml文件中进行配置)
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-jdbcartifactId>
<version>4.3.4.RELEASEversion>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.48version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.1.22version>
dependency>
(2)属性文件配置(一般在resources目录下进行配置,配置文件类型为 properties)
jdbc.url=jdbc:mysql://localhost/user?useUnicode=true&characterEncoding=utf-8
jdbc.driver=com.mysql.jdbc.Driver
jdbc.user=root
jdbc.passworld=123456
(3)配置类
@Configuration//把一个类标记为配置类,相当于xml配置文件
@ComponentScan("com.woniu.cq")//组件扫描
@PropertySource("jdbc.properties")//将属性文件配置引入
public class JdbcConf {
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.user}")
private String user;
@Value("${jdbc.passworld}")
private String passworld;
//配置数据源
@Bean
public DataSource druidDataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setUsername(user);
druidDataSource.setPassword(passworld);
druidDataSource.setUrl(url);
druidDataSource.setDriverClassName(driver);
return druidDataSource;
}
//获取Jdbc模板对象
@Bean
public JdbcTemplate jdbcTemplate(){
JdbcTemplate jdbcTemplate = new JdbcTemplate(druidDataSource());
return jdbcTemplate;
}
}
(4)Jdbc的使用
@Repository
public class UserDAOImpl implements UserDAO {
@Autowired
private JdbcTemplate jdbcTemplate;
//向user表中插入一条数据
@Override
public void insert(int userId, String username) {
jdbcTemplate.update("insert into user(username) values(?)",username);
}
}
//另一种查询方法 查询所有商品
@Override
public List<Product> serch() {
String sql = "select * from product";
//只需要传入sql语句,泛型Product,以及Product.class即可进行数据库查询,返回为集合
List<Product> products = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Product>(Product.class));
return products;
}
更多 Aop使用JdbcTemplate的方式:
测试
也可以参考链接:https://blog.csdn.net/qq_38977097/article/details/81564680
(1)事务的四大基本特性
事物的概述
⑴ 原子性(Atomicity)
原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。
⑵ 一致性(Consistency)
一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。
拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。
⑶ 隔离性(Isolation)
隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。
即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。
关于事务的隔离性数据库提供了多种隔离级别,稍后会介绍到。
⑷ 持久性(Durability)
持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
例如我们在使用JDBC操作数据库时,在提交事务方法后,提示用户事务操作完成,当我们程序执行完成直到看到提示后,就可以认定事务以及正确提交,即使这时候数据库出现了问题,也必须要将我们的事务完全执行完成,否则就会造成我们看到提示事务处理完毕,但是数据库因为故障而没有执行事务的重大错误。
关于理解事务的隔离级别,具体详情可参考:
https://blog.csdn.net/itcats_cn/article/details/81487466
事务传播行为类型 | 说明 |
---|---|
*** PROPAGATION_REQUIRED** | 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。 |
PROPAGATION_SUPPORTS | 支持当前事务,如果当前没有事务,就以非事务方式执行。 |
PROPAGATION_MANDATORY | 必须存在一个事务,使用当前的事务,如果当前没有事务,就抛出异常。 |
*PROPAGATION_REQUIRES_NEW | 新建事务,如果当前存在事务,把当前事务挂起。 两个物理事务实现 |
PROPAGATION_NOT_SUPPORTED | 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 |
PROPAGATION_NEVER | 以非事务方式执行,如果当前存在事务,则抛出异常。 |
PROPAGATION_NESTED | 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。 保存点实现,部分回滚 |
(2)事务的开启和结束
dml 数据操纵语言 insert delete update select => 一批同时成功同时失败的DML
ddl 数据定义语言 create drop alter truncate
事务开启
事务结束
commit / rollback;
链接断开
遇到ddl或者dcl ,事务会自动提交(比如说你去执行insert,delect,update,中间突然来个create table,会把前面的事务进行提交)
(3)Spring事务抽象:
PlatformTransactionManager 平台事务管理器 (这是一个标准)
PlatformTransactionManager 的API
平台事务管理器的实现:
spring封装了事务管理的代码(打开,提交,回滚事务)
事务操作对象,因为在不同平台,操作事务的代码各不相同.spring提供了一个接口
————— PlatformTransactionManager 接口
————— 在不同平台,实现不同的接口即可
————— 注意:在spring中玩事务管理.最为核心的对象就是TransactionManager对象
TransactionDefinition 事务定义(事务的属性)
TransactionStatus(事务状态)
(1)基本配置:开启事务支持 @EnableTransactionManagement
@Configuration//把一个类标记为配置类,相当于xml配置文件
@ComponentScan("com.woniu.cq")//组件扫描
@PropertySource("jdbc.properties")//将属性文件配置引入
@EnableTransactionManagement开始事务支持
public class JdbcConf {
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.user}")
private String user;
@Value("${jdbc.passworld}")
private String passworld;
//配置数据源
@Bean
public DataSource druidDataSource(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setUsername(user);
druidDataSource.setPassword(passworld);
druidDataSource.setUrl(url);
druidDataSource.setDriverClassName(driver);
return druidDataSource;
}
//事务管理
@Bean
public PlatformTransactionManager transactionManager(){
return new DataSourceTransactionManager(druidDataSource());
}
//获取Jdbc模板对象
@Bean
public JdbcTemplate jdbcTemplate(){
JdbcTemplate jdbcTemplate = new JdbcTemplate(druidDataSource());
return jdbcTemplate;
}
//jdbc.properties 配置解析 【jdbc.properties内容可参看 二.5.(2)】
@Bean
public static PropertySourcesPlaceholderConfigurer placeholderConfigurer(){
return new PropertySourcesPlaceholderConfigurer();
}
/**
* 事务模板,执行事务内的操作(在使用编程时事务管理的时候会用到)
* @return
*/
@Bean
public TransactionTemplate txTenplate(){
return new TransactionTemplate(transactionManager());
}
}
(2)使用事务管理
//模拟转账
@Transactional
public void transfer(){
//事务要做的事情:
//执行转入钱的方法
xxxxx
//执行转出钱的方法
xxxxx
}
实现的方式为Aop
transactionManager.getTransaction();
try{
proceedingJoinPoint().proceed();
transactionManager.commit()
}catch(Exception e){
transactionManager.rollback();
}
使用代码如下:
//以下单为例
@Service
public class OrderServiceImpl implements OderService {
@Autowired
private TransactionTemplate txTemplate;
@Override
public void order(){
//开启事务管理
txTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
//事务要做的事情:
//执行查询库存以及查询余额的方法
xxxxx
//执行增加订单的方法
xxxxx
//标记事务为回滚
transactionStatus.setRollbackOnly();
}
});
}
}
//模拟转账
@Transactional
public void transfer(){
//事务要做的事情:
//执行转入钱的方法
xxxxx
//执行转出钱的方法
xxxxx
}
实现的方式为Aop
transactionManager.getTransaction();
try{
proceedingJoinPoint().proceed();
transactionManager.commit()
}catch(Exception e){
transactionManager.rollback();
}
使用代码如下:
//以下单为例
@Service
public class OrderServiceImpl implements OderService {
@Autowired
private TransactionTemplate txTemplate;
@Override
public void order(){
//开启事务管理
txTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
//事务要做的事情:
//执行查询库存以及查询余额的方法
xxxxx
//执行增加订单的方法
xxxxx
//标记事务为回滚
transactionStatus.setRollbackOnly();
}
});
}
}