New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Create CGLIB proxy instances honoring <constructor-arg> tags [SPR-3150] #7836
Comments
Juergen Hoeller commented We do generally not support CGLIB proxies for classes that do not have default constructors, neither for standard AOP proxies nor for scoped proxies. (Well, to be exact, we do internally, but we're not exposing this functionality to applications.) Creating proxy instances with constructor arguments will usually lead to the proxy class internally initializing state, which is very undesirable. In general, only use CGLIB proxy classes that allow for 'stateless' construction. In your case, I would strongly recommend to use <aop:scoped-proxy proxy-target-class="false"/> for such a bean, in particular since ArrayBlockingQueue implements a BlockingQueue interface anyway! Juergen |
Bruno Navert commented Point taken. I was forced to use CGLIB proxies due to another bug in 2.0.0, but that bug has since been fixed in 2.0.3 so it's not an issue anymore. |
Kent Tong commented Having a constructor that takes arguments does NOT imply that the object is stateful. For example, one singleton bean could refer to another singleton bean using constructor injection. On the other hand, even if a default constructor is used, it is possible to be stateful (eg, establishing a DB connection in that constructor). With the current behavior, it is impossible to create a CGLIB proxy for it if constructor injection is used. Therefore, I'd suggest change this behavior and give a warning in the documentation that the constructor will be executed twice. |
Tomasz Nurkiewicz commented This limitation is even more annoying when working with Scala:
Here I can inject dependencies via constructor and not only Scala compiler will automatically create private fields for each injected dependency, but also these fields will be final. However when CGLIB proxy is used I am forced to add dummy c-tor and keep it in sync with the primary one:
|
Oleg Alexeyev commented It basically means that constructor injection doesn't work if AOP is enabled and an object doesn't implement interfaces. Or do I miss something? This is now exactly the problem I faced with. And now have to get back to setter injection or create an interface, which don't really need. |
Ilya Kazakevich commented Regular project has a lot of services. Most of them have final fields with pointers to other services. All of them are created using [constructor-arg] in xml. Now I need to wrap them to implement logging and I do not want to use AspectJ weaving. That works perfectly in CGLIB, so nothing prevents you from doing it. You only need to pass arguments to CGLIB. BTW, you do have "Cglib2AopProxy#setConstructorArguments", why not to use it? |
Przemysław Pokrywka commented Kent, Tomasz, Oleg and Ilya had a valid point. Even parameterless constructors can have side-effects, so clear warning in the docs would be useful. And with the warning in place there's no longer need to annoy users of constructor-based injection. Spring was meant to be agnostic about setter/constructor injection, wasn't it? |
Andrzej Winnicki commented Przemysław is right. Constructor injection is becoming more and more popular. We need either clear warning in the docs: you can't use constructor-injection with CGLIB and AOP, or have this issue fixed. |
Juergen Hoeller commented Let's consider this fixed as of 4.0 RC1, since #15223 introduced an ObjenesisCglibAopProxy that bypasses constructor invocation for a CGLIB proxy instance altogether, avoiding any kind of side effect from constructor invocation (even in case of a default constructor). This is used by default with an embedded version of Objenesis in Spring Framework 4.0 now. Juergen |
Bruno Navert opened SPR-3150 and commented
This problem was encountered with Snapshot build 98 of version 2.0.3.
The following bean definition of a custom-scoped bean (the class is a backport of JDK 1.5's java.util.concurrent.ArrayBlockingQueue to work on JDK 1.4):
Failed with the error below. The class in question has no empty constructor, it needs an integer value, which is specified by <constructor-arg>.
I am using CGLib 2.1.3 (the one that ships with Hibernate 3.2.1)
This problem does not occur in version 2.0.0
Affects: 2.0.3
Issue Links:
15 votes, 19 watchers
The text was updated successfully, but these errors were encountered: