package edu.lnu.factory;
import edu.lnu.annotation.Tran;
import edu.lnu.dao.Dao;
import edu.lnu.service.Service;
import edu.lnu.util.TransactionManager;
import java.io.FileReader;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Properties;
/**基本工厂类
* Created by Meiling on 2016/6/25.
*/
public class BasicFactory {
private static BasicFactory factory = new BasicFactory();
private static Properties properties = null;
static {
try {
properties = new Properties();
properties.load(new FileReader(BasicFactory.class.getClassLoader().getResource("config.properties").getPath()));
} catch (Exception e) {
e.printStackTrace();
}
}
private BasicFactory() {
}
public static BasicFactory getFactory() {
return factory;
}
public <T extends Dao> T getDao(Class<T> clazz) {
try {
String infname = clazz.getSimpleName();
String imoleName = properties.getProperty(infname);
return (T) Class.forName(imoleName).newInstance();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException();
}
}
public <T extends Service> T getService(Class<T> clazz) {
try {
String infname = clazz.getSimpleName();
String imoleName = properties.getProperty(infname);
final T service = (T) Class.forName(imoleName).newInstance();
T proxyService = (T) Proxy.newProxyInstance(service.getClass().getClassLoader(), service.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if(method.isAnnotationPresent(Tran.class)){
try {
TransactionManager.startTran();
Object obj = method.invoke(service, args);
TransactionManager.commit();
return obj;
} catch (InvocationTargetException e) {
TransactionManager.rollBack();
throw new RuntimeException(e.getTargetException());
} catch (Exception e) {
TransactionManager.rollBack();
e.printStackTrace();
throw new RuntimeException(e);
} finally {
TransactionManager.release();
}
}else{
return method.invoke(service, args);
}
}
});
return proxyService;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException();
}
}
}
package edu.lnu.util;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.apache.commons.dbutils.DbUtils;
import javax.sql.DataSource;
import javax.xml.transform.Source;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.SQLException;
/**事务管理类
* Created by Meiling on 2016/7/8.
*/
public class TransactionManager {
private static DataSource source = new ComboPooledDataSource();
private TransactionManager() {
}
private static ThreadLocal<Connection> conn_ThreadLocal = new ThreadLocal<Connection>() {
};
private static ThreadLocal<Connection> realConn_ThreadLocal = new ThreadLocal<Connection>();
/**
* 保存每个线程是否开启过事务
*/
private static ThreadLocal<Boolean> flag_ThreadLocal = new ThreadLocal<Boolean>() {
@Override
protected Boolean initialValue() {
return false;
}
};
public static void startTran() throws SQLException {
flag_ThreadLocal.set(true);
final Connection conn = source.getConnection();
conn.setAutoCommit(false);
realConn_ThreadLocal.set(conn);
Connection proxConn = (Connection) Proxy.newProxyInstance(conn.getClass().getClassLoader(), conn.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("close".equals(method.getName())) {
return null;
} else {
return method.invoke(conn, args);
}
}
});
conn_ThreadLocal.set(proxConn);
}
public static void commit() {
DbUtils.commitAndCloseQuietly(conn_ThreadLocal.get());
}
public static void rollBack() {
DbUtils.rollbackAndCloseQuietly(conn_ThreadLocal.get());
}
/**
* 如果没有开启事务拿到的是普通的数据源
* 如果开启过事务 则返回一个改造过getConnection方法的数据源,这个方法改造后都返回同一个开启过事务的connection
*
* @return
*/
public static DataSource getSource() throws SQLException {
if (flag_ThreadLocal.get()) {
DataSource proxysource = (DataSource) Proxy.newProxyInstance(source.getClass().getClassLoader(), source.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("getConnection".equals(method.getName())) {
return conn_ThreadLocal.get();
} else {
return method.invoke(source, args);
}
}
});
return proxysource;
} else {
return source;
}
}
public static void release() {
try {
realConn_ThreadLocal.get().close();
} catch (SQLException e) {
e.printStackTrace();
}
realConn_ThreadLocal.remove();
conn_ThreadLocal.remove();
flag_ThreadLocal.remove();
}
}