題目:使用動態代理編寫一個系統實現事務,其中,代理在被代理的調用成功時(不拋出任何異常)提執行提交,而在其執行失敗時執行回滾。你的提交和回滾都針對一個外部文本文件,該文件不在Java異常的控制範圍之內。你必須注意操作的原子性。
package test;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/*
* 使用Java動態代理實現事務,以向文件中寫入內容爲例
* */
public class FileWriter1Test {
static File file = new File("D:\\test12.txt"); //寫入內容的目標文件
static String s = "Hello World! 你好";
public static void customer(FileWriter1 fileWriter1) {
try {
fileWriter1.writer(file,s); //向file中寫入s
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
if (!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
FileWriter1 proxy = (FileWriter1) Proxy.newProxyInstance(FileWriter1.class.getClassLoader(),
new Class[]{ FileWriter1.class },
new FileWriter1Handler(new FileWriter1Impl())); //使用Proxy的靜態方法newProxyInstance創建代理對象,第一個參數爲ClassLoader,第二個參數爲代理所需要實現的接口,第三個參數爲調用處理器對象
customer(proxy); //使用代理
//customer(new FileWriter1Impl()); //不使用代理
}
}
/*
* 接口
* */
interface FileWriter1 {
public abstract void writer(File file, String str) throws IOException;
}
/*
* FileWriter1接口的實現類,同時也是被代理的類
* */
class FileWriter1Impl implements FileWriter1 {
@Override
/*
* 向file文件中寫入str
* */
public void writer(File file, String str) throws IOException {
FileWriter fw = new FileWriter(file);
fw.write(str);
fw.close();
//int i = 1/0; //模擬寫入過程中出現錯誤
}
}
/*
* 調用處理器
* */
class FileWriter1Handler implements InvocationHandler {
private Object proxied; //被代理的對象
public FileWriter1Handler (Object proxied) {
this.proxied = proxied;
}
@Override
/*
* 所有對代理的方法的調用都會在invoke方法中被集中處理
* proxy是代理對象,method對象就是被調用的方法,args是參數數組
* 在此方法中我們可以增加被代理的類的方法所不具有的功能,例如本例中增加的就是備份和回滾操作
* */
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
File file = (File)args[0]; //添加數據的目標文件
File copyFile = new File("D:\\tem" + file.getName()); //目標文件的備份文件
if (!copyFile.exists()) {
copyFile.createNewFile();
}
copyFile(file, copyFile); //備份文件
try {
Object invoke = method.invoke(proxied, args); //反射,調用被代類的對應方法
} catch (Exception e) {
copyFile(copyFile,file); //發生異常,回滾事務,將備份文件的內容再次恢復到原文件
} finally {
copyFile.delete(); //刪除備份文件
}
return null;
}
/*
* 將原文件file備份到新的文件copyFile
* */
private File copyFile(File file,File copyFile) throws IOException{
FileReader fr = new FileReader(file);
FileWriter fw = new FileWriter(copyFile);
char[] ch = new char[10];
int n = 0;
while ((n = fr.read(ch)) != -1) {
fw.write(ch,0,n);
}
fr.close();
fw.close();
return copyFile;
}
}
我的這個實現能夠滿足被代理調用成功時提交,被代理調用失敗時回滾。但是那如果我在備份文件或者回滾時發生了異常又該怎麼辦呢?如果有人有更好的解決辦法還請不吝賜教。謝謝!!!