1

I am studying for the Spring Core certification and I have the following doubt related how can Spring instantiate classes with private constructors (such as Singleton pattern) or how can instantiate objects from Factories (that are not the Spring context).

For example I have the following singleton factory:

public class AccountServiceSingleton implements AccountService {

    private static AccountServiceSingleton inst = new AccountServiceSingleton();

    private AccountServiceSingleton() { ... }

    public static AccountService getInstance() {
        // ...
        return inst;
    }
}

This is a singleton factory because it build a private static object builded with a private constructor and I have a public method to get this object.

So I think that the problem how can Spring build this object? depends on the fact that that the constructor is private so I can't do something like this in my Java configuration class

@Confguration
public class ApplicationConfig{

    @Bean
    public AccountServiceSingleton accountServiceSingleton(){
        return new AccountServiceSingleton();
    }
}

because I can't access to the private AccountServiceSingleton() constructor.

At the same time I can't use the equivalent XML configuration for the same reason.

Have I understand what is the problem or am I missing something?

I think that I am missing something because on the documentation I read that I can use the following 2 solutions for the previous problem:

  1. Use a @Bean method in @Configuration class: so, reading it, I think that the previous Java configuration class work...but why?

  2. XML factory-method attribute in the XML configuration, searching online I found that have to be something like this, but how can I use this to configure the previous AccountServiceSingleton bean in an XML configuration?

Tnx

AndreaNobili
  • 40,955
  • 107
  • 324
  • 596
  • 2
    To answer the titular question: [Reflection](https://docs.oracle.com/javase/tutorial/reflect/). Also, just because a class has a private constructor doesn't mean it's automatically a singleton, there's plenty of other reasons why you might want to make a constructor private. – JonK Nov 19 '14 at 11:06
  • You may also want to look at some of the answers [here](http://stackoverflow.com/questions/2637864/singleton-design-pattern-vs-singleton-beans-in-spring-container) – JonK Nov 19 '14 at 11:12

3 Answers3

4

It's really easy, and you can do it, too:

Constructor cxor = AccountServiceSingleton.class.getDeclaredConstructor();
cxor.setAccessible(true);
return cxor.newInstance();
Marko Topolnik
  • 195,646
  • 29
  • 319
  • 436
  • 1
    `getConstructor` will not consider private constructors; use `getDeclaredConstructor()` instead: http://stackoverflow.com/a/8249415/190596 – Stijn Geukens Feb 01 '17 at 08:42
2

I found the answer by myself still reading the documentation. I think that the right answer for the question is:

If I want to configure this class as a Spring bean:

public class AccountServiceSingleton implements AccountService {

    private static AccountServiceSingleton inst = new AccountServiceSingleton();

    private AccountServiceSingleton() { ... }

    public static AccountService getInstance() {
        // ...
        return inst;
    }
}

using the Java configuration I simply have to annotate the relative bean method using @Bean in the configuration class.

If I want configure the beans using the XML configuration I have to use the factory method attribute, something like it:

<bean id=“accountService” class=“com.acme.AccountServiceSingleton” 
      factory-method="getInstance" />

So it say that the getInstance() method will be call to obtain the singleton object from my singleton factory

AndreaNobili
  • 40,955
  • 107
  • 324
  • 596
0

How about doing like this:

@Confguration
public class ApplicationConfig{

    @Bean
    public AccountServiceSingleton accountServiceSingleton(){
        return AccountServiceSingleton.getInstance();
    }
}
gamedo
  • 141
  • 1
  • 1
  • 8