Ответ
Spring Framework предоставляет три основных подхода к конфигурации бинов (управляемых объектов), от классического до современного.
1. Конфигурация с помощью аннотаций (Рекомендуемый современный подход)
Основан на автоматическом сканировании классов и использовании аннотаций.
-
Объявление бина: Используются стереотипные аннотации. Spring обнаруживает их при включенном сканировании (
@ComponentScan).@Component // Универсальный бин @Service // Бин бизнес-логики (семантический аналог @Component) @Repository // Бин уровня доступа к данным (добавляет трансляцию исключений) @Controller / @RestController // Бин веб-уровня (MVC/REST) public class MyService { ... } -
Внедрение зависимостей (Dependency Injection - DI):
@Service public class OrderService { // 1. Внедрение через поле (Field Injection) - менее предпочтительно @Autowired private PaymentService paymentService; // 2. Внедрение через конструктор (Constructor Injection) - РЕКОМЕНДУЕТСЯ private final UserRepository userRepo; @Autowired // Необязательно с Spring 4.3+, если конструктор один public OrderService(UserRepository userRepo) { this.userRepo = userRepo; } // 3. Внедрение через сеттер (Setter Injection) private NotificationService notifier; @Autowired public void setNotifier(NotificationService notifier) { this.notifier = notifier; } }
2. Java-based конфигурация (@Configuration и @Bean)
Позволяет явно объявлять бины в Java-классах. Полезно для настройки сторонних библиотек или сложной логики создания бина.
@Configuration
public class AppConfig {
@Bean // Объявляет метод как фабрику бина. Имя бина = имя метода.
public DataSource dataSource() {
return new HikariDataSource(...); // Создание и настройка сложного объекта
}
@Bean
public OrderService orderService(UserRepository repo) {
// Spring автоматически внедрит бин UserRepository как параметр
return new OrderService(repo);
}
}
3. XML-конфигурация (Устаревший, но поддерживаемый подход)
<beans>
<!-- Объявление бина -->
<bean id="myRepository" class="com.example.MyRepositoryImpl"/>
<!-- Внедрение зависимости -->
<bean id="myService" class="com.example.MyService">
<constructor-arg ref="myRepository"/> <!-- Через конструктор -->
<!-- или -->
<property name="repository" ref="myRepository"/> <!-- Через сеттер -->
</bean>
</beans>
Ключевые моменты:
@Autowiredавтоматически связывает бины по типу. Для разрешения неоднозначности используется@Qualifier("beanName").- Область видимости (Scope) бина задается аннотацией
@Scope(например,"singleton"(по умолчанию),"prototype","request","session"). - Современные приложения обычно используют комбинацию
@ComponentScan(для своих классов) и@Bean(для внешней конфигурации).
Ответ 18+ 🔞
Слушай, а вот Spring Framework, он же, блядь, как шведский стол — подходи и выбирай, как тебе твои бины настраивать. Три способа, от дедовского XML до современной магии с аннотациями. Сейчас разжую, только не подавись.
Первый, самый модный — через аннотации (все эти @Component, @Service)
Вот это, блядь, магия чистой воды. Вместо того чтобы в XML-файлах, как в каменном веке, прописывать каждую сущность, ты просто пишешь над классом волшебное слово. Spring сканирует проект, видит эти аннотации и сам, охуев от такой наглости, создаёт из них бины.
@Component // Универсальный бин, типа "создай из этого класса бин, нахуй"
@Service // То же самое, но для сервисов (семантический сахар, блядь)
@Repository // Для работы с данными (ещё и исключения ловит, хитрая жопа)
@Controller // Для веба, чтобы запросы обрабатывать
public class MyService { ... }
А чтобы один бин в другой запихнуть (это называется Dependency Injection, или "впендюрить зависимость"), есть тоже варианты:
@Service
public class OrderService {
// Способ 1: Внедрение в поле. Быстро, но говнисто. Не видно зависимостей, тестировать неудобно.
@Autowired
private PaymentService paymentService;
// Способ 2: Внедрение через конструктор. Вот это, ёпта, красота! РЕКОМЕНДУЮ.
private final UserRepository userRepo; // final, Карл! Безопасно и понятно.
@Autowired // А эту аннотацию можно и не писать, если конструктор один — Spring и так догадается.
public OrderService(UserRepository userRepo) {
this.userRepo = userRepo;
}
// Способ 3: Через сеттер. Ну, на любителя. Бывает нужно.
private NotificationService notifier;
@Autowired
public void setNotifier(NotificationService notifier) {
this.notifier = notifier;
}
}
Второй способ — Java-based конфигурация (@Configuration)
Бывает, класс не твой (из библиотеки) или бин нужно собрать по сложной схеме, как шкаф из Икеи. Вот тут и выручает @Configuration. Ты сам, своими руками, в коде говоришь Spring'у: "Создай бин вот таким, блядь, способом".
@Configuration // Говорит: "В этом классе лежат рецепты бинов, читай внимательно"
public class AppConfig {
@Bean // Метод, который возвращает объект. Spring вызовет его и результат засунет в контекст.
public DataSource dataSource() {
return new HikariDataSource(...); // Вот тебе, Spring, настрой пул соединений сам!
}
@Bean
public OrderService orderService(UserRepository repo) { // Смотри-ка, параметр! Spring сам подставит нужный бин.
return new OrderService(repo); // Конструируем сервис вручную.
}
}
Третий — XML. Устаревший, но как памятник архитектуры.
Этим, блядь, пугают junior'ов. Всё вручную, тегами. Выглядит как древние скрижали.
<beans>
<!-- Объявляем бин, типа "возьми этот класс и сделай из него бин с именем myRepository" -->
<bean id="myRepository" class="com.example.MyRepositoryImpl"/>
<!-- А теперь создаём сервис и засовываем в него репозиторий -->
<bean id="myService" class="com.example.MyService">
<constructor-arg ref="myRepository"/> <!-- Пропихнули через конструктор -->
<!-- или так, через сеттер -->
<property name="repository" ref="myRepository"/>
</bean>
</beans>
А теперь, блядь, ключевые моменты, чтобы не облажаться:
@Autowiredищет бин по типу. Если нашёл два бина одного типа — будет конфликт, пиздец. Спасёт@Qualifier("имя_бина"), он уточнит, какой именно.- Область видимости (Scope). По умолчанию бин — синглтон (один на весь мир). Но можно сделать
"prototype"(новый при каждом запросе),"request"(на время HTTP-запроса). Задаётся аннотацией@Scope. - В нормальном, недопетухом проекте используют гибрид: свои классы помечают
@Component(или его производными), а для настройки всяких внешних библиотек — пишут@Configurationклассы с@Bean. XML оставь для поддержки легаси-кода, которому, блядь, больше лет, чем тебе.