17.Spring Boot的Bean详解(新手版)

发布于:2025-07-10 ⋅ 阅读:(22) ⋅ 点赞:(0)

文章目录

1. 什么是Bean?从零开始理解

1.1 Bean的定义

Bean是Spring框架中的核心概念。简单来说,Bean就是一个由Spring容器创建、管理和维护的Java对象。

举个生活化的例子:
想象你住在一个高级公寓(Spring容器),公寓管理员(Spring容器)负责:

  • 为你准备房间(创建Bean对象)
  • 提供水电服务(注入依赖)
  • 维护房间设施(管理Bean生命周期)
  • 处理房间之间的关系(Bean之间的依赖)

1.2 为什么需要Bean?

在传统Java开发中,我们需要手动创建和管理对象:

// 传统方式 - 手动管理对象
public class TraditionalExample {
    public static void main(String[] args) {
        // 手动创建数据库连接
        DatabaseConnection dbConnection = new DatabaseConnection("localhost", 3306, "user", "password");
        
        // 手动创建数据访问对象
        UserDao userDao = new UserDao(dbConnection);
        
        // 手动创建服务对象
        UserService userService = new UserService(userDao);
        
        // 手动创建控制器
        UserController userController = new UserController(userService);
        
        // 如果有很多对象,管理起来会很复杂!
    }
}

使用Spring Bean后:

// Spring方式 - 自动管理对象
@RestController
public class UserController {
    
    @Autowired  // Spring自动注入
    private UserService userService;
    
    // 不需要手动创建UserService,Spring会自动处理
}

@Service
public class UserService {
    
    @Autowired  // Spring自动注入
    private UserDao userDao;
    
    // 不需要手动创建UserDao,Spring会自动处理
}

1.3 Bean vs 普通对象的区别

特性 普通Java对象 Spring Bean
创建方式 new关键字手动创建 Spring容器自动创建
生命周期管理 开发者手动管理 Spring容器自动管理
依赖注入 手动传递参数 Spring自动注入
单例管理 需要手动实现 Spring提供多种作用域
配置管理 硬编码或手动读取配置 Spring自动读取配置

2. Spring容器:Bean的家

2.1 什么是Spring容器?

Spring容器就像一个智能的对象工厂,它负责:

  1. 创建对象:根据配置创建Bean实例
  2. 管理依赖:自动注入Bean之间的依赖关系
  3. 控制生命周期:管理Bean的创建、初始化、使用和销毁
  4. 提供服务:为应用程序提供所需的Bean

2.2 容器的工作流程

// 1. Spring Boot启动时扫描注解
@SpringBootApplication  // 这个注解告诉Spring开始扫描
public class MyApplication {
    public static void main(String[] args) {
        // 2. 启动Spring容器
        SpringApplication.run(MyApplication.class, args);
        // 3. 容器开始创建和管理Bean
    }
}

// 4. Spring发现这个类有@Service注解,创建Bean
@Service
public class UserService {
    // 5. Spring创建UserService的实例并放入容器中
}

// 6. Spring发现需要注入UserService的地方,自动注入
@RestController
public class UserController {
    @Autowired
    private UserService userService;  // 7. Spring自动注入
}

3. Bean的声明方式详解

3.1 使用@Component及其专门化注解

3.1.1 @Component - 通用组件
// 最基础的Bean声明方式
@Component
public class EmailSender {
    
    public void sendEmail(String to, String subject, String body) {
        System.out.println("发送邮件到: " + to);
        System.out.println("主题: " + subject);
        System.out.println("内容: " + body);
    }
}

// 使用这个Bean
@Service
public class NotificationService {
    
    @Autowired
    private EmailSender emailSender;  // Spring会自动注入EmailSender
    
    public void sendWelcomeEmail(String userEmail) {
        emailSender.sendEmail(userEmail, "欢迎", "欢迎注册我们的网站!");
    }
}
3.1.2 @Service - 业务逻辑层
// @Service表示这是一个服务层的Bean
@Service
public class UserService {
    
    @Autowired
    private UserRepository userRepository;
    
    // 注册新用户
    public User registerUser(String username, String email, String password) {
        // 1. 检查用户是否已存在
        if (userRepository.existsByUsername(username)) {
            throw new RuntimeException("用户名已存在");
        }
        
        // 2. 创建新用户
        User user = new User();
        user.setUsername(username);
        user.setEmail(email);
        user.setPassword(encryptPassword(password));
        
        // 3. 保存用户
        return userRepository.save(user);
    }
    
    // 获取用户信息
    public User getUserById(Long id) {
        return userRepository.findById(id)
            .orElseThrow(() -> new RuntimeException("用户不存在"));
    }
    
    // 密码加密(简化示例)
    private String encryptPassword(String password) {
        return "encrypted_" + password;
    }
}
3.1.3 @Repository - 数据访问层
// @Repository表示这是一个数据访问层的Bean
@Repository
public class UserRepository {
    
    // 模拟数据库存储
    private List<User> users = new ArrayList<>();
    private Long nextId = 1L;
    
    // 保存用户
    public User save(User user) {
        if (user.getId() == null) {
            user.setId(nextId++);
        }
        
        // 如果是更新操作,先删除旧的
        users.removeIf(u -> u.getId().equals(user.getId()));
        users.add(user);
        
        System.out.println("用户已保存: " + user.getUsername());
        return user;
    }
    
    // 根据ID查找用户
    public Optional<User> findById(Long id) {
        return users.stream()
                .filter(user -> user.getId().equals(id))
                .findFirst();
    }
    
    // 检查用户名是否存在
    public boolean existsByUsername(String username) {
        return users.stream()
                .anyMatch(user -> user.getUsername().equals(username));
    }
    
    // 查找所有用户
    public List<User> findAll() {
        return new ArrayList<>(users);
    }
    
    // 根据用户名查找
    public Optional<User> findByUsername(String username) {
        return users.stream()
                .filter(user -> user.getUsername().equals(username))
                .findFirst();
    }
}
3.1.4 @Controller和@RestController - 控制层
// @RestController = @Controller + @ResponseBody
// 表示这是一个RESTful API控制器
@RestController
@RequestMapping("/api/users")  // 基础路径
public class UserController {
    
    @Autowired
    private UserService userService;
    
    @Autowired
    private NotificationService notificationService;
    
    // 注册新用户
    @PostMapping("/register")
    public ResponseEntity<String> registerUser(@RequestBody UserRegistrationRequest request) {
        try {
            // 1. 调用服务层注册用户
            User user = userService.registerUser(
                request.getUsername(), 
                request.getEmail(), 
                request.getPassword()
            );
            
            // 2. 发送欢迎邮件
            notificationService.sendWelcomeEmail(user.getEmail());
            
            // 3. 返回成功响应
            return ResponseEntity.ok("用户注册成功: " + user.getUsername());
            
        } catch (Exception e) {
            // 4. 处理异常
            return ResponseEntity.badRequest().body("注册失败: " + e.getMessage());
        }
    }
    
