Ошибка приватного доступа к внешнему классу, введенному CDI из статического внутреннего класса.
-
21-12-2019 - |
Вопрос
У меня есть (в минималистической версии) следующие управляемые компоненты CDI в JBoss EAP 6.0.1.
@ApplicationScoped
public class Outer {
private final List<String> values = new ArrayList<String>();
public void printValues() {
System.out.println("Values: " + values);
}
private void addValue(String value) {
values.add(value);
}
public static class Inner {
@Inject
private Outer outer;
public void addFoo() {
outer.addValue("foo");
}
}
}
И следующий код для проверки этого (не задавайтесь вопросом, почему.Это только для этой витрины.):
@Inject
Outer outer;
@Inject
Outer.Inner inner;
public void test() {
inner.addFoo();
outer.printValues();
}
Я получаю вывод:
Values: {}
где я ожидал значения foo.
Дальнейшее расследование показало, что звонок в private void addValue
получает доступ к версии values
атрибут, который находится в сгенерированном Weld прокси Outer
тогда как вызов public void printValues
обращается к реальному атрибуту реального экземпляра управляемого компонента.
Чтобы еще больше запутать ситуацию:Если я изменю уровень доступа addValue
к одному из package
, protected
или public
все работает так, как ожидалось.
Но цель внутреннего класса в моем случае заключалась в том, чтобы сделать метод закрытым, чтобы другие CDI-клиенты Outer не могли вызвать этот метод.И теперь это единственное, что не работает :D
Есть идеи, что случилось?Это ошибка в Weld?
Решение
В настоящее время все поставщики CDI используют прокси (это не требуется по спецификации, но именно так были реализованы все три реализации) для внедрения любых объектов без псевдообласти.Если бы Внешний был @DependantScoped
Я почти уверен, что все будет работать так, как вы хотите.Созданные прокси, естественно, являются подклассами ваших классов, поэтому вызов частного метода для внедренного объекта не будет работать.Честно говоря, я удивлен, что он не взорвался.