文章目录
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容器就像一个智能的对象工厂,它负责:
- 创建对象:根据配置创建Bean实例
- 管理依赖:自动注入Bean之间的依赖关系
- 控制生命周期:管理Bean的创建、初始化、使用和销毁
- 提供服务:为应用程序提供所需的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?
当你需要:
- 配置第三方库的对象
- 需要复杂的创建逻辑
- 根据条件创建不同的Bean
- 配置系统组件
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;
}
}
}
构造器注入的优点:
- 依赖不可变:可以使用final关键字
- 保证完整性:对象创建时就有了所有依赖
- 便于测试:容易进行单元测试
- 避免循环依赖:编译时就能发现问题
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的生命周期包括以下阶段:
- 实例化:创建Bean实例
- 属性赋值:设置Bean的属性
- 初始化:执行初始化方法
- 使用:Bean可以被应用程序使用
- 销毁:应用关闭时销毁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的核心概念回顾
- Bean是什么:Spring容器管理的Java对象
- 为什么使用Bean:自动化对象管理,降低耦合度
- 如何声明Bean:@Component系列注解、@Bean方法
- 依赖注入:自动装配Bean之间的依赖关系
- 作用域:控制Bean的生命周期和实例化策略
- 生命周期:从创建到销毁的完整过程
11.2 最佳实践总结
- 优先使用构造器注入,保证依赖的不可变性
- 合理选择Bean作用域,无状态用单例,有状态用原型
- 避免循环依赖,通过重新设计或使用@Lazy解决
- 使用有意义的Bean名称,提高代码可读性
- 合理使用生命周期回调,管理资源的创建和释放
- 条件化创建Bean,根据环境和配置灵活选择
11.3 学习建议
- 从简单开始:先掌握@Service、@Repository、@Controller
- 理解依赖注入:搞清楚构造器注入、Setter注入的区别
- 实践作用域:创建不同作用域的Bean,观察行为差异
- 学习生命周期:使用@PostConstruct和@PreDestroy管理资源
- 探索高级特性:条件化Bean、FactoryBean、懒加载等
- 项目实践:在实际项目中应用这些概念
通过深入理解和实践Spring Boot的Bean机制,您将能够构建出结构清晰、易于维护的应用程序!