Какие знаешь аннотации для определения бинов?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
# Аннотации для определения бинов в Spring
В Spring Framework существует множество аннотаций для определения управляемых компонентов (бинов). Рассмотрим основные из них.
1. @Component
Основная аннотация для создания Spring бина. Используется как универсальный маркер для любого управляемого компонента:
@Component
public class MyComponent {
public void doSomething() {
System.out.println("Doing something");
}
}
Spring автоматически обнаружит этот класс при сканировании classpath и создаст бин.
2. @Service
Специализированная аннотация для бизнес-логики. Семантически указывает, что класс содержит бизнес-сервис:
@Service
public class UserService {
public User createUser(String name) {
// бизнес-логика
return new User(name);
}
}
Когда использовать: для классов, содержащих основную бизнес-логику приложения.
3. @Repository
Аннотация для классов, работающих с БД (Data Access Object pattern). Обеспечивает трансляцию исключений БД в Spring DataAccessException:
@Repository
public class UserRepository {
@Autowired
private JdbcTemplate jdbcTemplate;
public User findById(Long id) {
String sql = "SELECT * FROM users WHERE id = ?";
return jdbcTemplate.queryForObject(sql, new UserRowMapper(), id);
}
public void save(User user) {
String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
jdbcTemplate.update(sql, user.getName(), user.getEmail());
}
}
Преимущества:
- PersistenceExceptionTranslator автоматически преобразует проверяемые исключения в unchecked исключения
- Улучшает читаемость кода
4. @Controller
Аннотация для контроллеров в Spring MVC. Обрабатывает HTTP запросы:
@Controller
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/users/{id}")
public String getUser(@PathVariable Long id, Model model) {
User user = userService.findById(id);
model.addAttribute("user", user);
return "user-detail";
}
}
5. @RestController
Комбинация @Controller + @ResponseBody. Используется для REST API, возвращает JSON/XML вместо представления:
@RestController
@RequestMapping("/api/users")
public class UserRestController {
@Autowired
private UserService userService;
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
return userService.findById(id);
}
@PostMapping
public User createUser(@RequestBody UserDTO dto) {
return userService.createUser(dto.getName());
}
@DeleteMapping("/{id}")
public void deleteUser(@PathVariable Long id) {
userService.deleteById(id);
}
}
6. @Configuration
Аннотация для классов, содержащих конфигурацию приложения. Используется вместе с методами, отмеченными @Bean:
@Configuration
public class AppConfig {
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.postgresql.Driver");
dataSource.setUrl("jdbc:postgresql://localhost:5432/mydb");
dataSource.setUsername("user");
dataSource.setPassword("password");
return dataSource;
}
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean
public UserRepository userRepository(JdbcTemplate jdbcTemplate) {
return new UserRepository(jdbcTemplate);
}
}
7. @Bean
Аннотация для методов, которые создают и возвращают управляемые объекты. Используется внутри @Configuration классов:
@Configuration
public class ServiceConfig {
@Bean
public UserService userService() {
return new UserService();
}
@Bean
public UserValidator userValidator() {
return new UserValidator();
}
// Метод можно сделать зависимостью для другого бина
@Bean
public OrderService orderService(UserService userService) {
return new OrderService(userService);
}
}
8. @Conditional
Создать бин только при выполнении определенного условия:
@Component
@ConditionalOnProperty(name = "feature.advanced.enabled", havingValue = "true")
public class AdvancedFeature {
// этот бин будет создан только если feature.advanced.enabled=true
}
@Bean
@ConditionalOnBean(DataSource.class)
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
9. @Scope
Определяет область видимости бина (сколько экземпляров создается):
// Singleton (по умолчанию) - один экземпляр на весь контекст
@Component
@Scope("singleton")
public class SingletonService {}
// Prototype - новый экземпляр при каждом запросе
@Component
@Scope("prototype")
public class PrototypeService {}
// Request scope (только в веб-приложениях)
@Component
@Scope("request")
public class RequestService {}
// Session scope (только в веб-приложениях)
@Component
@Scope("session")
public class SessionService {}
10. @Lazy
Отложенная инициализация бина (создается только при первом использовании):
@Component
@Lazy
public class ExpensiveService {
public ExpensiveService() {
System.out.println("ExpensiveService инициализирована");
}
}
@Service
public class MyService {
@Autowired
@Lazy
private ExpensiveService expensiveService;
// expensiveService будет создана только при первом обращении
}
11. @Primary
Указать, какой бин использовать по умолчанию при наличии нескольких реализаций:
interface DataSource {}
@Component
@Primary
public class PostgresDataSource implements DataSource {}
@Component
public class MySQLDataSource implements DataSource {}
@Service
public class DatabaseService {
private final DataSource dataSource;
// будет внедрен PostgresDataSource (помечен @Primary)
public DatabaseService(DataSource dataSource) {
this.dataSource = dataSource;
}
}
12. @Qualifier
Указать конкретный бин по имени при наличии нескольких реализаций:
@Component("postgresSource")
public class PostgresDataSource implements DataSource {}
@Component("mysqlSource")
public class MySQLDataSource implements DataSource {}
@Service
public class DatabaseService {
private final DataSource dataSource;
// явно указываем, какой бин использовать
public DatabaseService(@Qualifier("mysqlSource") DataSource dataSource) {
this.dataSource = dataSource;
}
}
Иерархия и сравнение основных аннотаций
| Аннотация | Назначение | Область | Примеры |
|---|---|---|---|
@Component | Универсальный компонент | Любой | Utility, Helper классы |
@Service | Бизнес-логика | Слой сервисов | UserService, OrderService |
@Repository | Доступ к данным | Слой доступа | UserRepository, OrderRepository |
@Controller | Обработка HTTP (MVC) | Веб-слой | UserController |
@RestController | REST API | Веб-слой | API контроллеры |
@Configuration | Конфигурация | Конфигурация | AppConfig, SecurityConfig |
@Bean | Создание объектов | Конфигурация | Методы в @Configuration |
Практический пример полной архитектуры
// 1. Сущность
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue
private Long id;
private String name;
private String email;
}
// 2. Repository слой
@Repository
public class UserRepository extends JpaRepository<User, Long> {
User findByEmail(String email);
}
// 3. Service слой
@Service
public class UserService {
private final UserRepository userRepository;
private final MailService mailService;
public UserService(UserRepository userRepository, MailService mailService) {
this.userRepository = userRepository;
this.mailService = mailService;
}
public User registerUser(String name, String email) {
User user = new User();
user.setName(name);
user.setEmail(email);
userRepository.save(user);
mailService.sendWelcomeEmail(email);
return user;
}
}
// 4. Controller слой
@RestController
@RequestMapping("/api/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@PostMapping
public User createUser(@RequestBody UserDTO dto) {
return userService.registerUser(dto.getName(), dto.getEmail());
}
}
// 5. Configuration
@Configuration
public class AppConfig {
// дополнительная конфигурация при необходимости
}
Правильное использование этих аннотаций обеспечивает чистую архитектуру, слабую связанность и высокую тестируемость кода.