Java Annotation and Processor для пометки метода как такового, чтобы его можно было вызывать один раз и только один раз? - PullRequest
5 голосов
/ 28 октября 2011

Мне нужно пометить методы, чтобы они вызывали исключение RuntimeException, если они вызываются более одного раза.

Я пытаюсь применить некоторую семантику одиночного присваивания, и число параметров для моего класса слишком велико, чтобы поместить его в один конструктор, и я должен быть в состоянии сделать эти классы JAXB также осведомленными, поэтомуобъекты должны быть изменяемыми, но я хочу применить семантику одиночного присваивания.

Я вполне уверен, что могу сделать это с Аспектами, но я действительно хотел бы иметь возможность использовать вместо этого собственный процессор аннотаций.

Я знаю, как это сделать с помощью Decorators в Python.

Как написать процессор аннотаций, который может перехватывать вызовы аннотированного метода во время выполнения, а не только во время компиляции?

Я думаю, что кое-что с динамическими прокси перехватывает вызовы методов, мне просто нужно выяснить, как интегрировать их с моим процессором аннотаций.

Динамические прокси требуют от вас использованияИнтерфейс, который является слишком громоздким, у меня есть CGLib MethodInterceptor , работающий сейчас, намного меньшетребования к тому, что перехватывается и оформляется за счет добавления зависимости.

Ответы [ 4 ]

3 голосов
/ 28 октября 2011

Нет, нет ничего готового к использованию.И AspectJ кажется единственным способом заставить его работать в более общем смысле.Как отметил Дж. Б. Низет, у аннотации должен быть синтаксический анализатор.

Однако я бы посоветовал найти лучшее и более простое решение - шаблон Builder.Как это выглядит:

  • у вас есть FooBuilder (это также может быть статический внутренний класс), который является изменяемым и имеет установщик и получатель для каждого из полей
  • FooBuilder имеет метод build(), который возвращает экземпляр Foo
  • Foo, имеет конструктор, который принимает только FooBuilder, и вы присваиваете ему каждое поле.

Таким образом:

  • Foo является неизменным, что является вашей конечной целью
  • Он прост в использовании.Вы устанавливаете только те поля, которые вам нужны.Что-то вроде:

    Foo foo = new Foo.FooBuilder().setBar(..).setBaz(..).build();
    

Таким образом, конструктор может поддерживать JAXB.Например:

FooBuilder builder = (FooBuilder) unmarshaller.unmarshal(stream);
Foo foo = builder.build();

Объекты JAXB должны быть изменяемыми, а ваше требование является неизменным объектом.Следовательно, строитель пригодится, чтобы преодолеть это.

2 голосов
/ 25 апреля 2012

Этот вопрос демонстрирует некоторое сходство с вопросом Применение CGLib Proxy из процессора аннотаций .

Если вы хотите изменить поведение исходного исходного кода в процессоре аннотаций, посмотрите, как http://projectlombok.org/ достигает этого. Единственным недостатком IMO является то, что lombok использует классы com.sun. *.

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

1 голос
/ 28 октября 2011

Вы можете настроить JAXB для использования доступа к полю (переменной экземпляра), используя @XmlAccessorType(XmlAccessType.FIELD).Это позволит вам делать то, что вам нужно, с помощью метода set:

Вы также можете использовать механизм JAXB XmlAdapter для поддержки неизменяемых объектов:

0 голосов
/ 28 октября 2011

Вместо использования аннотации вы можете использовать.

assert count++ != 0;

Вам понадобится один счетчик на метод.

...