1. Bean定义基础

1.1 什么是Bean定义(BeanDefinition)

Bean定义是Spring IoC容器中用于描述Bean的元数据对象,它是Bean实例化的蓝图。

// Bean定义包含的核心信息
public interface BeanDefinition {
    String getBeanClassName();      // 类的全限定名
    String getScope();               // 作用域(singleton/prototype等)
    boolean isLazyInit();           // 是否延迟初始化

    String[ ] getDependsOn();        // 依赖的其他Bean

    boolean isAutowireCandidate();  // 是否作为自动装配候选
    boolean isPrimary();            // 是否为主候选Bean
    String getInitMethodName();     // 初始化方法名
    String getDestroyMethodName();  // 销毁方法名
    // ... 更多属性
}

1.2 Bean定义 vs Bean实例

特性 Bean定义(BeanDefinition) Bean实例(Bean Instance)
性质 元数据/配置信息 实际的Java对象
创建时机 容器启动时(配置加载阶段) 根据作用域决定
存储位置 BeanDefinitionRegistry BeanFactory/ApplicationContext
数量 每个Bean一个定义 根据作用域可能有多个实例
作用 描述如何创建Bean 提供实际的业务功能
// 简化示意
ApplicationContext context = new AnnotationConfigApplicationContext();

// 阶段1:注册Bean定义
BeanDefinition definition = new RootBeanDefinition(OrderService.class);
definition.setScope("singleton");
context.registerBeanDefinition("orderService", definition);

// 阶段2:根据Bean定义创建Bean实例
OrderService instance = context.getBean(OrderService.class);

1.3 Bean定义的创建方式

方式1:注解扫描(最常用)

@Configuration
@ComponentScan("com.xxx.mall")
public class AppConfig {
    // 扫描包下所有@Component/@Service/@Controller等
    // 自动创建BeanDefinition
}

@Service  // 被扫描器识别,自动注册为BeanDefinition
public class OrderService { }

方式2:@Bean方法

@Configuration
public class AppConfig {
    
    @Bean  // 方法返回值类型和名称用于创建BeanDefinition
    public DataSource dataSource() {
        HikariDataSource ds = new HikariDataSource();
        ds.setJdbcUrl("jdbc:mysql://localhost:3306/db");
        return ds;
    }
}

方式3:XML配置(传统方式)

<beans>
    <bean id="orderService" class="com.xxx.OrderService" 
          scope="singleton" lazy-init="false">
        <property name="orderRepository" ref="orderRepository"/>
    </bean>
</beans>

方式4:编程式注册

public class CustomBeanRegistrar {
    public void register(BeanDefinitionRegistry registry) {
        BeanDefinitionBuilder builder = BeanDefinitionBuilder
            .genericBeanDefinition(OrderService.class)
            .setScope("singleton")
            .setLazyInit(false);
            
        registry.registerBeanDefinition("orderService", 
                                       builder.getBeanDefinition());
    }
}

1.4 Bean的完整生命周期

1. 加载Bean定义
   ↓
2. 实例化Bean(调用构造器)
   ↓
3. 填充属性(依赖注入)
   ↓
4. 调用Aware接口方法
   - BeanNameAware.setBeanName()
   - BeanFactoryAware.setBeanFactory()
   - ApplicationContextAware.setApplicationContext()
   ↓
5. BeanPostProcessor.postProcessBeforeInitialization()
   ↓
6. 调用初始化方法
   - @PostConstruct注解的方法
   - InitializingBean.afterPropertiesSet()
   - 自定义init-method
   ↓
7. BeanPostProcessor.postProcessAfterInitialization()
   ↓
8. Bean就绪,可以使用
   ↓
9. 容器关闭时调用销毁方法
   - @PreDestroy注解的方法
   - DisposableBean.destroy()
   - 自定义destroy-method

实际代码示例:

@Service
public class OrderService implements InitializingBean, DisposableBean {
    
    private OrderRepository orderRepository;
    
