← Назад к вопросам

Будут ли созданы два разных экземпляра бина, если два класса используют один и тот же бин

1.8 Middle🔥 201 комментариев
#Spring Boot и Spring Data#Spring Framework

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Создание экземпляров Spring бинов при совместном использовании

Нет, не будут созданы два разных экземпляра. Spring создаст ровно один экземпляр бина и внедрит его обоим классам. Это называется Singleton паттерн — дефолтное поведение Spring контейнера.

Singleton Scope (по умолчанию)

@Configuration
public class AppConfig {
    @Bean
    public UserService userService() {
        return new UserService();
    }
}

@Component
public class OrderController {
    @Autowired
    private UserService userService;  // Получит ОДИН экземпляр
}

@Component
public class PaymentService {
    @Autowired
    private UserService userService;  // ТОТ ЖЕ экземпляр, что выше
}

Оба класса получат ссылку на один и тот же объект UserService. Это подтвердить через equals и hashCode:

public class BeanSingletonTest {
    @Test
    public void testBeanIsSingleton(ApplicationContext context) {
        UserService service1 = context.getBean(UserService.class);
        UserService service2 = context.getBean(UserService.class);
        
        assertTrue(service1 == service2);  // Один и тот же объект в памяти
    }
}

Когда нужны разные экземпляры

Если нужны разные экземпляры, используй scope "prototype":

@Component
@Scope("prototype")
public class UserService {
    // ...
}

Теперь каждый вызов getBean() или @Autowired создаст новый экземпляр:

@Test
public void testBeanIsPrototype(ApplicationContext context) {
    UserService service1 = context.getBean(UserService.class);
    UserService service2 = context.getBean(UserService.class);
    
    assertFalse(service1 == service2);  // Разные объекты
}

Другие Scopes

  • singleton (по умолчанию) — один экземпляр на всё приложение
  • prototype — новый экземпляр каждый раз
  • request (в web приложениях) — новый для каждого HTTP запроса
  • session (в web приложениях) — новый для каждой пользовательской сессии
  • application — один на весь ServletContext
  • websocket — один на WebSocket сессию

Практическое применение

В моём опыте singleton использовался для:

  • Stateless сервисов (UserService, OrderService)
  • Компонентов с дорогостоящей инициализацией
  • Репозиториев и DAO

Prototype использовался для:

  • Объектов с состоянием, специфичным для одного использования
  • Event объектов
  • Временных контейнеров данных

Важные нюансы

  1. Thread Safety — Singleton должны быть thread-safe, так как используются одновременно разными потоками
  2. Lazy Initialization — Singleton создаются при первом обращении (если не указано иное)
  3. Circular Dependencies — с prototype сложнее решать циклические зависимости

Проверка типа скопа

public class BeanScopeChecker implements ApplicationContextAware {
    @Override
    public void setApplicationContext(ApplicationContext context) {
        ConfigurableApplicationContext appContext = (ConfigurableApplicationContext) context;
        ConfigurableBeanFactory factory = appContext.getBeanFactory();
        String scope = factory.getBeanDefinition("userService").getScope();
        System.out.println("Scope: " + scope);  // singleton или prototype
    }
}

Итак, при совместном использовании одного бина двумя классами Spring гарантирует, что оба получат ссылку на один и тот же singleton экземпляр, если явно не указано другое через @Scope("prototype").

Будут ли созданы два разных экземпляра бина, если два класса используют один и тот же бин | PrepBro