Внедрение зависимости в Вашу Singleton

У меня есть одиночный элемент, который имеет введенный Дао пружины (упрощенный ниже):

public class MyService<T> implements Service<T> {
    private final Map<String, T> objects;
    private static MyService instance;

    MyDao myDao;

    public void set MyDao(MyDao myDao) {
        this. myDao = myDao;
    }

    private MyService() {
        this.objects = Collections.synchronizedMap(new HashMap<String, T>());
        // start a background thread that runs for ever
    }

    public static synchronized MyService getInstance() {
        if(instance == null) {
            instance = new MyService();
        }
        return instance;
    }

    public void doSomething() {
        myDao.persist(objects);
    }
}

Моя пружинная конфигурация будет, вероятно, похожа на это:

 <bean id="service" class="MyService" factory-method="getInstance"/>

Но это инстанцирует MyService во время запуска.

Существует ли программный способ сделать, внедрение зависимости MyDao в MyService, но не иметь пружину управляют MyService?

В основном я хочу смочь сделать это из своего кода:

MyService.getInstance().doSomething();

в то время как наличие пружины вводит MyDao для меня.

6
задан Langali 18 May 2010 в 20:10
поделиться

3 ответа

Как упоминалось другими, вы должны позволить Spring управлять своими синглтонами, но если вы хотите управлять ими самостоятельно и просто позволяете Spring вводить зависимости, сделайте следующее:

applicationContext.getAutowireCapableBeanFactory().autowireBean(yourService);
0
ответ дан 17 December 2019 в 02:25
поделиться

Если вам нужен синглтон, почему бы просто не определить этот класс в конфигурациях Spring, и он автоматически синглтон (по умолчанию).

Чтобы избежать инициализации при запуске, смотрели ли вы на Spring отложенную инициализацию ? В основном вам нужно:

lazy-init="true"

в определении вашего bean-компонента.

2
ответ дан 17 December 2019 в 02:25
поделиться

Я считаю, что интерфейс FactoryBean - хорошая альтернатива для вас. Это очень хороший выбор, когда вам нужно выполнить некоторую логику инициализации. Например, для запуска базы данных в памяти или некоторых фоновых процессов в отдельных потоках.

Подробнее об этом можно прочитать в справочной документации .

Пример, демонстрирующий, как я создаю экземпляр базы данных и возвращаю источник данных каждый раз, когда кому-то нужен bean-компонент из реализации FactoryBean.

@PostConstruct
void init() {
    embeddedDatabase = new EmbeddedDatabaseBuilder().addScript(schemaPath)
         .addScript(dataPath).setType(embeddedDatabaseType).build();
}


public DataSource getObject() throws Exception {
    return embeddedDatabase;
}

Это обеспечивает слабую связь между фабричной логикой и возвращаемым объектом. Он активно используется фреймворком Spring внутри.

Если вы хотите, чтобы он инициализировался при первом использовании, установите для lazy-initialization значение true.

Другой альтернативой, если вы хотите, чтобы ваш код взаимодействовал с контейнером Spring, является создание фабрики, реализующей интерфейс ApplicationContextAware . Тогда вы можете сделать что-то вроде этого:

myDao = context.getBean(MyDao.class);
0
ответ дан 17 December 2019 в 02:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: