54

Is it possible in Spring that a class for bean doesn't have a public constructor but only a private one? Will this private constructor be invoked when the bean is created?

2
  • 8
    How about giving it a try and then posting the results? Commented Aug 31, 2011 at 8:38
  • 1
    It is difficult - I don't have all source. Commented Aug 31, 2011 at 8:40

6 Answers 6

89

Yes, Spring can invoke private constructors. If it finds a constructor with the right arguments, regardless of visibility, it will use reflection to set its constructor to be accessible.

Sign up to request clarification or add additional context in comments.

7 Comments

Could you please give me the reference to docs? Constructor has parameters, and in xml file to this arguments assigned values.
you mean if a bean has specifically something like private bean() { ... } spring can invoke that? How is that possible, that defies the whole purpose of "private".
Sorry, I'm probably wrong about it only being no-arg constructors. I'm just going by what I've noticed on my own projects. I can't say I've ever seen it in the Spring documentation anywhere. But this is the javadoc for the class that is responsible for doing the instantiation. static.springsource.org/spring/docs/3.0.x/javadoc-api/org/…
@Ashkan It is possible using reflection. In particular, the Spring BeanUtils class uses a class called ReflectionUtils to make the constructor accessible. See javadocs for Constructor.setAccessible().
@Kevin Stembridge you are correct, it is possible using Reflection.
|
3

You can always use a factory method to create beans rather than relying on a default constructor, from The IoC container: Instantiation using an instance factory method:

<!-- the factory bean, which contains a method called createInstance() -->
<bean id="serviceLocator" class="com.foo.DefaultServiceLocator">
  <!-- inject any dependencies required by this locator bean -->
</bean>

<!-- the bean to be created via the factory bean -->
<bean id="exampleBean"
      factory-bean="serviceLocator"
      factory-method="createInstance"/>

This has the advantage that you can use non-default constructors for your bean, and the dependencies for the factory method bean can be injected as well.

5 Comments

interesting, but I cannot find factory. May be exists another way?
@Matthew: He appears to be retrofitting Spring around some fugly third-party code. That's just bound to be messy.
@Donal, no I didn't understand what he said in the comment.
Could you please tell what would be the java config equivalent for this xml config please?
Create a @Configuration class with an @Bean method to call the static createInstance() method. That is the Java equivalent of the XML configuration.
3

Yes, Private constructors are invoked by spring. Consider my code:

Bean definition file:

<bean id="message" class="com.aa.testp.Message">
        <constructor-arg index="0" value="Hi Nice"/>
    </bean>

Bean class:

package com.aa.testp;

public class Message {

    private String message;

    private Message(String msg) {
       // You may add your log or print statements to check execution or invocation
        message = msg;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public void display() {
        System.out.println(" Hi " + message);
    }

}

The above code works fine. Hence, spring invoked the private constructor.

1 Comment

Anyone know how to do this using Spring Java configuration (not xml based)?
1

Yes ! Spring can access private constructor. It will works internally like below code.

 try {
    Class clazz = Class.forName("A"); // A - Fully qualified class name
    Constructor constructor[] = clazz.getDeclaredConstructors();
    constructor[0].setAccessible(true);
    A a = (A) constructor[0].newInstance();
 }
 catch (Exception e) {
        e.printStackTrace();
 }

Comments

0

You would normally have a static factory method in such beans, you can specify that method for spring to get an instance of that bean. See 3.3.1.3 here. This is the way it's recommended by Spring, rather than going against visibility restrictions.

7 Comments

strange, there are no static method, no public constructor but when I do debug - private constructor invoked! by sun.reflect.NativeConstructorAccessorImpl
Without specifics/code it won't be possible to comment any further!
I suppose you are wrong. There are no specific code - I see in debugger only standard sun/spring methods.
@Ashkan: I suspect you're getting the -1 votes because you're wrong. Spring can peek behind the curtain (unless there's a strict security manager in place and the Spring code isn't marked as trusted).
@Ashkan: It's very bad style to go against visibility restrictions. Don't do it! Or if you do, feel very bad about it. (Spring does it because it wants to split the definition of a bean from its configuration, but they're typically still closely linked. This question happens to be about the exceptional case where that's not true…)
|
0

Spring will never call private constructor as Bean scope. If do it will through the below error.

Common causes of this problem include using a final class or a non-visible class. Nested exception is

java.lang.IllegalArgumentException: No visible constructors in class.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.