2016-09-14 8 views
2

Пачка-А:OSGi classloading: почему BND импортирует классы, на которые не ссылаются напрямую?

FooA.java

package com.foo.a; 

import com.foo.b.FooB; 

class FooA { 
    FooB b = new FooB(); 
} 

Пачка-Б:

FooB.java:

package com.foo.b; 

import com.foo.c.FooC; 

class FooB { 

    public FooC foo() { 
     ... 
    } 
} 

Пачка-С: ...

Итак, у меня есть 3 пучка - A, B и C.

Bundle Ссылка на ссылки B непосредственно, а ссылки B B-B. C. Как вы видите, FooA не использует метод в FooB, который возвращает FooC, поэтому FooC напрямую не ссылается в пакете A.

Почему BND, включая импортный пакет OSGi, com.foo.c? То, как я это понимаю, - расслоение. Нужно только расслоение B, чтобы иметь возможность разрешить себя. Bundle B, с другой стороны, требует C. Но почему A должен требовать C напрямую, если он там не используется?

ответ

2

Я думаю, что bnd импортирует все классы, которые видны снаружи для классов, которые вы используете. Поскольку вы используете класс FooB, вам может потребоваться доступ ко всем классам, которые могут потребоваться в качестве параметров или возвращать в качестве результатов.

Если вы хотите избежать зависимости, вы можете создать интерфейс, который отображает только те методы, которые вам действительно нужны. Затем вы можете создать службу с этим интерфейсом в комплекте B и получить доступ только к сервису с использованием интерфейса из пакета A.

+0

Хорошо, я понимаю идею с введением интерфейса. Но я не ищу решение этой проблемы. То, что я пытаюсь сделать, - это понять проблему - почему BND включает этот пакет? Действительно ли пакет необходим? Если я удалю импорт вручную, это приведет к разрушению загрузки класса? Зачем? A не использует C напрямую ... – mdzh

+0

Все зависит от того, требуется ли Java для создания экземпляра класса A или его использования в вашем случае. Было бы интересно посмотреть, что произойдет, если вы удалите импорт. Если он по-прежнему работает, возможно, bnd может быть улучшен, но, как правило, он довольно точен. И все же вы действительно должны попробовать использовать интерфейсы и службы ... это единственный способ действительно разделить ваши модули. –

2

Посмотрите на байт-код класса FooA. Вы увидите FooC в этом как-то. Используйте инструмент Java Decompiler, чтобы узнать, почему он используется. Некоторые декомпиляторы создают код, который показывает немного больше информации, чем оригинальный код Java. Я не вижу здесь, почему, но вот еще один пример:

Угадайте у вас есть следующие функции:

public class ListProvider { 

    public static ArrayList getMyList() { return null; } 

} 

И другой класс называет это следующим образом:

List myVar = ListProvider.getMyList(); 

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