For one of my requirment i have created a inteface with multiple methods and each method annotated with my own java custom annotation.
I have a spring aop aspect for my implementation class and i am not able to get my custom annotation in aop aspect.
after doing debug i understood my custom annotation is part of the interface and not in implementation class.
How can i get my custom annotation in my implementation methods which declared in interface ?
In Java, annotations are not inhereted from interfaces.With aspects you must annotate the implementation class (and/or methods within that class), not the interface (if any) that the class implements. String aop follows Java’s rule that annotations on interfaces are not inherited.
So, if you want to work with your annotation , create an abstract super class to be able to do this.
Inside aspect you work with proxy object and methods are wrapped in proxy calls. But if you know a real class/interface , you can get annotation by reflection api from source class/interface
Related
I have a set of classes I would like to require a certain method implemented with Spring's #Scheduled annotation. I don't want a default defined, I just want to require that the annotation is used on a certain method.
Is this possible either through Interfaces or abstract classes?
Spring doc has the two recommendations:
Spring recommends that you only annotate concrete classes (and methods
of concrete classes) with the #Transactional annotation, as opposed to
annotating interfaces. You certainly can place the #Transactional
annotation on an interface (or an interface method), but this works
only as you would expect it to if you are using interface-based
proxies. The fact that Java annotations are not inherited from
interfaces means that if you are using class-based proxies
(proxy-target-class="true") or the weaving-based aspect
(mode="aspectj"), then the transaction settings are not recognized by
the proxying and weaving infrastructure, and the object will not be
wrapped in a transactional proxy, which would be decidedly bad.
(from http://static.springsource.org/spring/docs/3.0.x/reference/transaction.html)
and
Spring AOP uses either JDK dynamic proxies or CGLIB to create the
proxy for a given target object. (JDK dynamic proxies are preferred
whenever you have a choice).
(from http://static.springsource.org/spring/docs/3.0.x/reference/aop.html#aop-understanding-aop-proxies)
Do I understand correctly that in order to follow both recommendations, I need to have #Transactional annotation on concrete class, but still provide an interfaces (that this class implements) containing all transactional methods, so that Spring can use JDK dynamix proxies for this interface?
It works like this
Have a business interface with methods, do not annotate interface methods with #Transactional
Write an implementation class for interface defined above and annotate methods in impl class with #Transactional
As spring recommends usage of JDK dynamic proxies which are interface based hence we need to have business interface in place.
Also, as stated
Java annotations are not inherited from interfaces
We need to annotate concrete / implementation class methods with #Transactional
I am working with proxy-reflection-annotations concept in java. I have created a proxy with Proxy.getInstance method.What I observed is this method takes only interface as parameters. So while using annotations, I can only place annotations on method names in Interface, but I would like to place annotations on methods in implementations of those interfaces.
So how can I achieve this.
Thanks
I have understood that JDKProxy is used when proxying interface via implementation and CBLIB proxy is used via inheritance(subclass extends superclass) proxying.
I am trying to auto generate some EJB service code, which are wrappers around Java DAO classes. DAO classes implement DAO interfaces, but also have their own public methods. This DAO layer is implemented by another team, so I cannot play around with it.
I am using CodeModel API to generate the code. I get each DAO class and want now to create the EJB Service code. Using java reflection I am trying to check if the method declared in the DAO class is an overridden implementing method of the interface or not. Is there anyway in which I can check that?
1) If overridden methods are with #Overridden annotation, than you could iterate through these methods, and check their annotation using this API: http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/reflect/Method.html#getDeclaredAnnotations%28%29
2) If there are no annotations, I think, the only way is to iterate through parent classes and interfaces and compare method signatures, declared there with signatures in your class.
I have a strange behaviour when autowiring
I have a similar code like this one, and it works
#Controller
public class Class1 {
#Autowired
private Class2 object2;
...
}
#Service
#Transactional
public class Class2{
...
}
The problem is that I need that the Class2 implements an interface so I've only changed the Class2 so it's now like:
#Controller
public class Class1 {
#Autowired
private Class2 object2;
...
}
#Service
#Transactional
public class Class2 implements IServiceReference<Class3, Long>{
...
}
public interface IServiceReference<T, PK extends Serializable> {
public T reference(PK id);
}
with this code I get a org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type for Class2.
It seems that #Transitional annotation is not compatible with the interface because if I remove the #Transitional annotation or the implements IServiceReference<Class3, Long> the problem disapears and the bean is injected (though I need to have both in this class). It also happens if I put the annotation #Transitional in the methods instead of in the Class.
I use Spring 3.0.2 if this helps.
Is not compatible the interface with the transactional method?
May it be a Spring bug?
The problem is that your Class1 needs a reference to IServiceReference and not the concrete reference of Class2
#Controller
public class Class1 {
#Autowired
private IServiceReference object2;
...
}
The reason this is that Spring is creating a dynamic proxy for classes that you marked #Transactional. Thus when Class2 is created its wrapped in a Proxy object that is obviously not of type Class2 but is of type IServiceReference.
If you want the behavior of using Class2 with proxy support you will have to turn on CGLIB
Read below:
From Springs Doc:
Spring AOP defaults to using standard
J2SE dynamic proxies for AOP proxies.
This enables any interface (or set of
interfaces) to be proxied.
Spring AOP can also use CGLIB proxies.
This is necessary to proxy classes,
rather than interfaces. CGLIB is used
by default if a business object does
not implement an interface. As it is
good practice to program to interfaces
rather than classes, business classes
normally will implement one or more
business interfaces. It is possible to
force the use of CGLIB, in those
(hopefully rare) cases where you need
to advise a method that is not
declared on an interface, or where you
need to pass a proxied object to a
method as a concrete type.
It is important to grasp the fact that
Spring AOP is proxy-based. See the
section entitled Section 6.6.1,
“Understanding AOP proxies” for a
thorough examination of exactly what
this implementation detail actually
means.
The Transactional annotation instructs Spring to generate proxy objects around the annotated beans, to implement the transactional semantics. The generated proxy will implement the same interfaces as the target bean. So if your target bean implements IServiceReference, then so will the generated proxy.
If the target bean has no implemented interfaces, then the generated proxy will instead be a subclass of the target bean type.
In your original example, the transactional proxy will be a subclass of Class2, because Class2 implemented no interfaces. When you changed Class2 to implement IServiceReference, the generated proxy no longer extended Class2, and instead implemented IServiceReference. This caused your ClassCastException.
The best approach to this situation is to remove the reference from Class1 to Class2, and instead talk to Class2 purely through its interfaces. Class2 can implement as many interfaces as you like, the proxy will implement all of them.
You can force Spring to generate subclass proxies regardless of the interfaces, but it's additional complexity, and I'd recommend against it.
You can force it to proxy by adding
#Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
also see this documentation.