gu.sql2java.ListenerContainerLocal Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sql2java-manager Show documentation
Show all versions of sql2java-manager Show documentation
sql2java manager class package for accessing database
package gu.sql2java;
import java.util.LinkedList;
import com.google.common.collect.ImmutableList;
import gu.sql2java.exception.RuntimeDaoException;
import static com.google.common.base.Preconditions.*;
import static gu.sql2java.SimpleLog.*;
/**
* container for multiple listener management
* @author guyadong
*/
class ListenerContainerLocal extends ListenerContainer {
static final TransactionListenerImpl TRANSACTION_LISTENER = new TransactionListenerImpl();
public ListenerContainerLocal(FireType fireType) {
super(BaseTableManager.isDebug(), fireType);
}
@Override
public void afterInsert(final B bean)throws RuntimeDaoException{
if(isLocalReqFirer()){
synchronized (listeners) {
for(final TableListener listener:listeners){
TRANSACTION_LISTENER.runCommitTask(new Runnable() {
@Override
public void run() {
try{
listener.afterInsert(bean);
}catch(Exception e){
log("afterInsert listener %s error:%s",listener.getClass().getName(),e.getMessage());
if(trace){
log(e);
}
}
}
});
}
}
}else {
super.afterInsert(bean);
}
}
@Override
public void afterUpdate(final B bean)throws RuntimeDaoException{
if(isLocalReqFirer()){
synchronized (listeners) {
for(final TableListener listener:listeners){
TRANSACTION_LISTENER.runCommitTask(new Runnable() {
@Override
public void run() {
try{
listener.afterUpdate(bean);
}catch(Exception e){
log("afterUpdate listener %s error:%s",listener.getClass().getName(),e.getMessage());
if(trace){
log(e);
}
}
}
});
}
}
}else {
super.afterUpdate(bean);
}
}
@Override
public void afterDelete(final B bean)throws RuntimeDaoException{
if(isLocalReqFirer()){
synchronized (listeners) {
for(final TableListener listener:listeners){
TRANSACTION_LISTENER.runCommitTask(new Runnable() {
@Override
public void run() {
try{
listener.afterDelete(bean);
}catch(Exception e){
log("afterDelete listener %s error:%s",listener.getClass().getName(),e.getMessage());
if(trace){
log(e);
}
}
}
});
}
}
}else {
super.afterDelete(bean);
}
}
@Override
public void done()throws RuntimeDaoException{
if(isLocalReqFirer()){
synchronized (listeners) {
for(final TableListener listener:listeners){
TRANSACTION_LISTENER.runDoneTask(new Runnable() {
@Override
public void run() {
try{
listener.done();
}catch(Exception e){
log("done listener %s error:%s",listener.getClass().getName(),e.getMessage());
if(trace){
log(e);
}
}
}
});
}
}
}
}
private static class TransactionListenerImpl implements TransactionListener{
private static final ThreadLocal> commitTasks = new ThreadLocal<>();
private static final ThreadLocal> doneTasks = new ThreadLocal<>();
@Override
public void onBegin() {
commitTasks.set(new LinkedList());
doneTasks.set(new LinkedList());
}
private static void runEachTask(LinkedList tasks){
try {
// task.run()执行时可能会修改 tasks 的内容,如果直接对tasks遍历会导致 ConcurrentModificationException 异常
// 所以这里在tasks的复本(copy)上执行遍历
ImmutableList copy;
while (! tasks.isEmpty()) {
copy = ImmutableList.copyOf(tasks);
for (Runnable task : copy) {
task.run();
}
tasks.removeAll(copy);
}
} catch (Exception e) {
log("{}:{}",e.getClass().getName(),e.getMessage());
}
}
@Override
public void onCommit() {
// run all commit tasks
runEachTask(checkNotNull(commitTasks.get(),"'onBegin' must be called firstly"));
}
@Override
public void onEnd() {
// run all done tasks
runEachTask(checkNotNull(doneTasks.get(),"'onBegin' must be called firstly"));
commitTasks.remove();
doneTasks.remove();
}
void runCommitTask(Runnable task){
LinkedList tasks = commitTasks.get();
if(tasks != null){
tasks.add(task);
}else {
task.run();
}
}
void runDoneTask(Runnable task){
LinkedList tasks = doneTasks.get();
if(tasks != null){
tasks.add(task);
}else {
task.run();
}
}
}
}