    // 获取用户信息
    @GetMapping("/{id}")
    public ResponseEntity<User> getUser(@PathVariable Long id) {
        try {
            User user = userService.getUserById(id);
            return ResponseEntity.ok(user);
        } catch (Exception e) {
            return ResponseEntity.notFound().build();
        }
    }
    
    // 获取所有用户
    @GetMapping
    public ResponseEntity<List<User>> getAllUsers() {
        // 这里为了演示,直接调用Repository
        // 实际项目中应该通过Service层
        return ResponseEntity.ok(userService.getAllUsers());
    }
}

// 用户注册请求的数据模型
public class UserRegistrationRequest {
    private String username;
    private String email;
    private String password;
    
    // 构造函数
    public UserRegistrationRequest() {}
    
    // Getter和Setter方法
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    
    public String getPassword() { return password; }
    public void setPassword(String password) { this.password = password; }
}
3.1.5 用户实体类
// 用户实体类
public class User {
    private Long id;
    private String username;
    private String email;
    private String password;
    private LocalDateTime createdAt;
    
    // 构造函数
    public User() {
        this.createdAt = LocalDateTime.now();
    }
    
    public User(String username, String email, String password) {
        this();
        this.username = username;
        this.email = email;
        this.password = password;
    }
    
    // Getter和Setter方法
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    
    public String getPassword() { return password; }
    public void setPassword(String password) { this.password = password; }
    
    public LocalDateTime getCreatedAt() { return createdAt; }
    public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
    
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", email='" + email + '\'' +
                ", createdAt=" + createdAt +
                '}';
    }
}

3.2 Bean名称自定义

// 默认Bean名称是类名首字母小写
@Service  // Bean名称: userService
public class UserService {
}

// 自定义Bean名称
@Service("myUserService")  // Bean名称: myUserService
public class UserService {
}

@Component("emailSender")  // Bean名称: emailSender
public class EmailSender {
}

// 在其他地方通过名称注入
@RestController
public class UserController {
    
    @Autowired
    @Qualifier("myUserService")  // 通过名称指定要注入的Bean
    private UserService userService;
}

4. 使用@Bean注解创建Bean

4.1 什么时候使用@Bean?

当你需要:

  1. 配置第三方库的对象
  2. 需要复杂的创建逻辑
  3. 根据条件创建不同的Bean
  4. 配置系统组件

4.2 基础@Bean使用

@Configuration  // 表示这是一个配置类
public class AppConfig {
    
    // 创建数据库连接Bean
    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC");
        dataSource.setUsername("root");
        dataSource.setPassword("password");
        
        System.out.println("数据源Bean已创建");
        return dataSource;
    }
    
    // 创建Redis连接Bean
    @Bean
    public JedisPool jedisPool() {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(100);  // 最大连接数
        config.setMaxIdle(20);    // 最大空闲连接数
        config.setMinIdle(5);     // 最小空闲连接数
        
        return new JedisPool(config, "localhost", 6379);
    }
    
    // 创建邮件发送器Bean
    @Bean
    public JavaMailSender mailSender() {
        JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
        mailSender.setHost("smtp.qq.com");
        mailSender.setPort(587);
        mailSender.setUsername("your-email@qq.com");
        mailSender.setPassword("your-password");
        
        Properties props = mailSender.getJavaMailProperties();
        props.put("mail.transport.protocol", "smtp");
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.starttls.enable", "true");
        
        return mailSender;
    }
}

4.3 Bean之间的依赖

@Configuration
public class ServiceConfig {
    
    // 创建数据库服务Bean
    @Bean
    public DatabaseService databaseService(DataSource dataSource) {
        // Spring会自动注入dataSource参数
        return new DatabaseService(dataSource);
    }
    
    // 创建缓存服务Bean
    @Bean
    public CacheService cacheService(JedisPool jedisPool) {
        return new CacheService(jedisPool);
    }
    
    // 创建用户服务Bean,依赖于数据库服务和缓存服务
    @Bean
    public UserService userService(DatabaseService databaseService, CacheService cacheService) {
        UserService userService = new UserService();
        userService.setDatabaseService(databaseService);
        userService.setCacheService(cacheService);
        return userService;
    }
}

// 数据库服务类
public class DatabaseService {
    private DataSource dataSource;
    
    public DatabaseService(DataSource dataSource) {
        this.dataSource = dataSource;
        System.out.println("DatabaseService初始化完成");
    }
    
    public void saveUser(User user) {
        System.out.println("保存用户到数据库: " + user.getUsername());
        // 实际的数据库操作
    }
}

// 缓存服务类
public class CacheService {
    private JedisPool jedisPool;
    
    public CacheService(JedisPool jedisPool) {
        this.jedisPool = jedisPool;
        System.out.println("CacheService初始化完成");
    }
    
    public void cacheUser(User user) {
        System.out.println("缓存用户信息: " + user.getUsername());
        // 实际的缓存操作
    }
}

4.4 条件化Bean创建

@Configuration
public class ConditionalConfig {
    
    // 只在开发环境创建的Bean
    @Bean
    @Profile("dev")  // 只在dev配置文件激活时创建
    public DataSource devDataSource() {
        System.out.println("创建开发环境数据源");
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setUrl("jdbc:h2:mem:devdb");  // 内存数据库
        return dataSource;
    }
    
    // 只在生产环境创建的Bean
    @Bean
    @Profile("prod")  // 只在prod配置文件激活时创建
    public DataSource prodDataSource() {
        System.out.println("创建生产环境数据源");
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setUrl("jdbc:mysql://prod-server:3306/proddb");
        return dataSource;
    }
    
    // 根据配置属性创建Bean
    @Bean
    @ConditionalOnProperty(name = "app.cache.enabled", havingValue = "true")
    public CacheManager cacheManager() {
        System.out.println("缓存已启用,创建缓存管理器");
        return new ConcurrentMapCacheManager("users", "products");
    }
}

5. 依赖注入详解

5.1 什么是依赖注入?

依赖注入(Dependency Injection,DI)是一种设计模式,它允许我们在对象外部创建对象的依赖关系,然后将这些依赖关系"注入"到对象中。

生活化例子:
想象你要做一顿饭:

  • 传统方式:你亲自去买菜、洗菜、切菜,然后做饭
  • 依赖注入方式:有人把洗好切好的菜直接送到你厨房,你只需要专心做饭

5.2 依赖注入的三种方式

5.2.1 构造器注入(推荐)
@Service
public class OrderService {
    
    private final UserService userService;
    private final ProductService productService;
    private final PaymentService paymentService;
    
