-1

I have a Interface I and a Abstract Class A , I have My custom annotation MyAnnotation which should take parameter as subclass S of A, now while processing annotation I want to call method of concrete class S

public interface I{
   void m1();
}

public abstract class A implements I {
    public abstract void m1();
}

public @interface MyAnnotation {
    public Class< ? extends A> ref();
    public Class< ? super A> ref2();
}

public S extends A{
    public void m1() {}
}

I am annotating method like

@MyAnnotation(ref= new XX() )  or @MyAnnotation(ref= XX.class )
@MyAnnotation(ref= new yy() ) or @MyAnnotation(ref= yy.class )

whichever works

//In spring aspect before processing I am getting method annotation and trying to call m1()  
annotation.ref().m1() //Error
annotation.ref2().m1() //Error
1
  • abstarct and public S extends A aren't correct Commented Oct 7, 2018 at 17:17

2 Answers 2

3

You can't use new XX() in an annotation. Annotations parameters can use a very specific set of types:

  • primitive
  • String
  • Class
  • an Enum
  • another Annotation
  • an array of any of the above

See this answer.

So to accomplish what you're trying to accomplish, you'd have to use a class.

You would then have to use reflection to create an instance and invoke the method.

Class<?> clazz = annotation.ref();
I instance = (I) cls.getConstructor().newInstance();
instance.m1();

See this answer.

Your classes must all have no-argument constructors, else you'll only be able to instantiate some this way but not others (leading you to have to conditionally branch based on the class).

Sign up to request clarification or add additional context in comments.

4 Comments

I think ((I) cls.newInstance()).m1() is a better option than ...getMethod(...).invoke(...)
@ernest_k newInstance is deprecated since 9; it's better to call Constructor::newInstance
@Eugene That's right. My comment is just about avoiding the getMethod(...).invoke(...) part, if you notice...
@ernest_k + Eugene, You're both right. It was a bit of a lazy answer, mostly just copied and pasted from the sources I listed. I've improved it now
0

You can't do that simply like that. You need an instance of the class first. If your A class is a Spring's bean, you can inject ApplicationContext and get the bean from there. Then you can call a method.

@Autowired
private ApplicationContext context;

void test(MyAnnotation annotation) {
    A bean = context.getBean(annotation.ref());
    bean.m1();
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.