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

Какими обладаешь знаниями в Spring

1.3 Junior🔥 161 комментариев
#Soft Skills и карьера#Spring Framework

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

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

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

Знания в Spring Framework: Полный обзор

Spring Ecosystem

Spring — не один фреймворк, а целая экосистема проектов:

Spring Ecosystem
├─ Spring Framework (Core)
│  ├─ Core Container (IoC, DI)
│  ├─ Aspect-Oriented Programming (AOP)
│  ├─ Data Access / Transaction Management
│  └─ Web Framework (Spring MVC, WebFlux)
├─ Spring Boot (Production-ready)
├─ Spring Cloud (Microservices)
├─ Spring Data (Data access)
├─ Spring Security (Authentication & Authorization)
├─ Spring Integration (Message-driven apps)
└─ Spring Batch (Batch processing)

1. Spring Core (IoC Container)

Inversion of Control (IoC)

// Без Spring: управляем зависимостями сами
public class UserService {
    private UserRepository userRepository;
    private EmailService emailService;
    
    public UserService() {
        // Мы создаём зависимости вручную
        this.userRepository = new UserRepository();
        this.emailService = new EmailService();
    }
}

// Проблемы: сложно тестировать, меняется в одном месте -> нужно обновлять везде

// С Spring: Spring управляет зависимостями
@Service
public class UserService {
    private final UserRepository userRepository;
    private final EmailService emailService;
    
    // Spring IoC контейнер создаёт и внедряет бины
    public UserService(UserRepository userRepository, 
                       EmailService emailService) {
        this.userRepository = userRepository;
        this.emailService = emailService;
    }
}

// Spring бины (beans):
@Service
public class UserService { }

@Repository
public class UserRepository { }

@Component
public class EmailService { }

// Spring автоматически создаёт экземпляры и связывает их

Dependency Injection

// Three ways to inject dependencies:

// 1. Constructor Injection (рекомендуется)
@Service
public class OrderService {
    private final UserRepository userRepository;
    private final PaymentGateway paymentGateway;
    
    public OrderService(UserRepository userRepository, 
                        PaymentGateway paymentGateway) {
        this.userRepository = userRepository;
        this.paymentGateway = paymentGateway;
    }
}

// 2. Setter Injection (устаревает)
@Service
public class OrderService {
    private UserRepository userRepository;
    
    @Autowired
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}

// 3. Field Injection (анти-паттерн)
@Service
public class OrderService {
    @Autowired
    private UserRepository userRepository; // Сложнее тестировать
}

Bean Lifecycle

// Bean проходит через несколько этапов:

@Component
public class MyBean implements InitializingBean, DisposableBean {
    
    // 1. Constructor
    public MyBean() {
        System.out.println("1. Constructor called");
    }
    
    // 2. Setter injection (если есть)
    
    // 3. InitializingBean
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("3. InitializingBean.afterPropertiesSet()");
    }
    
    // 4. @PostConstruct
    @PostConstruct
    public void init() {
        System.out.println("4. @PostConstruct");
    }
    
    // 5. Bean is ready to use
    public void doSomething() {
        System.out.println("5. Bean in use");
    }
    
    // 6. @PreDestroy
    @PreDestroy
    public void cleanup() {
        System.out.println("6. @PreDestroy");
    }
    
    // 7. DisposableBean
    @Override
    public void destroy() throws Exception {
        System.out.println("7. DisposableBean.destroy()");
    }
}

Bean Scopes

// 1. Singleton (default)
@Scope("singleton")
@Component
public class SingletonService { }
// Один экземпляр на весь ApplicationContext

// 2. Prototype
@Scope("prototype")
@Component
public class PrototypeService { }
// Новый экземпляр каждый раз

// 3. Request (Web)
@Scope("request")
@Component
public class RequestService { }
// Новый экземпляр на каждый HTTP запрос

// 4. Session (Web)
@Scope("session")
@Component
public class SessionService { }
// Новый экземпляр на каждую HTTP сессию

// 5. Application (Web)
@Scope("application")
@Component
public class ApplicationService { }
// Один экземпляр на весь ServletContext

2. Spring Web MVC

Controllers

@RestController
@RequestMapping("/api/users")
public class UserController {
    
    private final UserService userService;
    
    public UserController(UserService userService) {
        this.userService = userService;
    }
    
    // GET /api/users
    @GetMapping
    public List<User> getAll() {
        return userService.findAll();
    }
    
    // GET /api/users/{id}
    @GetMapping("/{id}")
    public User getById(@PathVariable Long id) {
        return userService.findById(id);
    }
    
    // POST /api/users
    @PostMapping
    public ResponseEntity<User> create(@RequestBody CreateUserRequest request) {
        User user = userService.create(request.getName(), request.getEmail());
        return ResponseEntity.status(HttpStatus.CREATED).body(user);
    }
    
    // PUT /api/users/{id}
    @PutMapping("/{id}")
    public User update(@PathVariable Long id, @RequestBody UpdateUserRequest request) {
        return userService.update(id, request.getName());
    }
    
    // DELETE /api/users/{id}
    @DeleteMapping("/{id}")
    public ResponseEntity<?> delete(@PathVariable Long id) {
        userService.delete(id);
        return ResponseEntity.noContent().build();
    }
}

Request/Response Handling

// Request body
@PostMapping
public User create(@RequestBody User user) { }

// Path variable
@GetMapping("/{id}")
public User getById(@PathVariable Long id) { }

// Query parameter
@GetMapping
public List<User> search(@RequestParam String name) { }
// GET /api/users?name=John

// Request header
@GetMapping
public User get(@RequestHeader("X-User-Id") String userId) { }

// Response status
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public User create(@RequestBody User user) { }

// ResponseEntity (full control)
@GetMapping("/{id}")
public ResponseEntity<User> get(@PathVariable Long id) {
    return ResponseEntity
        .ok()
        .header("X-Custom-Header", "value")
        .body(user);
}

3. Spring Data JPA

Repository Pattern

// Интерфейс
public interface UserRepository extends JpaRepository<User, Long> {
    
    // Spring генерирует реализацию автоматически
    User findByEmail(String email);
    
    List<User> findByAgeGreaterThan(int age);
    
    @Query("SELECT u FROM User u WHERE u.email LIKE %:email%")
    List<User> searchByEmail(@Param("email") String email);
    
    @Modifying
    @Query("UPDATE User u SET u.active = true WHERE u.id = :id")
    void activate(@Param("id") Long id);
}

// Использование
@RestController
public class UserController {
    
    private final UserRepository userRepository;
    
    public UserController(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
    
    public User getByEmail(String email) {
        return userRepository.findByEmail(email);
    }
}

JPA Relationships

// One-to-Many
@Entity
public class User {
    @Id
    private Long id;
    private String name;
    
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
    private Set<Order> orders;
}

@Entity
public class Order {
    @Id
    private Long id;
    
    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;
}

// Many-to-Many
@Entity
public class User {
    @ManyToMany
    @JoinTable(
        name = "user_roles",
        joinColumns = @JoinColumn(name = "user_id"),
        inverseJoinColumns = @JoinColumn(name = "role_id")
    )
    private Set<Role> roles;
}

4. Spring Transaction Management

@Transactional

@Service
public class OrderService {
    
    private final OrderRepository orderRepository;
    private final InventoryService inventoryService;
    
    // Весь метод выполняется в одной транзакции
    @Transactional
    public void createOrder(Order order) {
        // 1. Сохраняем заказ
        orderRepository.save(order);
        
        // 2. Уменьшаем инвентарь
        inventoryService.reserve(order.getItems());
        
        // Если ошибка -> всё откатывается (rollback)
        // Если успех -> всё коммитится
    }
    
    // Read-only транзакция (оптимизация для чтения)
    @Transactional(readOnly = true)
    public Order getOrder(Long id) {
        return orderRepository.findById(id).orElse(null);
    }
    
    // Не требует транзакции
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void logAction(String action) {
        // ...
    }
}

5. Spring AOP (Aspect-Oriented Programming)

Aspects

// Logging Aspect
@Aspect
@Component
public class LoggingAspect {
    