    // 1. 构造器(实例化阶段)
    public OrderService() {
        System.out.println("1. 构造器调用");
    }
    
    // 2. 依赖注入(属性填充阶段)
    @Autowired
    public void setOrderRepository(OrderRepository orderRepository) {
        System.out.println("2. 注入依赖");
        this.orderRepository = orderRepository;
    }
    
    // 3. 初始化方法
    @PostConstruct
    public void init() {
        System.out.println("3. @PostConstruct初始化");
    }
    
    @Override
    public void afterPropertiesSet() {
        System.out.println("4. afterPropertiesSet初始化");
    }
    
    // 4. 销毁方法
    @PreDestroy
    public void cleanup() {
        System.out.println("5. @PreDestroy清理");
    }
    
    @Override
    public void destroy() {
        System.out.println("6. destroy清理");
    }
}

// 输出顺序:
// 1. 构造器调用
// 2. 注入依赖
// 3. @PostConstruct初始化
// 4. afterPropertiesSet初始化
// (容器关闭时)
// 5. @PreDestroy清理
// 6. destroy清理

1.5 Bean定义的后置处理

Spring允许在Bean定义注册后、实例化前修改Bean定义:

@Component
public class CustomBeanDefinitionPostProcessor 
        implements BeanFactoryPostProcessor {
    
    @Override
    public void postProcessBeanFactory(
            ConfigurableListableBeanFactory beanFactory) {
        
        // 获取Bean定义
        BeanDefinition definition = beanFactory
            .getBeanDefinition("orderService");
        
        // 修改Bean定义属性
        definition.setScope("prototype");  // 改为原型模式
        definition.setLazyInit(true);      // 改为延迟初始化
    }
}


2. 核心注解实现原理

2.1 依赖注入类

@Autowired

  • 实现机制: Spring容器启动时通过AutowiredAnnotationBeanPostProcessor处理

  • 工作流程:

    1. 容器启动时扫描所有Bean定义

    2. 反射获取标注@Autowired的字段/构造器/方法

    3. 根据类型从容器中查找匹配的Bean

    4. 通过反射设置字段值或调用方法完成注入

@Component

  • 角色: Spring组件注解的基础注解,标记类为Spring管理的Bean

  • 实现机制: 通过ClassPathBeanDefinitionScanner组件扫描

  • 工作流程:

    1. Spring容器启动时扫描指定包路径

    2. 识别标注了@Component及其派生注解的类

    3. 将类信息注册为BeanDefinition

    4. 根据BeanDefinition创建Bean实例并放入IoC容器

派生注解体系:

@Component              // 基础注解,通用组件
  ├─ @Service          // 业务逻辑层
  ├─ @Repository       // 数据访问层
  └─ @Controller       // 控制层
       └─ @RestController  // RESTful控制层

注解对比:

注解 语义层次 使用场景 额外功能
@Component 通用组件 不属于明确分层的工具类、配置类
@Service 业务层 Service层,处理业务逻辑 无(语义化)
@Repository 持久层 DAO/Repository层,数据访问 自动转换持久化异常
@Controller 控制层 MVC控制器 配合@RequestMapping
@RestController RESTful层 RESTful API控制器 @Controller + @ResponseBody

@Component典型使用场景:

// 1. 工具类组件
@Component
public class RedisUtil {
    public void set(String key, Object value) { }
}

// 2. 配置类(也可用@Configuration)
@Component
public class AppConfigProperties {
    private String appName;
    private String version;
}

// 3. 事件监听器
@Component
public class OrderEventListener {
    @EventListener
    public void handleOrderCreated(OrderCreatedEvent event) { }
}

// 4. 定时任务
@Component
public class ScheduledTasks {
    @Scheduled(cron = "0 0 1 * * ?")
    public void cleanupTask() { }
}

// 5. 消息监听器
@Component
public class MessageConsumer {
    @RabbitListener(queues = "orderQueue")
    public void processMessage(String message) { }
}

