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

Что нужно сделать с методом класса с аннотацией Bean, чтобы Spring его увидел?

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

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

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

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

Использование аннотации @Bean в Spring

@Bean — это аннотация в Spring Framework, которая указывает, что метод производит bean, управляемый контейнером Spring. Однако для того чтобы Spring увидел и зарегистрировал этот bean, необходимо выполнить несколько требований.

Основное требование: @Configuration класс

Метод с аннотацией @Bean должен находиться внутри класса, помеченного аннотацией @Configuration.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {
    
    // Spring обнаружит и зарегистрирует этот bean
    @Bean
    public UserService userService() {
        return new UserService();
    }
    
    @Bean
    public UserRepository userRepository() {
        return new UserRepository();
    }
}

Почему нужен @Configuration?

Класс с аннотацией @Configuration служит источником определений bean для Spring. Spring сканирует такие классы и вызывает методы, помеченные @Bean, чтобы получить instances бинов.

Сканирование компонентов

Spring должен обнаружить сам класс @Configuration. Для этого нужно:

  1. Использовать @ComponentScan — явно указать пакеты для сканирования
@Configuration
@ComponentScan(basePackages = {"com.example.config", "com.example.service"})
public class AppConfig {
    @Bean
    public UserService userService() {
        return new UserService();
    }
}
  1. Или положить класс в базовый пакет приложения
// com.example.Application - main класс
@SpringBootApplication  // включает @ComponentScan на текущий пакет
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

// com.example.config.AppConfig - будет обнаружен автоматически
@Configuration
public class AppConfig {
    @Bean
    public UserService userService() {
        return new UserService();
    }
}

Зависимости между beans

Для использования других бинов в методе @Bean нужно передать их как параметры:

@Configuration
public class AppConfig {
    
    @Bean
    public UserRepository userRepository() {
        return new UserRepository();
    }
    
    // Spring автоматически внедрит userRepository
    @Bean
    public UserService userService(UserRepository userRepository) {
        return new UserService(userRepository);
    }
    
    // Можно внедрять несколько зависимостей
    @Bean
    public UserController userController(
            UserService userService,
            UserRepository userRepository) {
        return new UserController(userService, userRepository);
    }
}

Именование бинов

По умолчанию имя бина совпадает с именем метода. Можно изменить через параметр name:

@Configuration
public class AppConfig {
    
    @Bean(name = "customUserService")
    public UserService userService() {
        return new UserService();
    }
    
    // Несколько имён для одного бина
    @Bean(name = {"userService", "mainService"})
    public UserService getUserService() {
        return new UserService();
    }
}

// Использование бина по имени
@Service
public class OrderService {
    
    @Autowired
    @Qualifier("customUserService")
    private UserService userService;
}

Scope бинов

По умолчанию бины имеют scope singleton (один экземпляр на приложение). Можно изменить через @Scope:

@Configuration
public class AppConfig {
    
    // Singleton - по умолчанию
    @Bean
    public UserService singletonService() {
        return new UserService();
    }
    
    // Prototype - новый экземпляр каждый раз
    @Bean
    @Scope("prototype")
    public UserContext userContext() {
        return new UserContext();
    }
    
    // Request scope - новый для каждого HTTP запроса
    @Bean
    @Scope("request")
    public RequestData requestData() {
        return new RequestData();
    }
}

Условная регистрация бинов

@Configuration
public class AppConfig {
    
    // Бин регистрируется только если свойство true
    @Bean
    @ConditionalOnProperty(name = "feature.enabled", havingValue = "true")
    public FeatureService featureService() {
        return new FeatureService();
    }
    
    // Бин регистрируется только если класса нет в classpath
    @Bean
    @ConditionalOnMissingBean(EmailService.class)
    public EmailService defaultEmailService() {
        return new DefaultEmailService();
    }
    
    // Бин регистрируется только если другой бин существует
    @Bean
    @ConditionalOnBean(UserRepository.class)
    public UserService userService(UserRepository userRepository) {
        return new UserService(userRepository);
    }
}

Инициализация и уничтожение

@Configuration
public class AppConfig {
    
    @Bean
    public UserService userService() {
        return new UserService();
    }
    
    // Методы инициализации и уничтожения
    @Bean(initMethod = "init", destroyMethod = "cleanup")
    public Database database() {
        return new Database();
    }
}

public class Database {
    public void init() {
        System.out.println("Database initialized");
    }
    
    public void cleanup() {
        System.out.println("Database cleanup");
    }
}

// Или через PostConstruct / PreDestroy
public class DatabaseV2 {
    
    @PostConstruct
    public void init() {
        System.out.println("Database initialized");
    }
    
    @PreDestroy
    public void cleanup() {
        System.out.println("Database cleanup");
    }
}

Примеры реальных конфигураций

@Configuration
public class DataSourceConfig {
    
    // Конфигурация DataSource
    @Bean
    public DataSource dataSource() {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl("jdbc:postgresql://localhost:5432/mydb");
        config.setUsername("user");
        config.setPassword("password");
        config.setMaximumPoolSize(10);
        return new HikariDataSource(config);
    }
    
    // Конфигурация JdbcTemplate
    @Bean
    public JdbcTemplate jdbcTemplate(DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
    
    // Конфигурация RestTemplate
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

@Configuration
public class SecurityConfig {
    
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        return http
            .csrf().disable()
            .authorizeRequests()
                .requestMatchers("/public/**").permitAll()
                .anyRequest().authenticated()
            .and()
            .httpBasic()
            .and()
            .build();
    }
}

Лучшие практики

  1. Используйте @Configuration для создания бинов

    • Это явно указывает, что класс содержит определения бинов
  2. Передавайте зависимости через параметры метода

    • Spring автоматически разрешит их
  3. Используйте значимые имена методов

    • Это станет именем бина по умолчанию
  4. Разделяйте конфигурацию по темам

    • Один класс для database конфигурации, другой для security
  5. Используйте условную регистрацию

    • @ConditionalOnProperty, @ConditionalOnBean для гибкости
  6. Явно указывайте scope для non-singleton бинов

    • Это предотвращает неожиданное поведение

При правильной конфигурации Spring легко обнаружит и зарегистрирует все ваши бины.