当前位置: 首页 > news >正文

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

文章目录

    • 1. 什么是Bean?从零开始理解
      • 1.1 Bean的定义
      • 1.2 为什么需要Bean?
      • 1.3 Bean vs 普通对象的区别
    • 2. Spring容器:Bean的家
      • 2.1 什么是Spring容器?
      • 2.2 容器的工作流程
    • 3. Bean的声明方式详解
      • 3.1 使用@Component及其专门化注解
        • 3.1.1 @Component - 通用组件
        • 3.1.2 @Service - 业务逻辑层
        • 3.1.3 @Repository - 数据访问层
        • 3.1.4 @Controller和@RestController - 控制层
        • 3.1.5 用户实体类
      • 3.2 Bean名称自定义
    • 4. 使用@Bean注解创建Bean
      • 4.1 什么时候使用@Bean?
      • 4.2 基础@Bean使用
      • 4.3 Bean之间的依赖
      • 4.4 条件化Bean创建
    • 5. 依赖注入详解
      • 5.1 什么是依赖注入?
      • 5.2 依赖注入的三种方式
        • 5.2.1 构造器注入(推荐)
        • 5.2.2 Setter注入
        • 5.2.3 字段注入(不推荐,但常见)
      • 5.3 解决多个实现的问题
        • 5.3.1 使用@Qualifier
        • 5.3.2 使用@Primary
        • 5.3.3 注入所有实现
    • 6. Bean的作用域(Scope)
      • 6.1 什么是Bean作用域?
      • 6.2 Singleton作用域(默认)
      • 6.3 Prototype作用域
      • 6.4 Web作用域
        • 6.4.1 Request作用域
        • 6.4.2 Session作用域
    • 7. Bean的生命周期详解
      • 7.1 Bean生命周期概述
      • 7.2 生命周期回调方法
        • 7.2.1 使用@PostConstruct和@PreDestroy
        • 7.2.2 实现InitializingBean和DisposableBean接口
        • 7.2.3 使用@Bean的initMethod和destroyMethod
      • 7.3 Bean后置处理器
    • 8. 高级Bean特性
      • 8.1 懒加载(Lazy Loading)
      • 8.2 条件化Bean创建
        • 8.2.1 基于配置属性的条件
        • 8.2.2 基于类存在的条件
      • 8.3 FactoryBean
    • 9. 实际应用案例
      • 9.1 构建完整的用户管理系统
      • 9.2 增强的用户服务
      • 9.3 完整的控制器
    • 10. 常见问题与最佳实践
      • 10.1 避免循环依赖
      • 10.2 合理使用Bean作用域
      • 10.3 优先使用构造器注入
      • 10.4 Bean命名规范
    • 11. 总结
      • 11.1 Bean的核心概念回顾
      • 11.2 最佳实践总结
      • 11.3 学习建议

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 {@Autowiredprivate 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 {@Autowiredprivate EmailSender emailSender;  // Spring会自动注入EmailSenderpublic void sendWelcomeEmail(String userEmail) {emailSender.sendEmail(userEmail, "欢迎", "欢迎注册我们的网站!");}
}
3.1.2 @Service - 业务逻辑层
// @Service表示这是一个服务层的Bean
@Service
public class UserService {@Autowiredprivate 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 {@Autowiredprivate UserService userService;@Autowiredprivate 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();}}// 获取所有用户@GetMappingpublic 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; }@Overridepublic 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")  // 通过名称指定要注入的Beanprivate UserService userService;
}

4. 使用@Bean注解创建Bean

4.1 什么时候使用@Bean?

当你需要:

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

4.2 基础@Bean使用