    // 构造器注入 - 推荐方式
    public OrderService(UserService userService, 
                       ProductService productService, 
                       PaymentService paymentService) {
        this.userService = userService;
        this.productService = productService;
        this.paymentService = paymentService;
        
        System.out.println("OrderService通过构造器注入创建完成");
    }
    
    public Order createOrder(Long userId, Long productId, BigDecimal amount) {
        // 1. 验证用户
        User user = userService.getUserById(userId);
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        
        // 2. 验证产品
        Product product = productService.getProductById(productId);
        if (product == null) {
            throw new RuntimeException("产品不存在");
        }
        
        // 3. 创建订单
        Order order = new Order();
        order.setUserId(userId);
        order.setProductId(productId);
        order.setAmount(amount);
        order.setStatus("CREATED");
        
        // 4. 处理支付
        boolean paymentSuccess = paymentService.processPayment(order);
        if (paymentSuccess) {
            order.setStatus("PAID");
        } else {
            order.setStatus("PAYMENT_FAILED");
        }
        
        return order;
    }
}

// 产品服务
@Service
public class ProductService {
    
    public Product getProductById(Long id) {
        // 模拟查找产品
        Product product = new Product();
        product.setId(id);
        product.setName("示例产品 " + id);
        product.setPrice(new BigDecimal("99.99"));
        return product;
    }
}

// 支付服务
@Service
public class PaymentService {
    
    public boolean processPayment(Order order) {
        System.out.println("处理订单支付: " + order.getId() + ", 金额: " + order.getAmount());
        
        // 模拟支付处理
        try {
            Thread.sleep(1000);  // 模拟网络延迟
            return Math.random() > 0.1;  // 90%成功率
        } catch (InterruptedException e) {
            return false;
        }
    }
}

构造器注入的优点:

  1. 依赖不可变:可以使用final关键字
  2. 保证完整性:对象创建时就有了所有依赖
  3. 便于测试:容易进行单元测试
  4. 避免循环依赖:编译时就能发现问题
5.2.2 Setter注入
@Service
public class NotificationService {
    
    private EmailService emailService;
    private SmsService smsService;
    private PushService pushService;
    
    // Setter注入
    @Autowired
    public void setEmailService(EmailService emailService) {
        this.emailService = emailService;
        System.out.println("EmailService已注入");
    }
    
    @Autowired
    public void setSmsService(SmsService smsService) {
        this.smsService = smsService;
        System.out.println("SmsService已注入");
    }
    
    @Autowired(required = false)  // 可选依赖
    public void setPushService(PushService pushService) {
        this.pushService = pushService;
        System.out.println("PushService已注入");
    }
    
    public void sendNotification(String userId, String message) {
        // 发送邮件通知
        if (emailService != null) {
            emailService.sendEmail(userId, "通知", message);
        }
        
        // 发送短信通知
        if (smsService != null) {
            smsService.sendSms(userId, message);
        }
        
        // 发送推送通知(可选)
        if (pushService != null) {
            pushService.sendPush(userId, message);
        }
    }
}

@Service
public class EmailService {
    public void sendEmail(String to, String subject, String body) {
        System.out.println("发送邮件 - 收件人: " + to + ", 主题: " + subject);
    }
}

@Service
public class SmsService {
    public void sendSms(String phone, String message) {
        System.out.println("发送短信 - 手机号: " + phone + ", 内容: " + message);
    }
}

// 推送服务可能不总是可用
@Service
@ConditionalOnProperty(name = "app.push.enabled", havingValue = "true")
public class PushService {
    public void sendPush(String userId, String message) {
        System.out.println("发送推送 - 用户: " + userId + ", 内容: " + message);
    }
}
5.2.3 字段注入(不推荐,但常见)
@RestController
@RequestMapping("/api/orders")
public class OrderController {
    
    // 字段注入 - 简单但不推荐
    @Autowired
    private OrderService orderService;
    
    @Autowired
    private NotificationService notificationService;
    
    @PostMapping
    public ResponseEntity<String> createOrder(@RequestBody OrderRequest request) {
        try {
            Order order = orderService.createOrder(
                request.getUserId(), 
                request.getProductId(), 
                request.getAmount()
            );
            
            // 发送通知
            notificationService.sendNotification(
                request.getUserId().toString(), 
                "订单创建成功: " + order.getId()
            );
            
            return ResponseEntity.ok("订单创建成功: " + order.getId());
            
        } catch (Exception e) {
            return ResponseEntity.badRequest().body("订单创建失败: " + e.getMessage());
        }
    }
}

// 订单请求DTO
public class OrderRequest {
    private Long userId;
    private Long productId;
    private BigDecimal amount;
    
    // Getter和Setter
    public Long getUserId() { return userId; }
    public void setUserId(Long userId) { this.userId = userId; }
    
    public Long getProductId() { return productId; }
    public void setProductId(Long productId) { this.productId = productId; }
    
    public BigDecimal getAmount() { return amount; }
    public void setAmount(BigDecimal amount) { this.amount = amount; }
}

5.3 解决多个实现的问题

当一个接口有多个实现时,Spring需要知道注入哪一个。

5.3.1 使用@Qualifier
// 支付接口
public interface PaymentProcessor {
    boolean processPayment(BigDecimal amount);
}

// 支付宝实现
@Service("alipayProcessor")
public class AlipayProcessor implements PaymentProcessor {
    @Override
    public boolean processPayment(BigDecimal amount) {
        System.out.println("使用支付宝支付: " + amount);
        return true;
    }
}

// 微信支付实现
@Service("wechatProcessor")
public class WechatPayProcessor implements PaymentProcessor {
    @Override
    public boolean processPayment(BigDecimal amount) {
        System.out.println("使用微信支付: " + amount);
        return true;
    }
}

// 银行卡支付实现
@Service("bankCardProcessor")
public class BankCardProcessor implements PaymentProcessor {
    @Override
    public boolean processPayment(BigDecimal amount) {
        System.out.println("使用银行卡支付: " + amount);
        return true;
    }
}

// 使用特定的支付处理器
@Service
public class PaymentService {
    
    private final PaymentProcessor alipayProcessor;
    private final PaymentProcessor wechatProcessor;
    private final PaymentProcessor bankCardProcessor;
    
    public PaymentService(@Qualifier("alipayProcessor") PaymentProcessor alipayProcessor,
                         @Qualifier("wechatProcessor") PaymentProcessor wechatProcessor,
                         @Qualifier("bankCardProcessor") PaymentProcessor bankCardProcessor) {
        this.alipayProcessor = alipayProcessor;
        this.wechatProcessor = wechatProcessor;
        this.bankCardProcessor = bankCardProcessor;
    }
    