为什么要用派生注解而非@Component:

  1. 语义化: 清晰表达类的职责和分层

  2. AOP增强: 某些注解有额外功能(如@Repository的异常转换)

  3. 可读性: 代码更易理解和维护

  4. 工具支持: IDE和框架能根据注解提供针对性支持

// ❌ 不推荐:语义不清晰
@Component
public class OrderService { }

// ✅ 推荐:明确表达是业务层
@Service
public class OrderService { }

// ❌ 不推荐:语义不清晰
@Component
public class OrderRepository { }

// ✅ 推荐:明确表达是持久层,且有异常转换功能
@Repository
public class OrderRepository { }

2.2 Web层类

@RestController

  • 组合注解@Controller + @ResponseBody

  • 功能:

    • 标记为Spring MVC控制器

    • 自动将返回值序列化为JSON/XML响应

@RequestMapping

  • 实现机制RequestMappingHandlerMapping处理

  • 工作流程:

    1. 扫描所有@Controller/@RestController类

    2. 解析@RequestMapping注解信息(路径、HTTP方法等)

    3. 建立URL到处理方法的映射关系

    4. 请求到达时,DispatcherServlet根据映射分发到对应方法

@Validated

  • 实现机制: 基于JSR-303/JSR-380 Bean Validation规范

  • 工作流程:

    1. MethodValidationPostProcessor创建AOP代理

    2. 方法调用前拦截,触发参数校验

    3. 校验失败抛出ConstraintViolationException

2.3 文档类

@Api / @ApiOperation

  • 框架: Swagger/OpenAPI

  • 实现机制:

    • 启动时扫描注解通过反射提取元数据

    • 生成API文档JSON描述

    • Swagger UI渲染为可视化文档


3. 注解必要性与使用场景

注解 必要性 使用场景 替代方案
@Autowired ⭐⭐⭐⭐⭐ 注入Service/Repository/Component 构造器注入、@Resource
@Service ⭐⭐⭐⭐⭐ 标记业务逻辑层 @Component
@RestController ⭐⭐⭐⭐⭐ RESTful API控制器 @Controller + @ResponseBody
@RequestMapping ⭐⭐⭐⭐⭐ 定义API路由 @GetMapping/@PostMapping等
@Validated ⭐⭐⭐ 需要参数校验 手动校验
@Api ⭐⭐ 生成API文档 手写文档

典型使用场景

// Service层
@Service
public class OrderService {
    private final OrderRepository orderRepository;
    
    // 构造器注入(推荐)
    public OrderService(OrderRepository orderRepository) {
        this.orderRepository = orderRepository;
    }
}

// Controller层
@RestController
@RequestMapping("/api/v1.0/orders")
@Validated
@Api(tags = "订单管理")
public class OrderController {
    
    private final OrderService orderService;
    
    public OrderController(OrderService orderService) {
        this.orderService = orderService;
    }
    
    @PostMapping
    @ApiOperation("创建订单")
    public Response create(@Valid @RequestBody OrderDTO dto) {
        return Response.success(orderService.create(dto));
    }
}


4. 开发最佳实践

4.1 @Autowired 使用建议

✅ 推荐:构造器注入

@Service
public class OrderService {
    private final PaymentService paymentService;
    private final InventoryService inventoryService;
    
    // 单构造器可省略@Autowired
    public OrderService(PaymentService paymentService, 
                       InventoryService inventoryService) {
        this.paymentService = paymentService;
        this.inventoryService = inventoryService;
    }
}

优势:

  • 字段可以声明为final,保证不可变性

  • 便于单元测试(直接new对象传入mock依赖)

  • 强制所有必需依赖在对象创建时就绪

  • 避免NullPointerException

❌ 不推荐:字段注入

@Service
public class OrderService {
    @Autowired
    private PaymentService paymentService; // 无法final
}

问题:

  • 无法保证不可变性

  • 隐藏依赖关系

  • 单元测试需要Spring容器或反射

注意事项

  • 避免循环依赖(使用@Lazy或重构设计)

  • 注入接口而非实现类

  • 多个同类型Bean时使用@Qualifier指定