@Configuration  // 表示这是一个配置类
public class AppConfig {// 创建数据库连接Bean@Beanpublic 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@Beanpublic JedisPool jedisPool() {JedisPoolConfig config = new JedisPoolConfig();config.setMaxTotal(100);  // 最大连接数config.setMaxIdle(20);    // 最大空闲连接数config.setMinIdle(5);     // 最小空闲连接数return new JedisPool(config, "localhost", 6379);}// 创建邮件发送器Bean@Beanpublic 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@Beanpublic DatabaseService databaseService(DataSource dataSource) {// Spring会自动注入dataSource参数return new DatabaseService(dataSource);}// 创建缓存服务Bean@Beanpublic CacheService cacheService(JedisPool jedisPool) {return new CacheService(jedisPool);}// 创建用户服务Bean,依赖于数据库服务和缓存服务@Beanpublic 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注入@Autowiredpublic void setEmailService(EmailService emailService) {this.emailService = emailService;System.out.println("EmailService已注入");}@Autowiredpublic 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 {// 字段注入 - 简单但不推荐@Autowiredprivate OrderService orderService;@Autowiredprivate NotificationService notificationService;@PostMappingpublic 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和Setterpublic 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 {@Overridepublic boolean processPayment(BigDecimal amount) {System.out.println("使用支付宝支付: " + amount);return true;}
}// 微信支付实现
@Service("wechatProcessor")
public class WechatPayProcessor implements PaymentProcessor {@Overridepublic boolean processPayment(BigDecimal amount) {System.out.println("使用微信支付: " + amount);return true;}
}// 银行卡支付实现
@Service("bankCardProcessor")
public class BankCardProcessor implements PaymentProcessor {@Overridepublic 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 {@Overridepublic 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 {@Autowiredprivate UserService userService1;@Autowiredprivate 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 {@Autowiredprivate 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 {@Autowiredprivate 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和Setterpublic 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创建后自动调用@PostConstructpublic 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销毁前自动调用@PreDestroypublic 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;@Overridepublic void close() {this.closed = true;isConnected = false;}@Overridepublic 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;@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("=== CacheService初始化 ===");// 初始化缓存this.cache = new ConcurrentHashMap<>();// 预加载一些数据preloadCache();this.cacheEnabled = true;System.out.println("缓存服务已启动,预加载了 " + cache.size() + " 条数据");}@Overridepublic 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 {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof UserService) {System.out.println("准备初始化UserService: " + beanName);// 可以在这里修改bean的属性}return bean;}@Overridepublic 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缓存管理器");// 实际项目中这里会配置Redisreturn 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;@Overridepublic 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;}@Overridepublic Class<?> getObjectType() {return DatabaseConnection.class;}@Overridepublic 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();}@Beanpublic 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;@Datapublic static class Security {private boolean enabled = true;private int maxLoginAttempts = 3;}// Getter和Setter方法省略
}// 简单密码编码器
public class SimplePasswordEncoder implements PasswordEncoder {@Overridepublic String encode(CharSequence rawPassword) {return "simple_" + rawPassword.toString();}@Overridepublic 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和Setterpublic 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();}}@GetMappingpublic 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 {@Autowiredprivate ServiceB serviceB;  // ServiceA依赖ServiceB
}@Service
public class ServiceB {@Autowiredprivate 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 {@Autowiredprivate SharedService sharedService;
}@Service
public class ServiceB {@Autowiredprivate 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;  // 每个实例都有自己的counterpublic 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 {@Autowiredprivate UserRepository userRepository;  // 字段注入,难以测试@Autowiredprivate 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机制,您将能够构建出结构清晰、易于维护的应用程序!

http://www.lryc.cn/news/583154.html

相关文章:

  • OpenCV颜色矩哈希算法------cv::img_hash::ColorMomentHash
  • STM32-待机唤醒实验
  • [Leetcode] 预处理 | 多叉树bfs | 格雷编码 | static_cast | 矩阵对角线
  • User手机上如何抓取界面的布局uiautomatorviewer
  • 【机器人】Aether 多任务世界模型 | 4D动态重建 | 视频预测 | 视觉规划
  • 速卖通跨境运营破局:亚矩阵云手机如何用“本地化黑科技”撬动俄罗斯市场25%客单价增长
  • React 编译器与性能优化:告别手动 Memoization
  • 开始读 PostgreSQL 16 Administration Cookbook
  • 苍穹外卖项目日记(day04)
  • 【Netty+WebSocket详解】WebSocket全双工通信与Netty的高效结合与实战
  • 冷冻电镜重构的GPU加速破局:从Relion到CryoSPARC的并行重构算法
  • 《重构项目》基于Apollo架构设计的项目重构方案(多种地图、多阶段、多任务、状态机管理)
  • 仓颉语言 1.0.0 升级指南:工具链适配、collection 操作重构与 Map 遍历删除避坑
  • IT系统安全刚需:绝缘故障定位系统
  • Tailwind CSS纵向滚动条设置
  • PiscTrace深蹲计数功能实现:基于 YOLO-Pose 和人体关键点分析
  • 基于Java+Maven+Testng+Selenium+Log4j+Allure+Jenkins搭建一个WebUI自动化框架(4)集成Allure报表
  • JavaScript数组方法——梳理和考点
  • SpringBoot实现动态Job实战
  • DRT-Net: Dual-Branch Rectangular Transformer with Contrastive Learning
  • 离线二维码生成器,无需网络快速制作
  • springBoot使用XWPFDocument 和 LoopRowTableRenderPolicy 两种方式填充数据到word模版中
  • Android-重学kotlin(协程源码第一阶段)新学习总结
  • npm init vue@latestnpm error code ETIMEDOUT
  • 网络请求与现实生活:用办理业务类比理解HTTP通信
  • kotlin学习,val使用get()的问题
  • AI 知识库 2.0 时代!2025 设备管理系统如何实现 “智慧运维”?
  • Docker完全指南:从入门到生产环境实战
  • 将.net应用部署到Linux服务器
  • 深入解析 .NET 泛型:从原理到实战优化