JAVA程式設計118——事務控制/動態代理
一、目錄結構
二、資料庫結構及測試資料
三、程式碼詳解
1、xml配置檔案:pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" >
<modelVersion>4.0.0</modelVersion>
<groupId>com.mollen</groupId>
<artifactId>exam</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
< artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
</dependency >
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<dependency>
<groupId>commons-dbutils</groupId>
<artifactId>commons-dbutils</artifactId>
<version>1.6</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<target>1.7</target>
<source>1.7</source>
</configuration>
</plugin>
</plugins>
</build>
</project>
2、資料來源配置檔案:db.properties
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.jdbcUrl=jdbc:mysql://localhost:3306/my_db2
jdbc.user=root
jdbc.password=root
3、實體類:Account.java
package com.mollen.bean;
/**
* @ClassName: Account
* @Auther: Mollen
* @CreateTime: 2018-11-06 11:53:29
* @Description:
*/
public class Account {
private int id;
private String name;
private double money;
public Account() {
}
public Account(int id, String name, double money) {
this.id = id;
this.name = name;
this.money = money;
}
@Override
public String toString() {
return "Account{" +
"id=" + id +
", name='" + name + '\'' +
", money=" + money +
'}';
}
//...getter/setter
}
4、dao層:
1、Dao介面:AccountDao.java
package com.mollen.dao;
import com.mollen.bean.Account;
/**
* @ClassName: AccountDao
* @Auther: Mollen
* @CreateTime: 2018-11-06 11:55:11
* @Description:
*/
public interface AccountDao {
/**
* 1.根據使用者名稱查詢賬戶資訊
* @return
*/
public Account findByName(String name) throws Exception;
/**
* 2.更新賬戶資訊
*/
public void upDate(String name,double money) throws Exception;
}
2、Dao實現類:AccountDaoImpl.java
package com.mollen.dao.impl;
import com.mollen.bean.Account;
import com.mollen.dao.AccountDao;
import com.mollen.utils.JdbcUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import java.sql.SQLException;
/**
* @ClassName: AccountDaoImpl
* @Auther: Mollen
* @CreateTime: 2018-11-06 11:58:35
* @Description:
*/
public class AccountDaoImpl implements AccountDao {
QueryRunner queryRunner = new QueryRunner();
public void setQueryRunner(QueryRunner queryRunner) {
this.queryRunner = queryRunner;
}
/**
* 1.根據使用者名稱查詢賬戶資訊
* @return
*/
public Account findByName(String name) throws SQLException{
return queryRunner.query(JdbcUtils.getConnection(),"SELECT * FROM account WHERE name = ?",new BeanHandler<Account>(Account.class),name);
}
/**
* 2.更新賬戶資訊
*/
public void upDate(String name,double money) throws SQLException{
queryRunner.update(JdbcUtils.getConnection(),"UPDATE account SET money = ? WHERE name = ?",money,name);
}
}
5、Service層:
1、Service層介面:AccountService.java
package com.mollen.service;
/**
* @ClassName: AccountService
* @Auther: Mollen
* @CreateTime: 2018-11-06 14:13:50
* @Description:
*/
public interface AccountService {
/**
* 轉賬業務
* @param source
* @param target
* @param money
* @throws Exception
*/
public void transfer(String source,String target,double money) throws Exception;
}
2、Service介面實現類:AccountServiceImpl.java
package com.mollen.service.impl;
import com.mollen.bean.Account;
import com.mollen.dao.AccountDao;
import com.mollen.dao.impl.AccountDaoImpl;
import com.mollen.service.AccountService;
/**
* @ClassName: AccountServiceImpl
* @Auther: Mollen
* @CreateTime: 2018-11-06 14:17:16
* @Description:
*/
public class AccountServiceImpl implements AccountService {
private AccountDao accountDao = new AccountDaoImpl();
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
public void transfer(String source, String target, double money) throws Exception {
//1.查詢轉出賬戶的賬戶餘額
Account source_account = accountDao.findByName(source);
//2.轉出賬戶的餘額減少
source_account.setMoney(source_account.getMoney()-money);
//3.修改轉出賬戶餘額
accountDao.upDate(source,source_account.getMoney());
//手動丟擲異常
//int i = 10 /0 ;
//1.查詢轉入賬戶的餘額
Account target_account = accountDao.findByName(target);
//2.轉入賬戶餘額增加
target_account.setMoney(target_account.getMoney()+money);
//3.修改轉入賬戶的餘額
accountDao.upDate(target,target_account.getMoney());
}
}
6、建立jdbc工具類:JdbcUtils.java
package com.mollen.utils;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.util.Properties;
/**
* @ClassName: JdbcUtils
* @Auther: Mollen
* @CreateTime: 2018-11-06 14:49:43
* @Description:
*
*/
public class JdbcUtils {
//1.建立執行緒標誌物件儲存物件(保證事務過程中用的是同一個連線)
private static ThreadLocal<Connection> threadLocal = new InheritableThreadLocal<>();
//3.獲取執行緒池連線物件
public static Connection getConnection(){
//獲取標誌
Connection connection = threadLocal.get();
try {
if (connection == null) {
connection = JdbcUtils.getDataSource().getConnection();
//存入標誌
threadLocal.set(connection);
}
return connection;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//4.獲取資料來源
public static DataSource getDataSource() throws IOException, PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
Properties properties = new Properties();
InputStream is = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
properties.load(is);
dataSource.setDriverClass(properties.getProperty("jdbc.driverClass"));
dataSource.setJdbcUrl(properties.getProperty("jdbc.jdbcUrl"));
dataSource.setUser(properties.getProperty("jdbc.user"));
dataSource.setPassword(properties.getProperty("jdbc.password"));
return dataSource;
}
//5.解除執行緒與連線繫結
public static void remove(){
threadLocal.remove();
}
}
7、建立事務類:TransactionManager.java
package com.mollen.utils;
import java.sql.SQLException;
/**
* @ClassName: TransactionManager
* @Auther: Mollen
* @CreateTime: 2018-11-06 14:49:58
* @Description:
*/
public class TransactionManager {
/**
* 1.開啟事務
*/
public static void startTransaction(){
try {
JdbcUtils.getConnection().setAutoCommit(false);
System.out.println("事務開啟!");
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 2.提交事務
*/
public static void commitTransaction(){
try {
JdbcUtils.getConnection().commit();
System.out.println("事務提交!");
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 3.回滾事務
*/
public static void rollbackTransaction(){
try {
JdbcUtils.getConnection().rollback();
System.out.println("事務回滾!");
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 4.關閉連線
*/
public static void close(){
try {
JdbcUtils.getConnection().close();
System.out.println("連線關閉!");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
8、建立動態代理測試類
package com.mollen.test;
import com.mollen.service.AccountService;
import com.mollen.service.impl.AccountServiceImpl;
import com.mollen.utils.TransactionManager;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.junit.Test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @ClassName: MyTest
* @Auther: Mollen
* @CreateTime: 2018-11-06 18:41:31
* @Description:
*/
public class MyTest {
AccountService accountService = new AccountServiceImpl();
/**
* 1、第一種方案:Jdk動態代理方式進行事務控制 --> 真實物件必須實現介面
*/
@Test
public void transfer1() {
/**
* ClassLoader loader, 真實物件的類載入器
* Class<?>[] interfaces, 真實物件實現的所有介面
* InvocationHandler h 代理物件的處理類
*/
AccountService accountService_proxy = (AccountService) Proxy.newProxyInstance(
accountService.getClass().getClassLoader(),
accountService.getClass().getInterfaces(),
new InvocationHandler() {
/**
* 呼叫代理物件任意方法,InvocationHandler中的invoke()都會執行
* @param proxy 代理物件
* @param method 代理物件呼叫的方法
* @param args 代理物件呼叫方法時摻入的引數
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//宣告一個事務執行結果
Object obj = null;
try {
//1.開啟事務--業務執行之前
TransactionManager.startTransaction();
//2.執行業務--執行業務操作
obj = method.invoke(accountService, args);
//3.提交事務--業務正常執行
TransactionManager.commitTransaction();
} catch (Exception e) {
e.printStackTrace();
//4.回滾事務--業務執行異常
TransactionManager.rollbackTransaction();
} finally {
//5.關閉連線
TransactionManager.close();
}
return obj;
}
});
try {
accountService_proxy.transfer("aaa", "bbb", 100);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 2、第二種方案:使用cglib動態代理技術
*/
@Test
public void transfer2() {
//1. 建立cglib的核心物件
Enhancer enhancer = new Enhancer();
//2. 設定產生的代理物件的父類
enhancer.setSuperclass(accountService.getClass());
//3. 設定呼叫代理物件的回撥函式
enhancer.setCallback(new MethodInterceptor() {
/**
*
* @param proxy 代理物件
* @param method 代理物件執行的方法
* @param args 代理物件呼叫方法時傳入的引數
* @param methodProxy 呼叫方法的代理物件 一般沒什麼用
* @return
* @throws Throwable
*/
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object obj = null;
try {
//1. 在轉賬業務執行之前 開啟事物
TransactionManager.startTransaction();
//2. 執行原有的轉賬業務
obj = method.invoke(accountService, args);
//3. 轉賬業務執行成功-- 提交事物
TransactionManager.commitTransaction();
} catch (Exception e) {
e.printStackTrace();
//4. 轉賬業務執行失敗---回滾事物
TransactionManager.rollbackTransaction();
} finally
相關推薦
JAVA程式設計118——事務控制/動態代理
一、目錄結構
二、資料庫結構及測試資料
三、程式碼詳解
1、xml配置檔案:pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.or
JAVA程式設計119——事務控制/動態代理/程式碼優化
一、優化方案:將代理類單獨抽取出來封裝成為一個代理工廠
package com.mollen.config;
import com.mollen.utils.TransactionManager;
import net.sf.cglib.proxy.Enhancer;
import n
Java框架之Spring02-AOP-動態代理-AspectJ-JdbcTemplate-事務
AOP
動態代理
代理設計模式的原理:使用一個代理將原本物件包裝起來,然後用該代理物件”取代”原始物件。任何對原始物件的呼叫都要通過代理。代理物件決定是否以及何時將方法呼叫轉到原始物件上。
代理模式的三要素:
代理主題介面
代理者
被代理者
代理模式的主要優點
代理模式在客戶端與目標物
Java實現AOP切面(動態代理)
定義 row ack tcl getc java的反射機制 div implement reat Java.lang.reflect包下,提供了實現代理機制的接口和類:
public interface InvocationHandler
InvocationHandl
java反射機制應用之動態代理
代理類 過多 size bject interface 並且 編譯期 代理 抽象 1.靜態代理類和動態代理類區別
靜態代理:要求被代理類和代理類同時實現相應的一套接口;通過代理類的對象調用重寫接口的方法時,實際上執行的是被代理類的同樣的
方法的調用。
動態代理:在程序運
Java高階特性—反射和動態代理
1).反射 通過反射的方式可以獲取class物件中的屬性、方法、建構函式等,一下是例項: 2).動態代理 使用場景:
在之前的程式碼呼叫階段,我們用action呼叫service的方法實現業務即可。 由於之前在service中實現的業務可能不能夠滿足當先客戶的要求,需要我們重
25(java中的反射和動態代理)
1 概述
反射獲取的都是class物件,以下是在不同的階段獲取物件的方式。
2 原始檔階段class物件的作用
可以利用全類名創造物件,具體程式碼為:
3 class物件獲取類中的欄位(即成員變數)
註釋:通過Class.forName()獲取到了Pe
JAVA中的JDK的動態代理
在java的動態代理機制中,有兩個重要的類或介面,一個是 InvocationHandler(Interface)、另一個則是 Proxy(Class)
當我們通過代理物件呼叫一個方法的時候,這個方法的呼叫就會被轉發為由InvocationHandler這個介面的 invoke 方法來進行呼叫。
Java基礎加強總結之動態代理(Proxy)
一、代理的概念
動態代理技術是整個java技術中最重要的一個技術,它是學習java框架的基礎,不會動態代理技術,那麼在學習Spring這些框架時是學不明白的。
動態代理技術就是用來產生一個物件的代理物件的。在開發中為什麼需要為一個物件產生代理物件呢? 舉一個現實生活中
java,簡單實現cglib動態代理。
Cglib是動態代理的一種實現方式,用來代理普通的javaBean,
/**
* 實現MethodInterceptor
* @author MyComputer
*
*/
public class CGLibProxy implements MethodInt
java程式設計思想之控制執行流程
java 使用了c的所有流程控制語句,涉及的關鍵字包括 if-else、while、do - while 、for 、 return 、break以及選擇語句switch。
1、true和false 所有條件語句都利用條件表示式的真或假來決定執行路徑
2、 if - elseif -
Java 理論與實踐: 用動態代理進行修飾
動態代理為實現許多常見設計模式(包括 Facade、Bridge、Interceptor、Decorator、Proxy(包括遠端和虛擬代理)和 Adapter 模式)提供了替代的動態機制。雖然這些模式不使用動態代理,只用普通的類就能夠實現,但是在許多情況下,動態代理方式更方便、更緊湊,可以清除許多手寫或
【八】Java設計模式GOF23之動態代理(原生JDK和CGLIB)
一、使用JDK原生動態代理
基於Java反射機制。
Java動態代理是基於介面的,如果物件沒有實現介面則選擇用CGLIB方式實現動態代理。
實現步驟:
1.首先實現一個InvocationHandler,方法呼叫會被轉發到該類的invoke()方法。
2.然後在需要
Java程式設計拾遺『控制流程』
與任何程式設計語言一樣,Java使用條件語句和迴圈結構確定控制流流程。
1. 條件語句
條件語句就是使用if進行條件判斷,及邏輯處理,主要包含以下幾種形式。
1.1 if
單if條件語句格式如下:
if (condition) {
statement;
}
如果
java 系列(一) 動態代理(下)
前兩章想必大家都知道動態代理是怎麼回事,本小節的內容是動態代理的實踐操作了。在Android專案中如何實現按鈕的防雙擊(防抖動)。
這個在Android上又叫Hook技術
1.前言
對於一些特定需求使用也是非常無可奈何的,比如And
Java設計模式Proxy之動態代理
Java動態代理主要涉及到兩個類:
InvocationHandler:該介面中僅定義了一個Object : invoke(Object proxy, Method method, Object[] args);引數proxy指代理類,method表示被代理的方法,args
Java程式設計思想_控制執行流程
return:指定一個方法返回什麼值(假設它沒void返回值);導致當前方法退出,並返回那個值。 break和continue:break用於強行退出迴圈,不執行迴圈中剩餘的語句; contin
java類載入器和動態代理
import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.Collection;
public class ProxyTest {
public static void main(String[] args) throw
java如何檢視jvm中動態代理class類內容
在看dubbo原始碼時,發現dubbo呼叫過程設計到了很多動態代理類技術,但是這些動態代理類都是執行在記憶體中的,沒有生成clas
java開發必學知識:動態代理
目錄
1. 引言
2. 代理模式及靜態代理
2.1 代理模式說明
2.2 靜態代理
2.3 靜態代理侷限性
3. 動態代理
3.1 JAVA反