4.2 @Component及其派生注解使用建议

选择合适的注解

// ✅ 业务逻辑层使用@Service
@Service
public class OrderService {
    public Order createOrder(OrderDTO dto) { }
    public Order getOrder(Long id) { }
}

// ✅ 数据访问层使用@Repository
@Repository
public class OrderRepository {
    public Order findById(Long id) { }
}

// ✅ 不属于明确分层的使用@Component
@Component
public class JwtTokenUtil {
    public String generateToken(String username) { }
    public boolean validateToken(String token) { }
}

// ✅ 配置属性类
@Component
@ConfigurationProperties(prefix = "app")
public class AppProperties {
    private String name;
    private String version;
}

// ❌ 职责混乱
@Service
public class BusinessService { 
    // 包含订单、支付、物流等多种业务 - 违反单一职责
}

// ❌ 注解选择错误
@Component  // 应该用@Service
public class PaymentService { }

@Service    // 应该用@Repository
public class UserDao { }

Bean命名规范

// 默认Bean名称为首字母小写的类名
@Component  // Bean名称: "orderValidator"
public class OrderValidator { }

// 自定义Bean名称
@Component("customOrderValidator")
public class OrderValidator { }

// 多实现时明确命名
@Service("alipayPaymentService")
public class AlipayPaymentService implements PaymentService { }

@Service("wechatPaymentService")
public class WechatPaymentService implements PaymentService { }

注意事项

规范:

  • ✅ 遵循单一职责原则

  • ✅ 按业务领域划分Service

  • ✅ 根据分层选择合适的注解(@Service/@Repository/@Component)

  • ✅ 工具类、辅助类使用@Component

  • ❌ 避免在一个类上同时使用多个组件注解

  • ❌ 避免过度使用@Component,优先使用语义化的派生注解

  • ❌ 不要在接口上使用组件注解(注解应在实现类上)

// ❌ 错误:在接口上使用
@Service
public interface PaymentService { }

// ✅ 正确:在实现类上使用
public interface PaymentService { }

@Service
public class AlipayPaymentServiceImpl implements PaymentService { }

4.3 @RequestMapping 使用建议

// ✅ RESTful风格
@RestController
@RequestMapping("/api/v1.0/orders")
public class OrderController {
    
    @GetMapping("/{id}")           // GET /api/v1.0/orders/123
    public Response get(@PathVariable Long id) { }
    
    @PostMapping                   // POST /api/v1.0/orders
    public Response create(@RequestBody OrderDTO dto) { }
    
    @PutMapping("/{id}")          // PUT /api/v1.0/orders/123
    public Response update(@PathVariable Long id, @RequestBody OrderDTO dto) { }
    
    @DeleteMapping("/{id}")       // DELETE /api/v1.0/orders/123
    public Response delete(@PathVariable Long id) { }
}

规范:

  • 类级别定义公共前缀

  • 使用HTTP方法明确语义(@GetMapping、@PostMapping等)

  • 路径使用小写和连字符

  • 版本号放在路径中(/v1.0/)

4.4 @Validated 使用建议

@RestController
@Validated // 类级别开启校验
public class OrderController {
    
    @PostMapping("/orders")
    public Response create(@Valid @RequestBody OrderDTO dto) {
        // @Valid触发DTO内部校验
        return Response.success();
    }
    
    @GetMapping("/orders/{id}")
    public Response get(@PathVariable @Min(1) Long id) {
        // @Validated + @Min校验路径参数
        return Response.success();
    }
}

// DTO定义
@Data
public class OrderDTO {
    @NotNull(message = "订单号不能为空")
    private String orderNo;
    
    @Min(value = 1, message = "金额必须大于0")
    private BigDecimal amount;
    
    @Email(message = "邮箱格式不正确")
    private String email;
}

配合全局异常处理:

@RestControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Response handleValidationException(MethodArgumentNotValidException e) {
        String message = e.getBindingResult().getFieldErrors()
            .stream()
            .map(FieldError::getDefaultMessage)
            .collect(Collectors.joining(", "));
        return Response.fail(message);
    }
}


