是否有可行的方法在Java中加载任何类时运行我自己的代码,而不强制用户明确地手动加载所有类和自定义类加载器?
无论细节如何,只要实现某个接口的类读取其注释将其与另一个类链接,并将该对赋予第三个类。
编辑:哎呀,我会详细说明:我正在做一个事件处理库。我正在做的是让客户端代码执行他们自己的侦听器/事件对,这需要作为一对在我的库中注册。 (嗯,毕竟不是那么久)。
进一步编辑:目前客户端代码需要手动注册这对类/接口,这非常有效。我的意图是将其自动化,我认为将两个类与注释联系起来会有所帮助。接下来,我想摆脱需要始终保持注册列表最新的客户端代码。
PS:静态块不会,因为我的接口被捆绑到一个库中,客户端代码将创建更多的接口。因此,抽象类也不会这样做,因为它必须是一个接口。
答案 0 :(得分:8)
如果要在接口上建立行为,可以在该接口中使用静态初始化程序。
public interface Foo{
static{
// do initializing here
}
}
我不是说这是一个好习惯,但它肯定会在第一次加载一个实现类时初始化。
更新:接口中的静态块是非法的。改为使用抽象类!
<强>参考:强>
但是如果我理解你的话,你希望每个实现类初始化一次。这将是棘手的。使用基于接口的解决方案绝对不能做到这一点。您可以使用具有动态初始化程序(或构造函数)的抽象基类来执行此操作,该基类检查所请求的映射是否已存在,如果不存在则添加它,但在构造函数中执行此类操作非常糟糕。
我认为你最干净的选择是在构建时生成代码(通过使用apt或通过字节码分析使用像asm这样的工具进行注释处理),或者在类加载时使用代理来动态创建映射。 / p>
啊,更多输入。很好。因此,客户端使用您的库并根据注释提供映射。然后我会说你的库应该提供一个初始化方法,其中客户端代码可以注册类。像这样:
YourLibrary.getInstance().registerMappedClasses(
CustomClass1.class,
CustomClass2.class,
CustomClass3.class,
CustomClass4.class
)
或者更好的是,一个包扫描机制(可以找到实现它的示例代码at this question):
YourLibrary.getInstance().registerMappedClassesFromPackages(
"com.mycompany.myclientcode.abc",
"com.mycompany.myclientcode.def"
)
无论如何,基本上没有办法避免让你的客户做那种工作,因为你无法控制他们的构建过程或他们的类加载器(但你当然可以提供类加载器或构建配置的指南)。
答案 1 :(得分:2)
如果你想在任何类加载上运行一些代码,你应该:
根据您的环境类型,有可能不是所有类都被自定义ClassLoader加载(一些实用程序包使用自己的CL,一些Java EE容器处理一些具有特定classLoaders的空间区域等) ,但这是对你所要求的一种近似。