Потеря пользовательской аннотации класса для прокси-классов

Я использую Seam для внедрения bean-компонентов в мой контроллер с помощью аннотации @In. Внедренный класс имеет пользовательскую аннотацию, при вызове InjectedClass.getClass().getAnnotation(annotationClass) он возвращает значение null.

При отладке я обнаружил, что Seam передает экземпляр прокси, поэтому getClass() возвращает InjectedClass_$$_javassist_seam_5, у которого нет моей пользовательской аннотации.

Как я могу получить свою пользовательскую аннотацию из прокси-класса?

Вот как выглядят мои занятия:

@CustomAnnotation(value="myvalue")
@Name("myAnnotatedClass")
public class MyAnnotatedClass extends SuperClass {...}

@Scope(ScopeType.SESSION)
@Name("myController")
public class MyController {
     @In("#{myAnnotatedClass}")
     private MyAnnotatedClass myAnnotatedClass;

     public void actionMethod(){
         //call another class which call myAnnotatedClass.getClass().getAnnotation(CustomAnnotation.class)
         //then do some reflection for MyAnnotatedClass fields 
     }
}

person Noura    schedule 30.12.2009    source источник
comment
Было бы очень полезно, если бы вы могли опубликовать соответствующие части исходного кода вашего внедренного класса.   -  person skaffman    schedule 30.12.2009
comment
Я изменил описание вопроса, чтобы иметь образец кода   -  person Noura    schedule 30.12.2009
comment
@Noura Добавлено в исходный ответ   -  person Arthur Ronald    schedule 30.12.2009


Ответы (2)


Хороший вопрос.

Когда вы вызываете метод с помощью Seam, он перехватывается прокси-сервером. А этот включает @In или @Out-jection. Но есть исключение из этого правила: это не работает, когда вы вызываете внутренний метод

Итак, попробуйте этот код

@Name
public class Service {

    @In
    private MyAnnotatedClass myAnnotatedClass;


    public void myInterceptedMethod() {
        // internal method bypass interceptor
        // So @In or @Out-jection is not enabled
        internalMethod();
    }

    private void internalMethod() {
        System.out.println(myAnnotatedClass.getClass().getAnnotation(annotationClass));
    }

}

Добавлено в исходный ответ

Вы хотите получить аннотацию из вашего bean-компонента. Но из-за перехватчика метода myAnnotatedClass.getClass() возвращает прокси-объект, а не сам класс компонента.

Для каждого класса компонента Seam создает определение компонента, в котором хранится в контексте приложения. Имя атрибута следует следующему шаблону: имя компонента плюс .component. Итак, если у вас есть боб, как этот

@Name("myBean")
public class MyBean {

}

Его определение компонента хранится в атрибуте myBean.component.

Итак, внутри вашего метода вы можете использовать

Component myBeanComponentDefinition = (Component) Context.getApplicationContext().get("myBean.component");

Теперь вы можете позвонить

myBeanComponentDefinition.getBeanClass().getAnnotation(CustomAnnotation.class);

С уважением,

person Arthur Ronald    schedule 30.12.2009
comment
Спасибо за ваш ответ, но он не работает. Я использовал оболочку для MyAnnotatedClass, у оболочки есть аннотация @Name вместо MyAnnotatedClass. Теперь в контроллер введена оболочка, и он вызывает wrapper.getMyAnnotatedClass().getAnnotation(annotationClass). Я думаю, что это уродливое решение, но оно решило проблему, пока у нас не будет лучшего. - person Noura; 30.12.2009
comment
да, это получает аннотацию. Я также мог бы получить аннотацию, используя myAnnotatedClass.getSuperClass().getAnnotation(CustomAnnotation.class), но я не могу получить поля путем отражения. Я повторяю myAnnotatedClass.getSuperClass().getClass().getDeclaredFields(). Затем вызовите field.get(myAnnotatedClass), при передаче прокси-объекта он выдает исключение. - person Noura; 30.12.2009

Если вы хотите меньше раздувать «ComponentDefinition», вы также можете использовать это, которое также работает для CDI и Spring:

Class.forName(myBean.getClass().getCanonicalName().substring(0,myBean.getClass().getCanonicalName().indexOf("$"))).getAnnotation(MyAnnotation.class)
person Xnyle    schedule 12.04.2013