5. Bean作用域与线程安全

5.1 单例模式(默认)

@Service // 默认singleton作用域
public class OrderService {
    // 这是全局单例,所有请求共享同一实例
}

// 等同于
@Service
@Scope("singleton")
public class OrderService { }

5.2 原型模式

@Service
@Scope("prototype") // 每次注入创建新实例
public class ReportGenerator {
    // 适用于有状态的Bean
}

5.3 线程安全问题

❌ 错误:单例Bean使用实例变量

@Service
public class OrderService {
    private Order currentOrder; // 危险!多线程会互相覆盖
    
    public void process(Long orderId) {
        this.currentOrder = orderRepository.findById(orderId);
        // 高并发下currentOrder会被其他线程覆盖
    }
}

✅ 正确:使用方法参数传递状态

@Service
public class OrderService {
    // 无状态,线程安全
    
    public void process(Long orderId) {
        Order order = orderRepository.findById(orderId); // 局部变量
        // 每次调用独立,线程安全
    }
}

✅ 正确:使用ThreadLocal(谨慎)

@Service
public class UserContextService {
    private ThreadLocal<User> currentUser = new ThreadLocal<>();
    
    public void setCurrentUser(User user) {
        currentUser.set(user);
    }
    
    public User getCurrentUser() {
        return currentUser.get();
    }
    
    public void clear() {
        currentUser.remove(); // 记得清理,避免内存泄漏
    }
}

5.4 Controller和Service都是单例

@RestController
public class OrderController {
    private final OrderService orderService; // 指向同一个单例Service
    
    public OrderController(OrderService orderService) {
        this.orderService = orderService;
    }
    
    // 每个HTTP请求由不同线程处理
    // 但都使用同一个Controller实例和同一个OrderService实例
}

关键点:

  • Controller、Service、Repository默认都是单例

  • 多个请求并发访问同一个实例

  • 必须保证无状态或线程安全


6. 常见问题与解决方案

6.1 循环依赖

// ❌ 循环依赖
@Service
public class OrderService {
    @Autowired
    private PaymentService paymentService;
}

@Service
public class PaymentService {
    @Autowired
    private OrderService orderService; // 循环!
}

解决方案:

  1. 使用@Lazy延迟加载

    @Service
    public class OrderService {
        private final PaymentService paymentService;
            
        public OrderService(@Lazy PaymentService paymentService) {
            this.paymentService = paymentService;
        }
    }
        
    
  2. 重构设计(推荐)

// 提取公共依赖
@Service
public class OrderService {
    private final OrderRepository orderRepository;
}

@Service
public class PaymentService {
    private final PaymentRepository paymentRepository;
}

@Service
public class OrderPaymentFacade {
    private final OrderService orderService;
    private final PaymentService paymentService;
    
    public void processOrderPayment() {
        // 协调两个服务
    }
}

6.2 多个同类型Bean

@Service("alipayService")
public class AlipayService implements PaymentService { }

@Service("wechatService")
public class WechatPayService implements PaymentService { }

// 注入时指定
@Autowired
@Qualifier("alipayService")
private PaymentService paymentService;

6.3 可选依赖

@Autowired(required = false)
private OptionalService optionalService; // 可能为null

// 或使用Optional
@Autowired
private Optional<OptionalService> optionalService;


7. 总结

核心原则

  1. 优先构造器注入,保证不可变性和可测试性

  2. 保持Bean无状态,避免线程安全问题

  3. 遵循单一职责,合理划分Service边界

  4. 统一路径规范,使用RESTful风格

  5. 充分利用校验,参数验证前移

性能考虑

  • 单例Bean在应用启动时创建,运行时复用,性能最优

  • 避免过度使用prototype作用域

  • 合理使用@Lazy延迟初始化,加快启动速度

可维护性

  • 注解让配置更接近代码,降低维护成本

  • 但避免过度使用注解,保持代码简洁

  • 重要的配置信息建议集中管理(如application.properties)