在Java中对方法体施加约束或限制

afs*_*tos 11 java architecture methods constraints invariants

上下文(编辑)

有些澄清是需要的,所以我会试着总结影响这个问题的因素.

  • 该项目的目标是为程序员提供某种功能,最有可能是以库的形式(我猜是一个带有类文件的JAR).

  • 要使用所述功能,程序员必须遵守必须(应该)满足的约束.否则它将无法按预期运行(就像锁定java.util.concurrent,必须在适当的时间和地点获取/释放).

  • 此代码不是使用它的应用程序的入口点(没有main).

  • API中公开的操作数量有限(且很小).

例子:

  1. 想想一个小游戏,几乎所有东西都是由已经实现的类实现和管理的.程序员唯一要做的就是编写一个方法或其中几个描述角色将要做什么的方法(走路,改变方向,停止,检查对象).我想确保他们的方法(可能标有注释?)只是walk,或者changeDirection,或者计算diff = desiredValue - x,而不是说,写入某个文件,或者打开套接字连接.

  2. 想想交易经理.该库将提供管理器,以及事务的一些常量属性(它们的隔离级别,超时,......).现在,程序员想要进行交易并使用这个经理.我想确保他们只read,write,commit,或rollback在一些资源,已知的经理.launchRocket如果经理不控制任何火箭发射,我不希望他们在交易过程中.

问题

我想在方法(或方法组)的主体上施加一些不变量/限制/约束,稍后由其他程序员在其他一些包/位置中实现.说,我给他们的东西:

public abstract class ToBeExtended {
    // some private stuff they should not modify
    // ...
    public abstract SomeReturnType safeMethod();
}
Run Code Online (Sandbox Code Playgroud)

为了本项目的目的,方法体满足一些不变量是很重要的(可能是必要的).或者更确切地说,此方法实现使用的命令集是有限的.这些约束的例子:

  • 此方法不得执行任何I/O.
  • 此方法不得实例化任何未知(潜在危险)对象.
  • ...

换一种方式:

  • 此方法可以调用已知(特定)类的方法.
  • 此方法可以执行一些基本指令(数学,分配局部变量,ifs,循环......).

我一直在浏览Annotations,似乎没有任何接近这一点.
我到目前为止的选择:

  1. 定义一些注释,@SafeAnnotation并将其应用于方法,与实施者定义合同,他将遵循规定的规则,否则系统将发生故障.

  2. Enum使用允许的操作定义a .而不是暴露允许的方法,只暴露一个方法,接受这些枚举对象的列表(或类似于控制流图?)并执行它,让我控制可以做什么.

例:

public enum AllowedOperations { OP1, OP2 }

public class TheOneKnown {
    public void executeMyStuff (List<AllowedOperations> ops) {
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题

语言中是否有任何功能,例如注释,反射或其他功能,允许我检查(在编译时或运行时)方法是否有效(满足我的约束)?
或者更确切地说,有没有办法强制它只调用一组有限的其他方法?

如果不是(我认为不是),第二种方法是否合适?
在直观,精心设计和/或良好实践中是合适的.

更新(进度)

看了一些相关的问题后,我也在考虑(作为第三种选择,也许)按照这个问题的接受答案中给出的步骤.虽然,这可能需要对架构进行一些重新思考.

使用注释来施加限制的整个想法似乎需要实现我自己的注释处理器.如果这是真的,我不妨考虑一个特定于域的小语言,以便程序员使用这些有限的操作,稍后将代码转换为Java.这样,我也可以控制指定的内容.

dig*_*oel 6

看看java策略文件.我没有使用它们,我不确定它们是否完全符合您的问题,但是通过深入研究文档它们可能是合适的.这里有一些可能有帮助的SO问题

限制Java中的文件访问

什么是简单的Java安全策略来限制文件写入单个目录?

这里有一些关于策略文件的文档.

http://docs.oracle.com/javase/6/docs/technotes/guides/security/PolicyFiles.html


gab*_*sch 4

我觉得这个问题的方向很好。

  • 使用特定的ClassLoader加载类。请注意,它们是一种有趣的马,通常会发生类本身由父类加载器加载的情况。也许您想要某种UrlClassLoader,并且父类加载器将设置为 Root 类加载器,但这还不够。
  • 用于threads避免无限循环(而不是像那里那样实现Runnable而不是扩展Thread) - 如果您不担心的话,这可能是不必要的。
  • 使用SecurityManager避免java.io操作

除了上述之外,我推荐2个选择:

为该方法提供一个控制器,其中包含它可以调用的函数

例如:

public void foo(Controller ctrl) {
}

public class Controller {
   public boolean commit();
   public boolean rollback();
}
Run Code Online (Sandbox Code Playgroud)

这可以给用户一个句柄,允许哪些操作。

使用Intent-like 命令模式

在Android中,系统的组件是相当封闭的。他们不能直接相互通信,他们只能触发一个事件,“这发生了”,或者“我想这样做”。

这样,可用命令的集合就不受限制。通常,如果这些方法只执行小型业务逻辑,那就足够了。