    public boolean processPayment(String paymentType, BigDecimal amount) {
        switch (paymentType.toLowerCase()) {
            case "alipay":
                return alipayProcessor.processPayment(amount);
            case "wechat":
                return wechatProcessor.processPayment(amount);
            case "bank":
                return bankCardProcessor.processPayment(amount);
            default:
                throw new IllegalArgumentException("不支持的支付方式: " + paymentType);
        }
    }
}
5.3.2 使用@Primary
// 设置默认的支付处理器
@Service
@Primary  // 默认使用这个实现
public class DefaultPaymentProcessor implements PaymentProcessor {
    @Override
    public boolean processPayment(BigDecimal amount) {
        System.out.println("使用默认支付方式: " + amount);
        return true;
    }
}

@Service
public class SimplePaymentService {
    
    private final PaymentProcessor paymentProcessor;
    
    // 会自动注入@Primary标记的实现
    public SimplePaymentService(PaymentProcessor paymentProcessor) {
        this.paymentProcessor = paymentProcessor;
    }
    
    public boolean pay(BigDecimal amount) {
        return paymentProcessor.processPayment(amount);
    }
}
5.3.3 注入所有实现
@Service
public class PaymentServiceManager {
    
    private final List<PaymentProcessor> paymentProcessors;
    private final Map<String, PaymentProcessor> processorMap;
    
    // 注入所有PaymentProcessor实现
    public PaymentServiceManager(List<PaymentProcessor> paymentProcessors) {
        this.paymentProcessors = paymentProcessors;
        this.processorMap = new HashMap<>();
        
        // 根据类名建立映射
        for (PaymentProcessor processor : paymentProcessors) {
            String name = processor.getClass().getSimpleName().toLowerCase();
            processorMap.put(name, processor);
        }
        
        System.out.println("发现 " + paymentProcessors.size() + " 个支付处理器");
    }
    
    public List<String> getAvailablePaymentMethods() {
        return new ArrayList<>(processorMap.keySet());
    }
    
    public boolean processPayment(String method, BigDecimal amount) {
        PaymentProcessor processor = processorMap.get(method.toLowerCase());
        if (processor != null) {
            return processor.processPayment(amount);
        } else {
            throw new IllegalArgumentException("不支持的支付方式: " + method);
        }
    }
}

6. Bean的作用域(Scope)

6.1 什么是Bean作用域?

Bean作用域定义了Bean实例的生命周期和可见性。Spring提供了多种作用域来满足不同的需求。

6.2 Singleton作用域(默认)

// 默认就是单例作用域
@Service
public class UserService {
    
    private int counter = 0;
    
    public String getServiceInfo() {
        counter++;
        return "UserService实例: " + this.hashCode() + ", 调用次数: " + counter;
    }
}

// 测试单例特性
@RestController
public class TestController {
    
    @Autowired
    private UserService userService1;
    
    @Autowired
    private UserService userService2;
    
    @GetMapping("/test-singleton")
    public Map<String, String> testSingleton() {
        Map<String, String> result = new HashMap<>();
        
        result.put("service1", userService1.getServiceInfo());
        result.put("service2", userService2.getServiceInfo());
        result.put("same_instance", String.valueOf(userService1 == userService2));
        
        return result;
        // 结果会显示两个服务是同一个实例,counter会持续增加
    }
}

6.3 Prototype作用域

// 每次请求都创建新实例
@Service
@Scope("prototype")  // 或者 @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class TokenGenerator {
    
    private final String token;
    private final LocalDateTime createdAt;
    
    public TokenGenerator() {
        this.token = UUID.randomUUID().toString();
        this.createdAt = LocalDateTime.now();
        System.out.println("创建新的TokenGenerator: " + token);
    }
    
    public String getToken() {
        return token;
    }
    
    public LocalDateTime getCreatedAt() {
        return createdAt;
    }
}

// 使用Prototype Bean
@Service
public class AuthService {
    
    private final ApplicationContext applicationContext;
    
    public AuthService(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }
    
    public String generateNewToken() {
        // 每次调用都会创建新的TokenGenerator实例
        TokenGenerator generator = applicationContext.getBean(TokenGenerator.class);
        return generator.getToken();
    }
}

6.4 Web作用域

6.4.1 Request作用域
// 每个HTTP请求创建一个实例
@Component
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class RequestInfo {
    
    private final String requestId;
    private final LocalDateTime requestTime;
    private final Map<String, Object> attributes;
    
    public RequestInfo() {
        this.requestId = UUID.randomUUID().toString();
        this.requestTime = LocalDateTime.now();
        this.attributes = new HashMap<>();
        System.out.println("创建新的RequestInfo: " + requestId);
    }
    
    public String getRequestId() {
        return requestId;
    }
    
    public LocalDateTime getRequestTime() {
        return requestTime;
    }
    
    public void setAttribute(String key, Object value) {
        attributes.put(key, value);
    }
    
    public Object getAttribute(String key) {
        return attributes.get(key);
    }
    
    public Map<String, Object> getAllAttributes() {
        return new HashMap<>(attributes);
    }
}

// 使用Request作用域Bean
@RestController
public class RequestController {
    
    @Autowired
    private RequestInfo requestInfo;
    
    @GetMapping("/request-info")
    public Map<String, Object> getRequestInfo() {
        requestInfo.setAttribute("endpoint", "/request-info");
        requestInfo.setAttribute("timestamp", LocalDateTime.now().toString());
        
        Map<String, Object> result = new HashMap<>();
        result.put("requestId", requestInfo.getRequestId());
        result.put("requestTime", requestInfo.getRequestTime());
        result.put("attributes", requestInfo.getAllAttributes());
        
        return result;
    }
    
    @GetMapping("/another-endpoint")
    public Map<String, Object> anotherEndpoint() {
        // 同一个请求中,requestInfo是同一个实例
        requestInfo.setAttribute("endpoint", "/another-endpoint");
        
        Map<String, Object> result = new HashMap<>();
        result.put("requestId", requestInfo.getRequestId());
        result.put("message", "这是同一个请求中的另一个端点");
        
        return result;
    }
}
6.4.2 Session作用域
// 每个HTTP会话创建一个实例
@Component
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserSession {
    
    private final String sessionId;
    private final LocalDateTime sessionStart;
    private String username;
    private final Map<String, Object> sessionData;
    
    public UserSession() {
        this.sessionId = UUID.randomUUID().toString();
        this.sessionStart = LocalDateTime.now();
        this.sessionData = new HashMap<>();
        System.out.println("创建新的UserSession: " + sessionId);
    }
    
    public String getSessionId() {
        return sessionId;
    }
    
    public LocalDateTime getSessionStart() {
        return sessionStart;
    }
    
    public String getUsername() {
        return username;
    }
    
    public void setUsername(String username) {
        this.username = username;
    }
    
    public void putData(String key, Object value) {
        sessionData.put(key, value);
    }
    
    public Object getData(String key) {
        return sessionData.get(key);
    }
    
    public boolean isLoggedIn() {
        return username != null;
    }
}

// 使用Session作用域Bean
@RestController
@RequestMapping("/session")
public class SessionController {
    
    @Autowired
    private UserSession userSession;
    
    @PostMapping("/login")
    public Map<String, Object> login(@RequestBody LoginRequest request) {
        // 模拟登录验证
        if ("admin".equals(request.getUsername()) && "password".equals(request.getPassword())) {
            userSession.setUsername(request.getUsername());
            userSession.putData("loginTime", LocalDateTime.now());
            
            Map<String, Object> result = new HashMap<>();
            result.put("success", true);
            result.put("sessionId", userSession.getSessionId());
            result.put("message", "登录成功");
            
            return result;
        } else {
            Map<String, Object> result = new HashMap<>();
            result.put("success", false);
            result.put("message", "用户名或密码错误");
            return result;
        }
    }
    
    @GetMapping("/info")
    public Map<String, Object> getSessionInfo() {
        Map<String, Object> result = new HashMap<>();
        result.put("sessionId", userSession.getSessionId());
        result.put("sessionStart", userSession.getSessionStart());
        result.put("username", userSession.getUsername());
        result.put("isLoggedIn", userSession.isLoggedIn());
        result.put("loginTime", userSession.getData("loginTime"));
        
        return result;
    }
    
    @PostMapping("/logout")
    public Map<String, Object> logout() {
        userSession.setUsername(null);
        userSession.putData("loginTime", null);
        
        Map<String, Object> result = new HashMap<>();
        result.put("success", true);
        result.put("message", "已退出登录");
        
        return result;
    }
}

// 登录请求DTO
public class LoginRequest {
    private String username;
    private String password;
    
    // Getter和Setter
    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }
    
    public String getPassword() { return password; }
    public void setPassword(String password) { this.password = password; }
}

7. Bean的生命周期详解

7.1 Bean生命周期概述

Bean的生命周期包括以下阶段:

  1. 实例化:创建Bean实例
  2. 属性赋值:设置Bean的属性
  3. 初始化:执行初始化方法
  4. 使用:Bean可以被应用程序使用
  5. 销毁:应用关闭时销毁Bean

7.2 生命周期回调方法

7.2.1 使用@PostConstruct和@PreDestroy
@Service
public class DatabaseConnectionService {
    
    private Connection connection;
    private boolean isConnected = false;
    
    // Bean创建后自动调用
    @PostConstruct
    public void initialize() {
        System.out.println("=== Bean初始化开始 ===");
        try {
            // 模拟建立数据库连接
            System.out.println("正在连接到数据库...");
            Thread.sleep(1000); // 模拟连接耗时
            
            // 实际项目中这里会是真实的数据库连接
            this.connection = createConnection();
            this.isConnected = true;
            
            System.out.println("数据库连接已建立");
            System.out.println("=== Bean初始化完成 ===");
            
        } catch (Exception e) {
            System.err.println("数据库连接失败: " + e.getMessage());
        }
    }
    
    // Bean销毁前自动调用
    @PreDestroy
    public void cleanup() {
        System.out.println("=== Bean销毁开始 ===");
        try {
            if (connection != null && isConnected) {
                // 关闭数据库连接
                connection.close();
                System.out.println("数据库连接已关闭");
            }
            
            // 清理其他资源
            System.out.println("清理完成");
            System.out.println("=== Bean销毁完成 ===");
            
        } catch (Exception e) {
            System.err.println("资源清理失败: " + e.getMessage());
        }
    }
    
    public boolean executeQuery(String sql) {
        if (!isConnected) {
            throw new RuntimeException("数据库未连接");
        }
        
        System.out.println("执行SQL: " + sql);
        return true;
    }
    
    // 模拟创建连接
    private Connection createConnection() {
        return new Connection() {
            private boolean closed = false;
            
            @Override
            public void close() {
                this.closed = true;
                isConnected = false;
            }
            
            @Override
            public boolean isClosed() {
                return closed;
            }
            
            // 其他Connection方法的简单实现...
        };
    }
}
7.2.2 实现InitializingBean和DisposableBean接口
@Service
public class CacheService implements InitializingBean, DisposableBean {
    
    private Map<String, Object> cache;
    private boolean cacheEnabled = false;
    
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("=== CacheService初始化 ===");
        
        // 初始化缓存
        this.cache = new ConcurrentHashMap<>();
        
        // 预加载一些数据
        preloadCache();
        
        this.cacheEnabled = true;
        System.out.println("缓存服务已启动,预加载了 " + cache.size() + " 条数据");
    }
    
    @Override
    public void destroy() throws Exception {
        System.out.println("=== CacheService销毁 ===");
        
        if (cache != null) {
            System.out.println("清理缓存数据,共 " + cache.size() + " 条");
            cache.clear();
            cache = null;
        }
        
        this.cacheEnabled = false;
        System.out.println("缓存服务已关闭");
    }
    
    private void preloadCache() {
        // 预加载一些常用数据
        cache.put("app.name", "Spring Boot Demo");
        cache.put("app.version", "1.0.0");
        cache.put("app.author", "Developer");
        
        System.out.println("预加载缓存数据完成");
    }
    
    public void put(String key, Object value) {
        if (!cacheEnabled) {
            throw new RuntimeException("缓存服务未启用");
        }
        cache.put(key, value);
        System.out.println("缓存数据: " + key);
    }
    
    public Object get(String key) {
        if (!cacheEnabled) {
            throw new RuntimeException("缓存服务未启用");
        }
        return cache.get(key);
    }
    
    public boolean containsKey(String key) {
        return cacheEnabled && cache.containsKey(key);
    }
    
    public int size() {
        return cacheEnabled ? cache.size() : 0;
    }
}
7.2.3 使用@Bean的initMethod和destroyMethod
@Configuration
public class ThirdPartyConfig {
    
    @Bean(initMethod = "start", destroyMethod = "stop")
    public ExternalService externalService() {
        ExternalService service = new ExternalService();
        service.setServiceUrl("http://api.example.com");
        service.setApiKey("your-api-key");
        service.setTimeout(5000);
        return service;
    }
}

// 第三方服务类(模拟)
public class ExternalService {
    
    private String serviceUrl;
    private String apiKey;
    private int timeout;
    private boolean isRunning = false;
    
    // 初始化方法
    public void start() {
        System.out.println("=== 启动外部服务 ===");
        System.out.println("服务URL: " + serviceUrl);
        System.out.println("API密钥: " + apiKey);
        System.out.println("超时时间: " + timeout + "ms");
        
        // 模拟启动过程
        try {
            Thread.sleep(500);
            this.isRunning = true;
            System.out.println("外部服务启动成功");
        } catch (InterruptedException e) {
            System.err.println("服务启动失败: " + e.getMessage());
        }
    }
    
