Вопрос по java – Java ClassLoader изменение

5

У меня есть классA:

public class A {
    public A(String str) {
        System.out.println("Create A instance: " + str);
    }

    public void methodA() {
        System.out.println("#methodA1()");
    }
}

И моя реализация загрузчика классов:

public class MyClassLoader extends ClassLoader {
    public MyClassLoader() {    
        super();
    }

    @Override
    public synchronized Class<?> loadClass(String name) 
            throws ClassNotFoundException {

        System.out.println("Load: " + name);

        return super.loadClass(name);
    }
}

И теперь я пытаюсь изменить загрузчик классов по умолчанию в текущем потоке:

import java.util.ArrayList;
import java.util.List;

public class ChangeLoaderTest {
    public static void main(String[] args) {
        // Save class loader so that we can restore later.
        ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();

        MyClassLoader newLoader = new MyClassLoader();
        try {
            // Set new classloader.
            Thread.currentThread().setContextClassLoader(newLoader);

            // My class.
            A a = new A("1");
            a.methodA();

            // Standard Java class.
            List<Integer> list = new ArrayList<Integer>();
            list.add(2);
            list.add(3);
        } finally {
            // Restore.
            Thread.currentThread().setContextClassLoader(oldLoader);
        }
    }
}

А такжеChangeLoaderTest выход:

Create A instance: 1
#methodA1()

Ни один. Никто

Load: ...

Зачем? Как я могу изменитьClassLoader в какой-нить?

Хорошо, я могу объяснить контекст этого вопроса. У меня есть класс, который читает изображения вBufferedImage, Иногда этоImageIO.read(file)иногда этоSanselan.getBufferedImage(file), У меня есть свой собственный класс для сохранения изображений, и я должен создатьBuffredImage из файла, затем скопируйте данные изBufferedImage к моему объекту. Я хочу использовать прокси-класс, чтобы поймать все#get(...) вызов методов для сохранения информации в моем объекте. dzav
"I have some class A:" Мне уже скучно. Нет, это не совсем верно, но я не собираюсь продолжать читать. В то время как некоторые люди думают, что лучше «абстрагировать проблему». до такой степени, что вы можете выразить это как тупые символы, я предпочитаю некоторый контекст, который помогает объяснить, что в классеA это заставляет вас хотеть загружать это динамически. И.Е. учебный классA может бытьUserDefinedPlugIn - последний обеспечивает некоторый контекст, первый - нет. Andrew Thompson

Ваш Ответ

3   ответа
4

контекстный загрузчик классов предназначен для использования фреймворками, Чтобы использовать загрузчик самостоятельно, вам нужно позвонитьloadClass("somepackage.A") а затем использовать API отражения для создания нового экземпляра A (Class.newInstance()).

Вы не сможете напрямую использовать A или его методы в своем источнике, поскольку вызывающий код не знает A - он использует другой загрузчик классов. Интерфейс или базовый класс A, который может быть загружен обычным загрузчиком классов, может использоваться, чтобы избежать отражения.

interface AIF{
        void someMethod();
 }
class A implements AIF{
      public void someMethod(){}
 }


public void test(){
     MyLoader loader = new MyLoader();
     Class cla = loader.loadClass("A");
     AIF a = (AIF) cla.newInstance();
     a.someMethod();

 }
К сожалению, вы не можете определить конструктор не по умолчанию в интерфейсе (любой конструктор в этом отношении) так, как это имеет vanveber. Итак, антре ...
@mazaneicha, вы можете обойти это, создав фабричный класс и фабричный интерфейс (только если вы действительно ненавидите рефлексию).
3

contextClassLoader механизмы этоnot используется базовыми операциями Java, такими какnew, Это только там, так что различные структуры могут получить доступ к загрузчику классов контекста и загрузить ресурсы, классы и т. Д. Java всегда будет использовать загрузчик классов, который загружал код, который выполняется. Это тот, к которому вы получаете доступ черезChangeLoaderTest.class.getClassLoader() - и с этим ничего не поделаешь.

0

что происходит то, что загрузчик классов вашего приложения, который также является родительским загрузчиком классов, является родительским. может найтиA и загрузить его. В результате ваш загрузчик классов не будет найден или использован для загрузки.A.

Честно говоря, у меня нет большого опыта работы с загрузчиками классов, но если вы вложили в подкласс тот, который использует URL для пути к классу (чтобы он мог найти файл класса), а родительский загрузчик классов не может его загрузить (не является частью classpath). ), ваш заказ будет использоваться.

Похожие вопросы