I am use Spring in my app, when we have some class that doesn't implements any interface, Spring will use "cglib" to proxy.
Can I change the cglib to other lib in Spring? If yes, How can I do it?
Thanks!
[EDIT]
Hi, I was wanting because I have problems with PermGen when I use CGLIB, the proxys instance are not cleaning when I do hotdeploy.
Yes, I can change for other stretegy, Aspect etc...
Spring only supports JDK (interface only) and CGLIB based (for classes) proxying, and while it's not explicitly mentioned, it also uses Objenesis with CGLIB for proxying classes with no default constructor. Also see their issues regarding this at https://jira.spring.io/browse/SPR-8190 and https://jira.spring.io/browse/SPR-5654 for further reference. That means there's no drop-in replacement or configuration options in Spring to switch to some other proxy creation method.
If you're still willing to explore uncharted territories, the DefaultAopProxyFactory might be a good place to start as it seems it's a central piece of the proxy creation code in Spring, the proxy creator classes use it as a factory through their common superclass ProxyCreatorSupport.
Related
As far as I know whenever I use interfaces for my beans, JDK Dynamic Proxies should be used instead of CGLIB. To be on teh safe side, I make sure I don't even have CGLIB in the classpath of my Spring Boot app.
However, when my controller implements an interface I see this in the stacktrace(never mind the stacktrace rootcause, it was a validation error):
at com.yuranos.documented.api.controllers.BookingControllerImpl.convertToDto(BookingControllerImpl.java:57)
at com.yuranos.documented.api.controllers.BookingControllerImpl.getBookingById(BookingControllerImpl.java:29)
at com.yuranos.documented.api.controllers.BookingControllerImpl$$FastClassBySpringCGLIB$$890fcd8a.invoke(<generated>)
What is even more confusing is that when I remove the interface, this strangely named proxy disappears:
at com.yuranos.documented.api.controllers.BookingControllerImpl.convertToDto(BookingControllerImpl.java:60)
at com.yuranos.documented.api.controllers.BookingControllerImpl.getBookingById(BookingControllerImpl.java:32)
Just for the sake of learning and understanding proxies, I wanted to see the proxy class generated by Spring AOP. It was not present in the classes folder generated by Eclipse.
Can somebody tell me its location?
If you are using interface-based proxies (default), Spring uses Proxy class to create proxy dynamically and in-memory. There is no .class file associated with that class.
When using class-based proxies (via cglib) Spring creates concrete subclasses of your classes. In the debugger you'll notice they are named something like YourRealService$$EnhancerByCGLIB$$... But again, these classes are only generated in-memory and not stored on disk.
If you really want to see AOP under the hood, you will have to use aspectj and compile-time weaving. Way too much work. So the bottom line is: just trust they work. And if they don't: examine stack traces.
I need to look up beans via their class type. When the beans have been wrapped by a Proxy (some methods are #Transactional) - the ApplicatoinContext fails to find them. I find that if I look them up via an interface, it works but in this case I'm working with a concrete class type. I know the bean is of the type I'm looking for but the getBean() method fails.
I can debug (and fix) the problem in Spring's AbstractBeanFactory code. The issue is that it checks the type of the beanInstance against type I'm requesting but the beanInstance.getClass() is a Proxy. AbstractBeanFactory should compensate for this and compare the type to the proxy's target class.
I have a fix for this but I don't particularly want to use a patched version of Spring and I suspect there must be something I can configure to get this working, or is this really a bug?
There are two major ways Spring implements AOP (e.g. #Transactional support): either by using proxy interfaces or CGLIB.
With interfaces (default) if your class implements any interfaces, Spring will create a proxy implementing all that interfaces. From now on you can only work with your bean through that interfaces. Your class is deeply burried inside them.
If you enable proxying target classes instead via cglib:
<aop:config proxy-target-class="true">
Spring will create a subclass (obvoiusly still implementing all your interfaces) instead. This will fix your problem. However remember that the returned object is not really your class but dynamically generated subclass that wraps and delegates to your original object. This shouldn't be a problem in most of the cases.
And no, of course this is not a bug but well known behaviour and no, there is no need to patch Spring.
See also
Location of the proxy class generated by Spring AOP
Getting Spring Error "Bean named 'x' must be of type [y], but was actually of type [$Proxy]" in Jenkins
How to mix CGLIB and JDK proxies in Spring configuration files?
Mocking a property of a CGLIB proxied service not working
<context:component-scan base-package="<Your base package name goes here>" />
<aop:aspectj-autoproxy />
<aop:config proxy-target-class="true"/>
write these three lines in applicationContext.xml this worked for me.
Overview
Using
Spring 3.0.1 (annotation configuration)
Current configuration is using CGLib as proxy creator but this is not my preference
Transactions are annotation configured without any special settings
All configuration is done with annotations (#Service, #Transactional, #ManagedResource, #Inject, etc.)
Hibernate 3.5 (entities are annotated with javax.persistence)
Guidelines highlights
Every bean annotated with #Repository or #Service must have an interface
Constructor DI (when re-configuration isn't required)
Constructor has default visibility (Foo(Bar bar) {...})
Bean fields are final (when re-configuration isn't required)
Leads to no default constructor
Implementations are default visible with final modifier (final class Foo)
The Problem
CGLib can't proxy final classes
CGLib requires default (empty) constructor
Some services are required to be exposed via JMX
MBean exporter can't work unless proxied by CGLib
Some #Transactional #Services are accessed via facade service which requires more than one service to include in the facade transaction (e.g. Observer service over 2 application components)
Some interfaces have more than one implementation (which currently distinguished by #Qualifier)
Future guideline (or nice to have feature) - each application module will have beanRefContext.xml file to configure its internal application context
When I used to work with XML configuration I was able to enforce all the guidelines I presented above, but when switching to annotations it seems like Spring is misbehaving.
Developers in my group prefer annotation configuration (I seems easier to wire and write new code), but I've noticed all kind of "hacks" they introduce to the code to prevent from dealing with Spring application context failures.
The Question(s)
Are there best practices I should follow when using annotation configuration?
When using more than one implementation per interface (trying to reduce the use of #Primary or #Qualifier)
When using #Transactional
When using #ManagedResource
When using a combination of the above
Is there a way of stop working with CGLib, keep the annotation configuration and still be able to export my MBeans with annotations?
What is the suitable implementation for keeping most (preferably, all) of my guidelines?
I came up with the following solution (to questions #2 and #3) to be able to enforce my design guidelines and keep using annotation based configuration:
Each dependent project (Maven module) has it's own ApplicationContext
Every dependent project application context is defined in beanRefContext.xml
These application contexts are loaded in hierarchy using Spring context hierarchy mechanism.
This step is actually not fully supported by Spring and requires additional work
Since my application is layered, I could disable CGLib on all my modules besides the JMX layer (I can live with it :-) ).
The above steps also enabled me to reduce the execution time of Spring aware tests (every module loaded only a sub-set of beans).
As a practical guideline (for question #1), if an interface has more than one implementation, I place #Primary on the widely used one and other clients, requiring another implementation, wire the bean using #Qualifier.
Answer to point 2)
You could use AspectJ instead of CGLib.
I don't know the meaning of using proxy in spring. what is efficient?
Proxies are used by AOP. In short:
Normally you have.
Caller --> Real object
But when, for example, you want automatic transaction management, spring puts a proxy of your real object
Caller --> Proxy --> Real object
where the proxy starts the transaction.
Here is nice article explaining both the essence of proxies and their efficiency (performance) in spring
The dynamic proxy is a feature of the JDK. It can be used to implement an interface using an invocation handler.
A dynamic proxy class (simply referred
to as a proxy class below) is a class
that implements a list of interfaces
specified at runtime when the class is
created, with behavior as described
below. A proxy interface is such an
interface that is implemented by a
proxy class. A proxy instance is an
instance of a proxy class. Each proxy
instance has an associated invocation
handler object, which implements the
interface InvocationHandler.
A dynamic proxy has some overhead. For most use cases the overhead won't be significant, though. The real problem is that the (over)use of dynamic proxies makes an application harder to understand and debug. For example a dynamic proxy will show up with mulitple lines in a stacktrace.
Dynamic proxies are often used to implement decorators. One example of this is AOP in Spring. (I don't want to go into the details of AOP and won't use AOP terminology to keep things simple). Where certain concerns are implemented in one class and used in many places. The dynamic proxies (and invocation handlers) are only the glue code (provided by Spring) to intercept the method calls. (Actually, dynamic proxies are only an implementation detail of this capability. Generating classes on the fly is another possibility to implement it.)
We can add a functionality to Java class by modifying the source/byte code or by using subclass or proxy which embeds the additional functionality and delegates the calls to underlying object.
The other answers are good, but here's how I think of it in very simple terms.
An annotation means "add hidden code for extra behavior."
The framework (or whatever knows what the annotation means) adds bytecode, Spring at runtime, AspectJ at compile time, for example.
It adds code as a proxy along with an interceptor. (A wrapper, decorator, adapter are similar and may be easier to understand than "proxy".)
When the program runs, the interceptor sends execution to the proxy which does its thing, which then may or may not send execution to the class that you coded and that it "wraps".
AOP can also use CGLIB proxies. This is used to proxy the classes instead of interfaces.