Dependency Injection (DI, Внедрение зависимостей) — это одна из ключевых концепций Spring Framework, которая позволяет управлять зависимостями между компонентами приложения. Вместо того чтобы объекты сами создавали свои зависимости, Spring берет на себя ответственность за создание и внедрение этих зависимостей. Это делает код более модульным, тестируемым и легко поддерживаемым.
DI является частью более широкой концепции IoC. Вместо того чтобы объекты сами управляли своими зависимостями, управление передается контейнеру Spring. Контейнер Spring создает объекты, управляет их жизненным циклом и внедряет зависимости.
В Spring объекты, которые управляются контейнером, называются бинами (beans). Бин — это объект, который создается, настраивается и управляется Spring IoC-контейнером.
ApplicationContext
— это интерфейс, который представляет Spring IoC-контейнер. Он отвечает за создание, настройку и управление бинами.
Spring поддерживает несколько способов внедрения зависимостей:
Зависимости передаются через конструктор класса. Это предпочтительный способ, так как он обеспечивает неизменяемость зависимостей и упрощает тестирование.
@Service
public class UserService {
private final UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
Зависимости передаются через сеттер-методы. Этот способ менее предпочтителен, так как делает зависимости изменяемыми.
@Service
public class UserService {
private UserRepository userRepository;
@Autowired
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
Зависимости внедряются напрямую в поля класса с помощью аннотации @Autowired
. Этот способ не рекомендуется, так как затрудняет тестирование и скрывает зависимости.
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
}
Spring автоматически сканирует классы в указанных пакетах и регистрирует их как бины, если они помечены аннотациями, такими как @Component
, @Service
, @Repository
, @Controller
.
@ComponentScan(basePackages = "com.example")
public class AppConfig {
}
Spring автоматически связывает бины на основе их типов. Если в контексте Spring есть только один бин определенного типа, он будет автоматически внедрен.
@Autowired
private UserRepository userRepository;
Если есть несколько бинов одного типа, можно использовать аннотацию @Qualifier
для указания конкретного бина.
@Autowired
@Qualifier("userRepositoryImpl")
private UserRepository userRepository;
Зависимости можно настроить с помощью Java-кода, используя аннотацию @Bean
в классах, помеченных @Configuration
.
@Configuration
public class AppConfig {
@Bean
public UserRepository userRepository() {
return new UserRepositoryImpl();
}
}
Хотя этот способ устарел, Spring всё ещё поддерживает конфигурацию через XML.
<bean id="userRepository" class="com.example.UserRepositoryImpl"/>
<bean id="userService" class="com.example.UserService">
<constructor-arg ref="userRepository"/>
</bean>
Spring управляет жизненным циклом бина, включая его создание, инициализацию и уничтожение. Вы можете настроить методы инициализации и уничтожения с помощью аннотаций @PostConstruct
и @PreDestroy
.
@Service
public class UserService {
@PostConstruct
public void init() {
// Логика инициализации
}
@PreDestroy
public void destroy() {
// Логика уничтожения
}
}
@Component
, @Service
, @Repository
, @Controller
.@Configuration
, @Bean
) или XML.Использование DI в Spring делает код более модульным, тестируемым и легко поддерживаемым, что является одной из причин популярности этого фреймворка.