    // 销毁方法
    public void stop() {
        System.out.println("=== 关闭外部服务 ===");
        this.isRunning = false;
        System.out.println("外部服务已关闭");
    }
    
    public String callApi(String endpoint, String data) {
        if (!isRunning) {
            throw new RuntimeException("服务未运行");
        }
        
        System.out.println("调用API: " + serviceUrl + endpoint + " 数据: " + data);
        return "API调用成功";
    }
    
    // Getter和Setter方法
    public void setServiceUrl(String serviceUrl) { this.serviceUrl = serviceUrl; }
    public void setApiKey(String apiKey) { this.apiKey = apiKey; }
    public void setTimeout(int timeout) { this.timeout = timeout; }
}

7.3 Bean后置处理器

@Component
public class CustomBeanPostProcessor implements BeanPostProcessor {
    
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof UserService) {
            System.out.println("准备初始化UserService: " + beanName);
            // 可以在这里修改bean的属性
        }
        return bean;
    }
    
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof UserService) {
            System.out.println("UserService初始化完成: " + beanName);
            // 可以在这里返回代理对象
        }
        return bean;
    }
}

8. 高级Bean特性

8.1 懒加载(Lazy Loading)

// 懒加载Bean - 只有在被使用时才创建
@Service
@Lazy
public class HeavyService {
    
