简体   繁体   English

Java - 导入项目中的静态初始化程序

[英]Java - static initializers in imported projects

So I have two projects A and B, and project B is imported in project A, and in project BI want to initialize some objects which have static initializers. 所以我有两个项目A和B,项目B在项目A中导入,而在项目BI中则想要初始化一些具有静态初始化程序的对象。 The problem is, they aren't getting called (already tested with final keyword, does not help). 问题是,它们没有被调用(已经使用final关键字测试,没有帮助)。

So I actually want to have a small system and it should go this way (every class decribed here are in project B): 所以我实际上想要一个小系统,它应该采用这种方式(这里描述的每个类都在项目B中):

  • class A is a main class in which you can call a method addClassToLoad() * to add other classes (which will be "loaded" when method start() in class A will be called); class A是一个主类,你可以在其中调用addClassToLoad() *方法来添加其他类(当调用类A中的方法start()时将被“加载”);
  • classes B, C and D call method addClassToLoad() from its static initializer; 类B,C和D从其静态初始化程序调用方法addClassToLoad() ;
  • when some class from project A calls a method start() , class A lists all classes it has gotten and calls a method onLoad() (explained in *). 当项目A中的某个类调用方法start() ,类A列出它已经获得的所有类,并调用方法onLoad() (在*中解释)。

And every method is static, so it's meant to be only one (no "instancing"). 每个方法都是静态的,所以它只是一个(没有“实例化”)。

Saddly, static initializers aren't getting called. 可悲的是,静态初始化器没有被调用。

And the question is: do I do something wrong (or maybe it is not possible at all) or maybe there is another way to do this small system? 问题是:我做错了什么(或者根本不可能)或者可能有另一种方法来做这个小系统? (I just don't really want to write in class A about every class, which must be loaded at start() method) (我只是不想在A类中写关于每个类,必须在start()方法中加载)

* addClassToLoad() takes an interface which has one method onLoad() , so it is getting called when method start() is called in class A * addClassToLoad()接受一个onLoad()方法的接口,因此在A类中调用方法start()会调用它

In code version: 在代码版本中:

class A: A类:

public class A {
    private static ArrayList<ClassToLoad> classesToLoad;

    public static void addClassToLoad(ClassToLoad c) {
        if (classesToLoad == null)
            classesToLoad = new ArrayList<ClassToLoad>();
        classesToLoad.add(c);
    }

    public static void start() {
        for (ClassToLoad c : classesToLoad) {
            c.onLoad();
        }
    }
}

class B (and others (C, D etc.) like this one): B级(和其他人(C,D等)一样):

public class B {

    static {
        A.addClassToLoad(new ClassToLoad() {
            public void onLoad() {
                load();
            }
        });
    }

    private static void load() {
        // do something here on load ...
    }
}

class ClassToLoad: class ClassToLoad:

public interface ClassToLoad {
    public void onLoad();
}

This is the same question when you add a new JDBC driver, why you have to call Class.forName() to register a JDBC driver. 添加新的JDBC驱动程序时,这是同样的问题,为什么必须调用Class.forName()来注册JDBC驱动程序。 Every JDBC driver class has a static initializer to register itself with DriverManager. 每个JDBC驱动程序类都有一个静态初始化程序,用于向DriverManager注册自己。 Why? 为什么? A class loader does not by default load all the classes in jar files. 默认情况下,类加载器不会加载jar文件中的所有类。 A class is loaded only when it is referenced during execution, which is smart as the class loader never has to load those unused classes into memory. 只有在执行期间引用类时才加载类,这很聪明,因为类加载器永远不必将这些未使用的类加载到内存中。 So to resolve your issue, you have to manage to load those classes, like by Class.forName() before you call start(). 因此,要解决您的问题,您必须设法在调用start()之前加载这些类,例如Class.forName()。 If you use spring, you can create a list of all those classes in your configure. 如果使用spring,则可以在configure中创建所有这些类的列表。 Spring also provides an util to scan packages for certain types of classes, then you can just specify a package name to scan. Spring还提供了一个util来扫描某些类型的类的包,然后你可以指定要扫描的包名。

Static fields will be set, and static initializers (static blocks) when ClassLoader will load class for the first time. 当ClassLoader第一次加载类时,将设置静态字段和静态初始化程序(静态块)。 Rembemer that this will happen when given class will be used for the first time as ClassLoader loads classes in lazy fashion (when needed) Rembemer将在给定的类中发生这种情况将首次使用,因为ClassLoader以惰性方式加载类(如果需要)

So it seems it's not possible for me to execute those static blocks, so I added every class, which I need to load, into class A, and that way they're actually loading without any problems (in project B). 所以我似乎不可能执行那些静态块,所以我将每个需要加载的类添加到A类中,这样它们实际上加载时没有任何问题(在项目B中)。 And in project AI need to add other classes, which I need to load, in the main class, obviously. 在项目AI中,显然需要在主类中添加我需要加载的其他类。

So I made those classes as Singletons, so they're actually loaded and are ready for "main" loading, launching and disposing. 所以我把这些类作为单身人士,所以他们实际上已经加载并准备好“主要”加载,启动和处理。 So the adding class looks like this: 所以添加类看起来像这样:

A.addClassToLoad(B.getInstance());

I used class ClassToLoad as a generic class to load (sounds funny), though I renamed it to SystemCycle . 我使用类ClassToLoad作为通用类加载(听起来很有趣),虽然我将其重命名为SystemCycle

So the code as an example of class B now looks like this: 所以作为B类示例的代码现在看起来像这样:

public class B implements SystemCycle {
    private static B instance = new B();

    private B() {}

    public static void getInstance() {
        return instance;
    }

    public void onLoad() { /* some code here */ }
    public void onLaunch() { /* some code here */ }
    public void onDispose() { /* some code here */ }

}

And SystemCycle class looks now like this: SystemCycle类现在看起来像这样:

public interface SystemCycle {

    public void onLoad();
    public void onLaunch();
    public void onDispose();

}

Well, that was obvious, because of example of class B. 嗯,这很明显,因为B类的例子。

And I even made small checking system, so if the user tries to call one of these methods, it will be ignored, as the class implementing SystemCycle checks whether the class A is actually loading, launching or disposing at that moment. 我甚至做了一个小的检查系统,所以如果用户试图调用其中一个方法,它将被忽略,因为实现SystemCycle的类检查A类是否实际上正在加载,启动或处置。 But if not, it just can do return . 但如果没有,它就可以return (though if the usermade class doesn't check that, it can be abused by other usermade class). (尽管如果usermade类没有检查它,它可能会被其他用户制作的类滥用)。

PS addClassToLoad in my project is actually called addSystemToLoad , so I made it here this way to make an example easier to understand. 我的项目中的PS addClassToLoad实际上叫做addSystemToLoad ,所以我这样做就是为了让一个例子更容易理解。

Small edit: I even tried something to do with annotations first, but even that thing didn't help me. 小编辑:我甚至首先尝试使用注释,但即使那件事也没有帮助我。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM