Nzall
Nzall

Reputation: 3555

Using existing Singleton objects for Autowire injection

We use singleton service classes in our application:

public class LevelApprovalServiceImpl extends BaseBusinessServiceImpl implements LevelApprovalService {

    /** There's one and only one instance of this class */
    private static final LevelApprovalServiceImpl INSTANCE = new LevelApprovalServiceImpl();

    /**
     * Constructor is private, use getInstance to get
     * an instance of this class
     */
    private LevelApprovalServiceImpl() {
    }

    /**
     * Returns the singleton instance of this class.
     *
     * @return  the singleton instance of this class.
     */
    public static LevelApprovalServiceImpl getInstance() {
        return INSTANCE;
    }
}

We recently upgraded Spring to Spring 5 and have started using the @Autowired annotation in our controllers:

@RestController
@RequestMapping("/approvals")
public class ApprovalRestController extends BaseRestController {
    @Autowired
    transient private LevelApprovalService levelApprovalService;  
}

The problem is that due to this, our web application currently has 2 instances of every singleton service: the singleton we created ourselves and the singleton created by Spring. autowiring. We'd rather this not be the case and have a single singleton instance for everything.

Is there a way to tell Spring to use the getInstance() method of the singleton while still using Spring annotations to wire things together? Not every service is used in the Spring frontend, so we need to have Spring use our singleton instance instead of the other way around, and we'd rather not have to switch to xml-based configuration or start using a configuration file.

Upvotes: 1

Views: 171

Answers (2)

Nikita Reshotko
Nikita Reshotko

Reputation: 1

You can create add your singleton instance to spring container as bean from configuration class:

@Configuration
public class MyConfig {

    @Bean
    public LevelApprovalServiceImpl service() {
        return LevelApprovalServiceImpl.getInstance();
    }
}

It would be right to choose either native singleton creation or Spring creation, btw your getInstance() is not thread-safe.

Upvotes: 0

Andrew
Andrew

Reputation: 49606

You can define a @Bean method in one of your @Configuration classes.

@Configuration
public class Configuration {

    @Bean
    public LevelApprovalService getLevelApprovalService() {
        return LevelApprovalServiceImpl.getInstance();
    }

}

This way, Spring will always be using the instance you have created.

Upvotes: 2

Related Questions