    public HeavyService() {
        System.out.println("=== 创建HeavyService ===");
        System.out.println("这是一个重量级服务,初始化需要很长时间...");
        
        // 模拟耗时的初始化过程
        try {
            Thread.sleep(3000);
            System.out.println("HeavyService初始化完成!");
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
    
    public String doHeavyWork() {
        return "执行重量级任务完成";
    }
}

// 使用懒加载Bean
@RestController
public class LazyController {
    
    @Autowired
    @Lazy  // 这里也需要加@Lazy,否则会立即初始化
    private HeavyService heavyService;
    
    @GetMapping("/heavy-work")
    public String doHeavyWork() {
        // 只有当这个方法被调用时,HeavyService才会被创建
        return heavyService.doHeavyWork();
    }
}

8.2 条件化Bean创建

8.2.1 基于配置属性的条件
@Configuration
public class ConditionalBeanConfig {
    
    // 只有当配置文件中cache.enabled=true时才创建
    @Bean
    @ConditionalOnProperty(name = "cache.enabled", havingValue = "true", matchIfMissing = false)
    public CacheManager redisCacheManager() {
        System.out.println("创建Redis缓存管理器");
        // 实际项目中这里会配置Redis
        return new ConcurrentMapCacheManager("users", "products");
    }
    
    // 如果没有配置缓存,则使用内存缓存
    @Bean
    @ConditionalOnProperty(name = "cache.enabled", havingValue = "false", matchIfMissing = true)
    public CacheManager memoryCacheManager() {
        System.out.println("创建内存缓存管理器");
        return new ConcurrentMapCacheManager();
    }
    
    // 基于表达式的条件
    @Bean
    @ConditionalOnExpression("${cache.enabled:false} and '${cache.type}'.equals('redis')")
    public RedisTemplate<String, Object> redisTemplate() {
        System.out.println("创建Redis模板");
        return new RedisTemplate<>();
    }
}
8.2.2 基于类存在的条件
@Configuration
public class ClassBasedConditionalConfig {
    
    // 只有当类路径中存在Redis类时才创建
    @Bean
    @ConditionalOnClass(name = "org.springframework.data.redis.core.RedisTemplate")
    public RedisConnectionFactory redisConnectionFactory() {
        System.out.println("Redis库存在,创建Redis连接工厂");
        // 这里会返回实际的Redis连接工厂
        return new MockRedisConnectionFactory();
    }
    
    // 当某个Bean不存在时才创建
    @Bean
    @ConditionalOnMissingBean(DataSource.class)
    public DataSource defaultDataSource() {
        System.out.println("没有配置数据源,使用默认数据源");
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setUrl("jdbc:h2:mem:testdb");
        return dataSource;
    }
}

// 模拟Redis连接工厂
class MockRedisConnectionFactory implements RedisConnectionFactory {
    // 简化实现
}

8.3 FactoryBean

// 使用FactoryBean创建复杂对象
@Component
public class DatabaseConnectionFactoryBean implements FactoryBean<DatabaseConnection> {
    
    @Value("${database.url:jdbc:h2:mem:testdb}")
    private String url;
    
    @Value("${database.username:sa}")
    private String username;
    
    @Value("${database.password:}")
    private String password;
    
    @Override
    public DatabaseConnection getObject() throws Exception {
        System.out.println("通过FactoryBean创建数据库连接");
        
        // 复杂的对象创建逻辑
        DatabaseConnection connection = new DatabaseConnection();
        connection.setUrl(url);
        connection.setUsername(username);
        connection.setPassword(password);
        
        // 执行连接测试
        if (connection.testConnection()) {
            System.out.println("数据库连接测试成功");
        } else {
            throw new RuntimeException("数据库连接测试失败");
        }
        
        return connection;
    }
    
    @Override
    public Class<?> getObjectType() {
        return DatabaseConnection.class;
    }
    
    @Override
    public boolean isSingleton() {
        return true;  // 返回单例
    }
}

// 数据库连接类
public class DatabaseConnection {
    private String url;
    private String username;
    private String password;
    
    public boolean testConnection() {
        System.out.println("测试数据库连接: " + url);
        // 模拟连接测试
        return true;
    }
    
    public void executeQuery(String sql) {
        System.out.println("执行SQL: " + sql);
    }
    
    // Getter和Setter方法
    public void setUrl(String url) { this.url = url; }
    public void setUsername(String username) { this.username = username; }
    public void setPassword(String password) { this.password = password; }
}

9. 实际应用案例

9.1 构建完整的用户管理系统

// 配置类
@Configuration
@EnableConfigurationProperties(AppProperties.class)
public class UserManagementConfig {
    
    @Bean
    @ConditionalOnProperty(name = "app.security.enabled", havingValue = "true")
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    
    @Bean
    @ConditionalOnProperty(name = "app.security.enabled", havingValue = "false", matchIfMissing = true)
    public PasswordEncoder simplePasswordEncoder() {
        return new SimplePasswordEncoder();
    }
    
    @Bean
    public UserValidator userValidator(AppProperties properties) {
        UserValidator validator = new UserValidator();
        validator.setMinPasswordLength(properties.getMinPasswordLength());
        validator.setRequireEmail(properties.isRequireEmail());
        return validator;
    }
}

// 配置属性类
@ConfigurationProperties(prefix = "app")
@Data
public class AppProperties {
    private Security security = new Security();
    private int minPasswordLength = 6;
    private boolean requireEmail = true;
    
    @Data
    public static class Security {
        private boolean enabled = true;
        private int maxLoginAttempts = 3;
    }
    
    // Getter和Setter方法省略
}

// 简单密码编码器
public class SimplePasswordEncoder implements PasswordEncoder {
    @Override
    public String encode(CharSequence rawPassword) {
        return "simple_" + rawPassword.toString();
    }
    
    @Override
    public boolean matches(CharSequence rawPassword, String encodedPassword) {
        return encodedPassword.equals(encode(rawPassword));
    }
}

// 用户验证器
public class UserValidator {
    private int minPasswordLength = 6;
    private boolean requireEmail = true;
    
    public void validateUser(User user) {
        if (user.getUsername() == null || user.getUsername().trim().isEmpty()) {
            throw new IllegalArgumentException("用户名不能为空");
        }
        
        if (user.getPassword() == null || user.getPassword().length() < minPasswordLength) {
            throw new IllegalArgumentException("密码长度至少" + minPasswordLength + "位");
        }
        
        if (requireEmail && (user.getEmail() == null || user.getEmail().trim().isEmpty())) {
            throw new IllegalArgumentException("邮箱不能为空");
        }
        
        if (user.getEmail() != null && !isValidEmail(user.getEmail())) {
            throw new IllegalArgumentException("邮箱格式不正确");
        }
    }
    
    private boolean isValidEmail(String email) {
        return email.contains("@") && email.contains(".");
    }
    
    // Setter方法
    public void setMinPasswordLength(int minPasswordLength) { this.minPasswordLength = minPasswordLength; }
    public void setRequireEmail(boolean requireEmail) { this.requireEmail = requireEmail; }
}

9.2 增强的用户服务

@Service
@Transactional
public class EnhancedUserService {
    
    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;
    private final UserValidator userValidator;
    private final NotificationService notificationService;
    private final CacheService cacheService;
    
    public EnhancedUserService(UserRepository userRepository,
                              PasswordEncoder passwordEncoder,
                              UserValidator userValidator,
                              NotificationService notificationService,
                              CacheService cacheService) {
        this.userRepository = userRepository;
        this.passwordEncoder = passwordEncoder;
        this.userValidator = userValidator;
        this.notificationService = notificationService;
        this.cacheService = cacheService;
        
        System.out.println("EnhancedUserService创建完成,使用的密码编码器: " + 
                          passwordEncoder.getClass().getSimpleName());
    }
    
    public User registerUser(UserRegistrationRequest request) {
        System.out.println("开始注册用户: " + request.getUsername());
        
        // 1. 创建用户对象
        User user = new User();
        user.setUsername(request.getUsername());
        user.setEmail(request.getEmail());
        user.setPassword(request.getPassword());
        
        // 2. 验证用户信息
        userValidator.validateUser(user);
        
        // 3. 检查用户名是否已存在
        if (userRepository.existsByUsername(request.getUsername())) {
            throw new RuntimeException("用户名已存在: " + request.getUsername());
        }
        
        // 4. 加密密码
        String encodedPassword = passwordEncoder.encode(request.getPassword());
        user.setPassword(encodedPassword);
        
        // 5. 保存用户
        User savedUser = userRepository.save(user);
        
        // 6. 缓存用户信息
        cacheUserInfo(savedUser);
        
        // 7. 发送欢迎通知
        try {
            notificationService.sendWelcomeEmail(savedUser.getEmail());
        } catch (Exception e) {
            System.err.println("发送欢迎邮件失败: " + e.getMessage());
            // 不影响用户注册流程
        }
        
        System.out.println("用户注册成功: " + savedUser.getUsername());
        return savedUser;
    }
    
    public User getUserById(Long id) {
        // 1. 先从缓存查找
        String cacheKey = "user:" + id;
        if (cacheService.containsKey(cacheKey)) {
            System.out.println("从缓存获取用户: " + id);
            return (User) cacheService.get(cacheKey);
        }
        
        // 2. 从数据库查找
        User user = userRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("用户不存在: " + id));
        
        // 3. 放入缓存
        cacheUserInfo(user);
        
        return user;
    }
    
    public boolean authenticateUser(String username, String password) {
        Optional<User> userOpt = userRepository.findByUsername(username);
        if (!userOpt.isPresent()) {
            return false;
        }
        
        User user = userOpt.get();
        return passwordEncoder.matches(password, user.getPassword());
    }
    
    public List<User> getAllUsers() {
        return userRepository.findAll();
    }
    
    public User updateUser(Long id, UserUpdateRequest request) {
        User user = getUserById(id);
        
        if (request.getEmail() != null) {
            user.setEmail(request.getEmail());
        }
        
        if (request.getPassword() != null) {
            userValidator.validateUser(user);  // 验证新信息
            String encodedPassword = passwordEncoder.encode(request.getPassword());
            user.setPassword(encodedPassword);
        }
        
        User updatedUser = userRepository.save(user);
        
        // 更新缓存
        cacheUserInfo(updatedUser);
        
        return updatedUser;
    }
    
    private void cacheUserInfo(User user) {
        String cacheKey = "user:" + user.getId();
        cacheService.put(cacheKey, user);
    }
}

// 用户更新请求DTO
public class UserUpdateRequest {
    private String email;
    private String password;
    
    // Getter和Setter
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
    
    public String getPassword() { return password; }
    public void setPassword(String password) { this.password = password; }
}

9.3 完整的控制器

@RestController
@RequestMapping("/api/v1/users")
@Validated
public class EnhancedUserController {
    
    private final EnhancedUserService userService;
    
    public EnhancedUserController(EnhancedUserService userService) {
        this.userService = userService;
    }
    
    @PostMapping("/register")
    public ResponseEntity<ApiResponse<User>> registerUser(
            @Valid @RequestBody UserRegistrationRequest request) {
        try {
            User user = userService.registerUser(request);
            
            ApiResponse<User> response = new ApiResponse<>();
            response.setSuccess(true);
            response.setMessage("用户注册成功");
            response.setData(user);
            
            return ResponseEntity.ok(response);
            
        } catch (Exception e) {
            ApiResponse<User> response = new ApiResponse<>();
            response.setSuccess(false);
            response.setMessage("注册失败: " + e.getMessage());
            
            return ResponseEntity.badRequest().body(response);
        }
    }
    
