net.gdface.utils.InterfaceContainer Maven / Gradle / Ivy
package net.gdface.utils;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.LinkedHashSet;
import java.util.Set;
import static net.gdface.utils.SimpleTypes.getRawClassOfSuperPamamType;
import static net.gdface.utils.SimpleLog.log;
/**
* 实现接口实例的级联容器
* @param 接口类型
* @author guyadong
*
*/
public class InterfaceContainer {
private final Set listeners = new LinkedHashSet();
private final Class interfaceClass;
private boolean skipOnError = true;
private boolean logOnError = false;
/**
* 接口容器实例
*/
public final I container;
/**
*
*/
@SuppressWarnings("unchecked")
protected InterfaceContainer() {
interfaceClass = (Class) getRawClassOfSuperPamamType(getClass())[0];
if(!interfaceClass.isInterface()){
throw new IllegalArgumentException("param I must be interface");
}
// 创建侦听器窗口接口实例
container = proxyInstance();
}
public InterfaceContainer(Class interfaceClass) {
Assert.notNull(interfaceClass, "interfaceClass");
if(!interfaceClass.isInterface()){
throw new IllegalArgumentException("param I must be interface");
}
this.interfaceClass = interfaceClass;
// 创建侦听器窗口接口实例
container = proxyInstance();
}
/**
* 根据当前对象创建新的接口实例{@link Proxy}
* @return
*/
private final I proxyInstance(){
return interfaceClass.cast(Proxy.newProxyInstance(
interfaceClass.getClassLoader(),
new Class>[]{ interfaceClass},
new Handler()));
}
/**
* 将接口实例加入容器
* @param listener
*/
public void register(I listener){
if(listener != null){
synchronized (this) {
listeners.add(listener);
}
}
}
/**
* 从容器中删除指定的接口实例
* @param listener
*/
public void unregister(I listener){
if(listener != null){
synchronized (this) {
listeners.remove(listener);
}
}
}
/**
* 设置当执行容器中的接口实例有异常抛出时的动作
* 为{@code true}时跳过继续执行下一个容器
* 为{@code false}时抛出异常
* @param skipOnError 当调用抛出异常时是否忽略
* @return 当前实例
*/
public InterfaceContainer setSkipOnError(boolean skipOnError) {
this.skipOnError = skipOnError;
return this;
}
/**
* 设置当执行容器中的接口实例有异常抛出时是否日志输出(仅当skipOnError为true时有效)
* @param logOnError 当调用抛出异常时是否输出日志
* @return 当前实例
*/
public InterfaceContainer setLogOnError(boolean logOnError) {
this.logOnError = logOnError;
return this;
}
private class Handler implements InvocationHandler{
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
for(I listener:listeners){
try {
method.invoke(listener, args);
} catch (InvocationTargetException e) {
Throwable te = e.getTargetException();
if(skipOnError){
if(logOnError){
//拦截所有异常,保证不影响其他的Listener运行
log("ERROR:"+te.getMessage(), te);
}
continue;
}
throw te;
}catch (Throwable e) {
throw e;
}
}
return null;
}
}
}