I am reading a book, which talks about enabling AspectJ support in Spring AOP.
Given below is a paragraph taken from the book:
To enable AspectJ annotation support in the Spring IoC container, you only have to define an empty
XML element aop:aspectj-autoproxy in your bean configuration file. Then, Spring will automatically
create proxies for any of your beans that are matched by your AspectJ aspects.
For cases in which interfaces are not available or not used in an application’s design, it’s possible to
create proxies by relying on CGLIB. To enable CGLIB, you need to set the attribute proxy-target-class=true in <aop:aspectj-autoproxy />.
I am not able to get the second paragraph. What is meant by 'interfaces are not available'. Can anyone illustrate this with an example ?
Spring AOP uses either JDK dynamic proxies or CGLIB to create the proxies for your target objects.
According to Spring documentation, in case your target implements at least one interface, a JDK dynamic proxy will be used. However if your target object does not implement any interfaces then a CGLIB proxy will be created.
This is how you can force creation of the CGLIB proxies (set proxy-target-class="true"):
<aop:config proxy-target-class="true">
<!-- other beans defined here... -->
</aop:config>
When using AspectJ and its autopoxy support you can also force CGLIB proxies. This is where the <aop:aspectj-autoproxy> is used and also here the "proxy-target-class" must be set to true:
<aop:aspectj-autoproxy proxy-target-class="true"/>
Please refer to Proxying mechanisms section of Aspect Oriented Programming with Spring documentation for more details.
Spring prefers to use interfaces for AOP because it can use JDK proxies.
Say for example I have an interface MyService
public interface MyService {
void doSomething();
}
And an implementation MyServiceImpl
#Service
public class MyServiceImpl implements MyService {
public void doSomething() {
// does something!
}
}
If Spring discovers that you've configured aspects for MyService, it will create a JDK Proxy that implements MyService and then proxy all calls through to your MyServiceImpl bean, adding aspect functionality where appropriate.
JDK proxies work by implementing the same interface as your target object and delegating calls to it; they do not work if there is no interface to implement. In case you don't have an interface like above, Spring needs to use a byte code library like CGLIB to dynamically create classes at runtime that incorporate the aspect functionality.
I found a blog here that clearly explains how AOP,Caching & Transaction works using runtime proxy classes.
When not coding to interface (quoting from the blog's section 'What if the bean class does not implement any interface?'):-
By default, if your bean does not implement an interface, Spring uses
technical inheritance: at startup time, a new class is created. It
inherits from your bean class and adds behavior in the child methods.
In order to generate such proxies, Spring uses a third party library
called cglib.
Spring AOP makes extensive use of proxies as a mechanism to implement cross-cutting concerns (a.k.a aspects) in a non-intrusive way, the idea basically is use the proxies as wrappers that enrich the original behaviour, i.e. add transactional capabilities.
To achieve this there are two options, depending of whether the original object implements an interface or not.
In the first case (the original object implements at least one interface) the dynamic proxy capabilities of the reflection API are used to create a proxy object that IMPLEMENTS the same interfaces that the original object and therefore the proxy can be used instead.
In the second case (the original object does NOT implement any interface), so a more elaborated trick must be used, and this is when CGLIB appears. According to the project page "CGLIB is used to extend Java classes and implements interfaces at runtime". So in this case the trick consists on create a proxy that EXTENDS the original object and therefore can be used instead.
Related
I have done my research before asking but no luck.
I have a StartUp Singleton bean. In this bean I have an #Inject #Any Instance. I loop all the implementations and try to check if the class is annotated with a custom annotation. All the implementations(all the classes that I want to inspect) are Stateful or Stateless beans.
Sometime the class I want is found and I can perform getClass().isAnnotationPresent(ClassNameAnnotation.class)
Most of the times I get a proxy object and in this case I cannot perform the above check.
I cannot find a way to get the real object. I have tried to get the SuperClass but not luck.
I will attach some of the code so you can have a better idea.
#Singleton
#Startup
public class CacheLoader {
#Inject
#Any
private Instance<ClassNameA> aClasses;
.......
#Lock(LockType.READ)
public void evaluate() {
if (!aClasses.isUnsatisfied()) {
for (ClassNameA className : aClasses) {
if (className.getClass().isAnnotationPresent(ClassNameAnnotation.class)) {
....
}
}
}
}
}
I tried to use the SuperClass of the proxy object but it does not return what I want. I tried also via Proxy.getInvocationHandler(). Even when I check the methods Proxy.isProxyClass(getClass()) or isSynthetic() does not return that the object is a proxy.
Thank you!
I think you would be better served by using a CDI Portable Extension, rather than a Singleton EJB. A couple of reasons
In CDI, everything is a proxy. So like some of the commenters have said, using reflection would be very fragile as it's not part of the spec. You're dealing with classes that are defined at runtime. It may work if you tie yourself to implementation-specific details, but it could break between releases of your CDI container.
The CDI Container will do all of the annotation scanning for you :)
A portable extension runs on startup, before other stuff starts flying around your app
A google search gave me this guide, but there are lots of them: https://www.baeldung.com/cdi-portable-extension
I think you would want to hook in processAnnotatedType() if you're modifying the bean declarations, or afterBeanDiscovery() if you're just documenting them as you said.
We actually have a CDI Portable Extension we use internally that does some config magic for environments. One of the config params is an annotation that is not a qualifier annotation, which sounds like what you want... the CDI container can get you the type, from which you can inspect the annotations.
Finally, this is not directed related to your question but may be useful: If your annotations drive configuration through fields of the annotations, selecting them can be quite complicated because of how the Java type and inheritance system works with annotations. You may benefit by using AnnotationLitreal in those cases. Read up here on this useful utility class here: http://www.kurtsparber.de/?p=387
EDIT:
Another side note... even thought I think you should switch to a Portable Extension, you shouldn't need #EJB's Singleton Startup anymore! you can do this with pure CDI: https://rmannibucau.wordpress.com/2015/03/10/cdi-and-startup/
Spring creates the class objects by Java dynamic proxies (java.lang.reflect.Proxy). i.e
#Component
public class NewsService implements Service{
}
But how the member variables are injected by Spring? ie
#Autowired
private EntityManager em;
Java dynamic proxies uses interface (i.e Service) to create the objects. But how member variables are injected? The instance variables are not known by interface.
Also when member instances are injected? Load time?(When containing class object is created?) or Lazy loading? (when object is used first?)
Few facts for you:
Spring instantiates specific classes, not interfaces. Dependency injection is done on the original bean instance.
When a proxy is created, Spring registers both the original bean and its proxy in the application context. JDK proxy is created for all interfaces implemented by the original bean.
Proxies are not created if they are not necessary (i.e. no aspect is applied on the target bean).
All beans are eagerly initialized by default. If you want some bean to be instantiated in a lazy fashion, you need to specify it explicitly.
Dependency injection happens right after the bean is instantiated. Some dependencies are injected based on the bean definition, other dependencies might be injected by various bean post processors (but they are executed right away as well).
How is dependency injection realized:
When using XML configuration or autowiring , dependency injection is done via Reflection API. Spring is able to either call property setter (setFoo(...)) or set field value directly (reflection allows setting private members).
When using #Bean methods in Java configuration, dependency injection is done by your method.
A bit on proxies:
JDK proxies and CGLIB proxies are two different proxying mechanisms. JDK creates artificial class based on provided interfaces, whereas CGLIB creates artificial subclass of the target class.
Which proxying mechanism is used depends on your Spring configuration (JDK is the default one). For obvious reasons JDK proxy can be used only in cases when your dependencies are referenced only by interface. From the other side you can not use CGLIB proxying for final 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.
We have a class which implements several interfaces. We would like to add some pointcut for the entire class - not for a particular interface of it.
How it can be done with Spring AOP? Is it possible to apply an aspect to non-interface class?
Yes, you have to use CGLIB to proxy classes. See section 7.1.3 of the spring docs
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.
The magic is to define proxy-target-class via the following...
<aop:config proxy-target-class="true">
<!-- other beans defined here... -->
</aop:config>