    @PostMapping("/login")
    public ResponseEntity<ApiResponse<String>> login(@RequestBody LoginRequest request) {
        boolean authenticated = userService.authenticateUser(request.getUsername(), request.getPassword());
        
        ApiResponse<String> response = new ApiResponse<>();
        if (authenticated) {
            response.setSuccess(true);
            response.setMessage("登录成功");
            response.setData("authentication-token-here");
            return ResponseEntity.ok(response);
        } else {
            response.setSuccess(false);
            response.setMessage("用户名或密码错误");
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response);
        }
    }
    
    @GetMapping("/{id}")
    public ResponseEntity<ApiResponse<User>> getUser(@PathVariable Long id) {
        try {
            User user = userService.getUserById(id);
            
            ApiResponse<User> response = new ApiResponse<>();
            response.setSuccess(true);
            response.setData(user);
            
            return ResponseEntity.ok(response);
            
        } catch (Exception e) {
            ApiResponse<User> response = new ApiResponse<>();
            response.setSuccess(false);
            response.setMessage(e.getMessage());
            
            return ResponseEntity.notFound().build();
        }
    }
    
    @GetMapping
    public ResponseEntity<ApiResponse<List<User>>> getAllUsers() {
        List<User> users = userService.getAllUsers();
        
        ApiResponse<List<User>> response = new ApiResponse<>();
        response.setSuccess(true);
        response.setMessage("获取用户列表成功");
        response.setData(users);
        
        return ResponseEntity.ok(response);
    }
    
    @PutMapping("/{id}")
    public ResponseEntity<ApiResponse<User>> updateUser(
            @PathVariable Long id,
            @RequestBody UserUpdateRequest request) {
        try {
            User user = userService.updateUser(id, request);
            
            ApiResponse<User> response = new ApiResponse<>();
            response.setSuccess(true);
            response.setMessage("用户信息更新成功");
            response.setData(user);
            
            return ResponseEntity.ok(response);
            
        } catch (Exception e) {
            ApiResponse<User> response = new ApiResponse<>();
            response.setSuccess(false);
            response.setMessage("更新失败: " + e.getMessage());
            
            return ResponseEntity.badRequest().body(response);
        }
    }
}

// 通用API响应类
public class ApiResponse<T> {
    private boolean success;
    private String message;
    private T data;
    private LocalDateTime timestamp;
    
    public ApiResponse() {
        this.timestamp = LocalDateTime.now();
    }
    
    // Getter和Setter方法
    public boolean isSuccess() { return success; }
    public void setSuccess(boolean success) { this.success = success; }
    
    public String getMessage() { return message; }
    public void setMessage(String message) { this.message = message; }
    
    public T getData() { return data; }
    public void setData(T data) { this.data = data; }
    
    public LocalDateTime getTimestamp() { return timestamp; }
    public void setTimestamp(LocalDateTime timestamp) { this.timestamp = timestamp; }
}

10. 常见问题与最佳实践

10.1 避免循环依赖

// ❌ 错误示例:循环依赖
@Service
public class ServiceA {
    @Autowired
    private ServiceB serviceB;  // ServiceA依赖ServiceB
}

@Service
public class ServiceB {
    @Autowired
    private ServiceA serviceA;  // ServiceB依赖ServiceA,形成循环
}

// ✅ 解决方案1:使用@Lazy
@Service
public class ServiceA {
    private final ServiceB serviceB;
    
    public ServiceA(@Lazy ServiceB serviceB) {  // 懒加载打破循环
        this.serviceB = serviceB;
    }
}

// ✅ 解决方案2:重新设计,引入第三个服务
@Service
public class SharedService {
    // 共同需要的功能
}

@Service
public class ServiceA {
    @Autowired
    private SharedService sharedService;
}

@Service
public class ServiceB {
    @Autowired
    private SharedService sharedService;
}

10.2 合理使用Bean作用域

// ✅ 正确:无状态的服务使用单例
@Service  // 默认单例,适合无状态的服务
public class UserService {
    // 无实例变量,线程安全
    public User findById(Long id) {
        // 查找逻辑
    }
}

// ❌ 错误:有状态的Bean使用单例会有线程安全问题
@Service  // 单例,但有状态,不线程安全
public class StatefulService {
    private int counter = 0;  // 实例变量,多线程访问会有问题
    
    public int increment() {
        return ++counter;  // 线程不安全
    }
}

// ✅ 正确:有状态的Bean使用原型作用域
@Service
@Scope("prototype")  // 每次使用都创建新实例
public class StatefulService {
    private int counter = 0;  // 每个实例都有自己的counter
    
    public int increment() {
        return ++counter;  // 线程安全
    }
}

10.3 优先使用构造器注入

// ✅ 推荐:构造器注入
@Service
public class UserService {
    private final UserRepository userRepository;
    private final EmailService emailService;
    
    // 构造器注入,依赖明确,便于测试
    public UserService(UserRepository userRepository, EmailService emailService) {
        this.userRepository = userRepository;
        this.emailService = emailService;
    }
}

// ❌ 不推荐:字段注入
@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;  // 字段注入,难以测试
    
    @Autowired
    private EmailService emailService;
}

10.4 Bean命名规范

// ✅ 好的Bean命名
@Service("userService")           // 清晰的服务名称
@Repository("userRepository")     // 清晰的仓库名称
@Component("emailSender")         // 清晰的组件名称

// ❌ 不好的Bean命名
@Service("us")                    // 太简短,不清晰
@Repository("repo1")              // 没有意义的名称
@Component("component")           // 通用名称,不具体

11. 总结

11.1 Bean的核心概念回顾

  1. Bean是什么:Spring容器管理的Java对象
  2. 为什么使用Bean:自动化对象管理,降低耦合度
  3. 如何声明Bean:@Component系列注解、@Bean方法
  4. 依赖注入:自动装配Bean之间的依赖关系
  5. 作用域:控制Bean的生命周期和实例化策略
  6. 生命周期:从创建到销毁的完整过程

11.2 最佳实践总结

  1. 优先使用构造器注入,保证依赖的不可变性
  2. 合理选择Bean作用域,无状态用单例,有状态用原型
  3. 避免循环依赖,通过重新设计或使用@Lazy解决
  4. 使用有意义的Bean名称,提高代码可读性
  5. 合理使用生命周期回调,管理资源的创建和释放
  6. 条件化创建Bean,根据环境和配置灵活选择

11.3 学习建议

  1. 从简单开始:先掌握@Service、@Repository、@Controller
  2. 理解依赖注入:搞清楚构造器注入、Setter注入的区别
  3. 实践作用域:创建不同作用域的Bean,观察行为差异
  4. 学习生命周期:使用@PostConstruct和@PreDestroy管理资源
  5. 探索高级特性:条件化Bean、FactoryBean、懒加载等
  6. 项目实践:在实际项目中应用这些概念

通过深入理解和实践Spring Boot的Bean机制,您将能够构建出结构清晰、易于维护的应用程序!


网站公告

今日签到

点亮在社区的每一天
去签到