开发者

Losing Class Custom Annotation For Proxy Classes

I am using Seam to inject beans to my controller using @In annotation. The injected class has a custom annotation, when calling injectedClass.getClass().getAnnotation(annotationClass) it returns null.

When debug I found that Seam passes a proxy instance so getClass() returns InjectedClass_$$_javassist_seam_5 which doesn't have my custom annotation.

How I can get my custom annotation from the proxy class?

Here's how my classes look like:

@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 
     }
}


Good question.

When you call a method by using Seam, it is intercepted by a proxy. And this one enables @In or @Out-jection. But There is an exception to this rule: it does not work when you call an internal method

So try this code

@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));
    }

}

Added to original answer

You want to retrieve an annotation from your bean. But, because of method interceptor, myAnnotatedClass.getClass() returns a proxy object, not the bean class itself.

For each bean class, Seam creates a Component definition, in which is stored in the application context. The name of the attribute follows this pattern: component name plus .component. So if you have a bean like this one

@Name("myBean")
public class MyBean {

}

Its Componet definition is stored in the attribute myBean.component

So inside your method, you can use

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

Now you can call

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

regards,


If you want less "ComponentDefinition" overbloat, you could also use this which also works for CDI and Spring:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