Why java classes do not inherit annotations from implemented interfaces?
I'd say the reason is that otherwise a multiple-inheritance problem would occur.
Example:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD) @Inherited
public @interface Baz { String value(); }
public interface Foo{
@Baz("baz") void doStuff();
}
public interface Bar{
@Baz("phleem") void doStuff();
}
public class Flipp{
@Baz("flopp") public void doStuff(){}
}
public class MyClass extends Flipp implements Foo, Bar{}
If I do this:
MyClass.class.getMethod("doStuff").getAnnotation(Baz.class).value()
what's the result going to be? 'baz', 'phleem' or 'flopp'?
For this reason, annotations on interfaces are rarely useful.
Annotation is not inherited from interface method
From the javadocs of java.lang.annotation.Inherited
:
Note that this meta-annotation type has no effect if the annotated
type is used to annotate anything other than a class. Note also that
this meta-annotation only causes annotations to be inherited from
superclasses; annotations on implemented interfaces have no effect.
Why can @Repeatable Annotations not be inherited from interfaces
Please recall the documentation of @Inherited
:
If an Inherited meta-annotation is present on an annotation type declaration, and the user queries the annotation type on a class declaration, and the class declaration has no annotation for this type, then the class's superclass will automatically be queried for the annotation type.
In other words, @Inherited
never was intended to be a feature for collecting multiple annotations on a type hierarchy. Instead, you will get the annotation of the most specific type which has an explicit annotation.
In other words, if you change your declaration to
@RepeatableAnnotation("FOO") @RepeatableAnnotation("BAR") class Base {}
@RepeatableAnnotation("C") @RepeatableAnnotation("D")
public class TestClass extends Base implements IntefaceA, IntefaceB {
it won’t change the result; FOO
and BAR
of Base
are not inherited by TestClass
as it has the explicit annotation values C
and D
.
Expanding this to the interface
hierarchy would be awkward due to the multiple inheritance and the fact that a super-interface may turn out to be a sub-interface of another super-interface so finding the most specific one is not trivial. This differs heavily from the linear search of the superclass hierarchy.
You may encounter the situation where multiple unrelated annotated interface
s exist but it’s not clear why this ambiguity should be resolved by joining them into one repeated annotation. This would not harmonize with the behavior in all other scenarios.
Note that the answer you have linked is a bit odd as it shows code using a method annotation but method annotations are never inherited, regardless of whether you specified @Inherited
or not (an audit tool should generate a warning when you combine @Target(ElementType.METHOD)
with @Inherited
, imho). @Inherited
is relevant for type annotations only.
Is a type-level annotation always inherited by public methods of that type?
It is never the case that they are equivalent unless the library interpreting the annotation specifically decides to treat the type-level annotation as a default (e.g., Spring's @Transactional
). Even then, it is entirely up to the code written in the library whether a combination of class-level and method-level annotations result in combination (@RequestMapping
) or replacement (@Transactional
) of definitions.
Do I Have to Put @Secured Annotations on Interface or on Class?
In your provided link said, @Transactional
is also @Inherited
. Lets break down each part of them.
As per spring's developers recommended that use @Transactional
annotation with concrete class.
You can use @Transactional
annotation in interface or a method inside the interface. You can think this will work as you expected if you used interface-based-proxies
. Annotation that is not inherited refers that if you are using class-based-proxies
then probably transaction attribute are not applied to that interface. So the ultimate object can not covered or wrapped by transactional attribute.
If so, @Secured
annotation is @Inherited
then this can be used both in interface and its implementation class.
From spring docs:
The Secured annotation is used to define a list of security configuration attributes for business methods.
For example:
@Secured({ "ROLE_USER" })
public void create(Contact contact);
@Secured({ "ROLE_USER", "ROLE_ADMIN" })
public void update(Contact contact);
@Secured({ "ROLE_ADMIN" })
public void delete(Contact contact);
So In the bottom line, you may have multiple implementations for an interface. So, keeping your @Secured
annotation in interface makes sense.
Perf4j does not profile annotated Interface method
Even if @Profiled
used @Inherit
it wouldn't work because inherited annotations are only ever passed on to sub classed and not implementations of interfaces.
@Inherited annotations are not inherited when used to annotate
anything other than a type. A type that implements one or more
interfaces never inherits any annotations from the interfaces it
implements.
Source: http://www.eclipse.org/aspectj/doc/released/adk15notebook/annotations.html#annotation-inheritance
More details: http://www.jroller.com/melix/entry/the_truth_about_annotations_inheritance
What would your custom processor do, query a service's interface for @Profiled
? I suggest you manually annotate the service implementations because in my experience @Profiled
is only helpful if you use it with its tag
and message
attributes (which differ in each implementing class I suppose).
http://perf4j.codehaus.org/devguide.html#Adding_the_Profiled_Annotation_to_Method_Declarations -> "@Profiled(tag = "dynamicTag_{$0}")"
Related Topics
Why Are Interface Variables Static and Final by Default
Problems Converting Byte Array to String and Back to Byte Array
Convenient Way to Parse Incoming Multipart/Form-Data Parameters in a Servlet
What Does the Question Mark in Java Generics' Type Parameter Mean
How to Determine the Class of a Generic Type
Strings Are Objects in Java, So Why Don't We Use 'New' to Create Them
Why Does the Jtable Header Not Appear in the Image
When Do Java Generics Require <? Extends T> Instead of <T> and Is There Any Downside of Switching
Which Cipher Suites to Enable for Ssl Socket
Java8 Lambdas VS Anonymous Classes
Strange Floating-Point Behaviour in a Java Program
Http Basic Authentication in Java Using Httpclient
How to Fix Role in Spring Security
How to Invoke a Linux Shell Command from Java
Java Socket Why Server Can Not Reply Client