    // Применяется ко всем методам в Service классах
    @Around("execution(* com.example.service.*Service.*(..))")
    public Object logMethodExecution(ProceedingJoinPoint joinPoint) 
            throws Throwable {
        
        String methodName = joinPoint.getSignature().getName();
        long start = System.currentTimeMillis();
        
        try {
            Object result = joinPoint.proceed(); // Вызов оригинального метода
            
            long duration = System.currentTimeMillis() - start;
            System.out.println(methodName + " executed in " + duration + "ms");
            
            return result;
        } catch (Exception e) {
            System.err.println(methodName + " failed: " + e.getMessage());
            throw e;
        }
    }
}

// Используется автоматически
@Service
public class UserService {
    public User getUser(Long id) {
        // Будет залогирован автоматически
    }
}

6. Spring Security

Authentication & Authorization

// Configuration
@Configuration
@EnableWebSecurity
public class SecurityConfig {
    
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/public/**").permitAll()
                .antMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            .and()
            .formLogin()
                .loginPage("/login")
                .defaultSuccessUrl("/home")
            .and()
            .logout()
                .logoutSuccessUrl("/login");
        
        return http.build();
    }
    
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

// Usage
@RestController
public class UserController {
    
    @PostMapping("/login")
    public ResponseEntity<?> login(@RequestBody LoginRequest request) {
        // Spring Security обрабатывает аутентификацию
    }
    
    @GetMapping("/admin")
    public String adminOnly() {
        // Доступно только ADMIN
        return "Admin content";
    }
    
    @GetMapping("/profile")
    public User getProfile(@AuthenticationPrincipal UserDetails userDetails) {
        // Получить текущего пользователя
        return userRepository.findByUsername(userDetails.getUsername());
    }
}

7. Spring Boot

Auto-configuration

// Вместо сотен конфигов нужен просто:
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

// application.properties
spring.datasource.url=jdbc:mysql://localhost/mydb
spring.datasource.username=root
spring.datasource.password=password
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true

// Spring Boot автоматически создаёт:
// - DataSource
// - EntityManagerFactory
// - TransactionManager
// - Embedded Tomcat
// - Jackson для JSON
// - Logging
// - И ещё 100 компонентов

Properties & YAML

# application.yml
spring:
  application:
    name: my-app
  datasource:
    url: jdbc:mysql://localhost/mydb
    username: root
    password: password
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
  jackson:
    serialization:
      write-dates-as-timestamps: false

logging:
  level:
    root: INFO
    com.example: DEBUG
  pattern:
    console: "%d %5p %40c{1.} : %m%n"

8. Spring Cloud

Microservices

// Service Discovery (Eureka)
@SpringBootApplication
@EnableEurekaClient
public class UserServiceApplication { }

// Inter-service communication (Feign)
@FeignClient(name = "order-service")
public interface OrderServiceClient {
    @GetMapping("/api/orders/{userId}")
    List<Order> getUserOrders(@PathVariable Long userId);
}

// Circuit Breaker (Hystrix/Resilience4j)
@Service
public class OrderService {
    
    private final OrderServiceClient orderServiceClient;
    
    @CircuitBreaker(name = "orderService")
    public List<Order> getUserOrders(Long userId) {
        return orderServiceClient.getUserOrders(userId);
    }
}

9. Spring Test

Testing

// Unit Test
@Test
public void testUserCreation() {
    UserService service = new UserService(mockRepository);
    User user = service.create("john@example.com", "John");
    assertEquals("John", user.getName());
}

// Integration Test
@SpringBootTest
public class UserServiceIntegrationTest {
    
    @Autowired
    private UserService userService;
    
    @Autowired
    private UserRepository userRepository;
    
    @Test
    @Transactional
    public void testCompleteFlow() {
        User user = userService.create("alice@example.com", "Alice");
        User fromDB = userRepository.findByEmail("alice@example.com");
        assertEquals(user.getName(), fromDB.getName());
    }
}

// Mocking
@WebMvcTest(UserController.class)
public class UserControllerTest {
    
    @Autowired
    private MockMvc mockMvc;
    
    @MockBean
    private UserService userService;
    
    @Test
    public void testGetUser() throws Exception {
        User user = new User(1L, "John", "john@example.com");
        Mockito.when(userService.getUser(1L)).thenReturn(user);
        
        mockMvc.perform(get("/api/users/1"))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.name").value("John"));
    }
}

10. Advanced Topics

Profiles

// Different configs for different environments
@Configuration
@Profile("development")
public class DevConfig {
    @Bean
    public DataSource dataSource() {
        return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.H2)
            .build();
    }
}

@Configuration
@Profile("production")
public class ProdConfig {
    @Bean
    public DataSource dataSource() {
        return createProductionDataSource();
    }
}

// application-dev.properties
# development specific config

// application-prod.properties
# production specific config

Conditional Beans

@Configuration
public class ConditionalConfig {
    
    @Bean
    @ConditionalOnProperty(name = "feature.cache.enabled", havingValue = "true")
    public CacheManager cacheManager() {
        return new CaffeineCacheManager();
    }
    
    @Bean
    @ConditionalOnClass(RedisTemplate.class)
    public RedisConnectionFactory redisConnectionFactory() {
        return new LettuceConnectionFactory();
    }
}

Ключевые концепции

✅ IoC Container — управление объектами
✅ DI — внедрение зависимостей
✅ AOP — сквозная функциональность
✅ MVC — разделение ответственности
✅ Data Access — работа с БД
✅ Transaction Management — ACID гарантии
✅ Security — аутентификация и авторизация
✅ Testing — качество кода
✅ Boot — быстрый старт
✅ Cloud — микросервисы

Вывод

Spring ecosystem решает основные задачи:

  • Dependency Injection — управление зависимостями
  • Web Development — REST API, MVC
  • Data Access — ORM через JPA
  • Security — аутентификация и авторизация
  • Testing — unit и integration тесты
  • Microservices — облачные приложения

Best Practices:

  • Constructor injection (не field injection)
  • Service-Repository pattern
  • Использовать Spring Boot для нового проекта
  • Писать тесты (Unit + Integration)
  • Использовать Spring Security для защиты
  • DRY и Single Responsibility Principle

Spring — индустриальный стандарт для Java веб-разработки.

Какими обладаешь знаниями в Spring | PrepBro