我想允许我的域类拥有" injectable"行为。
这个想法基于es4j协议https://es4j.eventsourcing.com/docs/master/core_concepts/domain_protocol.html
但是我使用AxonFramework,所以我需要自己实现它。
目前我采用的方法是#34;协议处理程序"这基于接口。
示例DomainProtocol(伪代码)
public interface NameProtocol extends ProtocolBase {
public String getName();
public void setName(String name);
default boolean handleNameProtocol(DomainEventMessage eventMessage){
// pseudocode
if(eventMessage == NameChangedEvent) setName(eventMessage.getName());
}
}
然后,基本聚合类型将根据类名或注释来初始化处理程序。
目前它基于MethodHandle methodHandle = lookup.findVirtual(aggregateClazz, "handle"+interf.getSimpleName(), MethodType.methodType(boolean.class, DomainEventMessage.class));
不幸的是,接口只允许公共方法,这会导致一些内部方法在外面可见,所以我创建了一个类ProtocolHelper
来强制执行这些方法的调用者:
public class ProtocolHelper extends SecurityManager {
public static final ProtocolHelper INSTANCE = new ProtocolHelper();
public Class[] getCallingClasses() {
return getClassContext();
}
public static void enforcePrivate(){
Class[] classes = ProtocolHelper.INSTANCE.getCallingClasses();
// 0 1 - this class
// 2 - the protected method
// 3 - should be a class that extends ProtocolBase (or same class as 2)
if(
!ProtocolBase.class.isAssignableFrom(classes[3])
&&
!classes[2].equals(classes[3])
)
throw new RuntimeException("This method can only be called by the protocol handler !");
}
}
然后像这样使用它:
@Deprecated
@Override
public void setName(String name) {
ProtocolHelper.enforcePrivate();
this.name = name;
}
显然这种方法非常可怕,但经过多个小时的试验和错误后,这是我能想到的最佳解决方案。
我尽量不在任何地方使用反射,但在初始化时,我不想让Annotation Processor复杂化构建..
感觉就像Java故意试图阻止我这样做,静态抽象类不被继承,不允许受保护的接口方法等等。有没有办法实现我想做的事情?
这个解决方案是否有任何我不知道的问题(除了它"丑陋"或"不是kosher")