你是否曾被各种Spring注解搞得晕头转向?是否在面试中被问及
@Autowired
和@Resource
区别时支支吾吾? 本文将系统梳理Spring核心注解,揭秘最佳实践,让你彻底告别配置烦恼,提升开发效率300%!
@Service
public class OrderService {
// 错误1:混淆注入方式
@Resource(name = "paymentService")
private PaymentServiceImpl paymentService; // 实现类注入→耦合
// 错误2:作用域误用
@Scope("prototype")
@Autowired
private CartService cartService; // 购物车应该用session作用域
// 错误3:生命周期混乱
@PostConstruct
public void init() {
// 初始化逻辑
}
@PreDestroy
public void cleanup() {
// 清理逻辑
}
}
典型问题:
注解 | 层 | 等效XML | 特殊能力 |
---|---|---|---|
@Component |
通用 |
|
基础组件标识 |
@Controller |
Web层 |
|
支持请求映射 |
@Service |
Service层 |
|
事务切面优先切入点 |
@Repository |
DAO层 |
|
自动转换数据访问异常 |
// 正确使用示例
@Repository // 自动转换SQLException为DataAccessException
public class JpaOrderDao implements OrderDao {
// 数据访问实现
}
@Controller // 自动注册为Web控制器
public class OrderController {
@GetMapping("/orders")
public List<Order> list() { /* ... */ }
}
// @Autowired:Spring原生智能注入
public class OrderService {
@Autowired // 1. 按类型匹配 2. 配合@Qualifier按名称
@Qualifier("wechatPayment")
private PaymentService paymentService;
}
// @Resource:JSR-250标准注入
public class CartService {
@Resource(name = "redisCart") // 1. 按名称匹配 2. 按类型
private CartStorage storage;
}
对比决策表:
场景 | 推荐注解 | 原因 |
---|---|---|
按类型注入 | @Autowired |
简洁直观 |
按名称注入 | @Resource |
直接指定name属性 |
多实现类选择 | @Qualifier |
配合@Autowired 更灵活 |
跨框架兼容 | @Resource |
符合JSR标准,通用性强 |
// 常用作用域配置
@Service
@Scope("prototype") // 每次请求新实例
public class ReportGenerator { /* 报表生成 */ }
@Controller
@Scope(value = WebApplicationContext.SCOPE_SESSION,
proxyMode = ScopedProxyMode.TARGET_CLASS) // 会话级作用域
public class UserPreferenceController { /* 用户偏好设置 */ }
作用域详解:
singleton
:默认,单例(适用无状态服务)prototype
:原型(适用有状态工具类)request
:HTTP请求生命周期session
:用户会话生命周期application
:ServletContext生命周期@Service
public class CacheManager {
@PostConstruct // 初始化顺序:1
public void loadCache() {
// 预热缓存(数据库查询)
}
// 实现InitializingBean:初始化顺序:2
@Override
public void afterPropertiesSet() {
// 校验缓存配置
}
@PreDestroy // 销毁顺序:1
public void clearCache() {
// 释放缓存资源
}
// DisposableBean:销毁顺序:2
@Override
public void destroy() {
// 关闭连接池
}
}
关键规则:同一阶段注解执行无序!使用
@Order
控制多个同类型组件的初始化顺序
@Configuration // 声明为配置类
@ComponentScan(
basePackages = "com.example",
excludeFilters = @ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = Controller.class) // 排除Controller
)
@PropertySource("classpath:app.properties") // 加载配置文件
public class AppConfig {
@Bean(initMethod = "connect", destroyMethod = "disconnect")
@Scope("prototype")
public DatabaseService databaseService(
@Value("${db.url}") String url // 注入配置值
) {
return new DatabaseService(url);
}
}
@Configuration
public class PaymentConfig {
@Bean
@ConditionalOnProperty(name = "payment.gateway", havingValue = "alipay")
public PaymentService alipayService() {
return new AlipayService();
}
@Bean
@ConditionalOnMissingBean // 当没有其他PaymentService时生效
public PaymentService defaultPaymentService() {
return new WechatPayment();
}
}
未被扫描:检查@ComponentScan
范围
@SpringBootApplication(scanBasePackages = "com.example")
public class Application { /* ... */ }
代理问题:CGLib代理导致private
方法注解失效
// 解决方案:改为protected/public
@Transactional
protected void deductStock() { /* ... */ }
内部调用:同类方法调用绕过代理
public void placeOrder() {
// 错误:直接调用
validatePayment();
// 正确:通过代理调用
((OrderService) AopContext.currentProxy()).validatePayment();
}
顺序问题:依赖Bean尚未初始化
@DependsOn("cacheManager") // 显式声明依赖
@Service
public class ProductService { /* ... */ }
// 构造器注入循环依赖(无法解决!)
public class ServiceA {
private final ServiceB b;
public ServiceA(ServiceB b) { this.b = b; } // 报错!
}
// 解决方案:改用Setter注入
@Service
public class ServiceA {
private ServiceB b;
@Autowired // 或 @Resource
public void setServiceB(ServiceB b) {
this.b = b;
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AuditLog {
String action(); // 操作类型
String module(); // 模块名称
}
@Aspect
@Component
public class AuditAspect {
@Around("@annotation(auditLog)")
public Object logAudit(ProceedingJoinPoint pjp, AuditLog auditLog) {
// 获取注解参数
String action = auditLog.action();
String module = auditLog.module();
// 执行业务逻辑
try {
return pjp.proceed();
} finally {
AuditRecorder.record(action, module);
}
}
}
@Service
public class OrderService {
@AuditLog(action = "CREATE_ORDER", module = "ORDER")
public void createOrder(Order order) {
// 业务逻辑
}
}
注解 | 作用 | 典型场景 |
---|---|---|
@SpringBootApplication |
启动类 | 主配置类 |
@EnableAutoConfiguration |
启用自动配置 | 简化配置 |
@ConfigurationProperties |
绑定配置到JavaBean | 读取application.yml |
@ConditionalOnClass |
类路径存在时生效 | 自动配置条件 |
@RestController |
@Controller + @ResponseBody |
RESTful API开发 |
@Async |
异步方法执行 | 耗时操作非阻塞处理 |
面试突击:为什么Spring推荐构造器注入?
答案:1) 保证依赖不可变 2) 避免循环依赖 3) 更易测试 4) 避免NPE
掌握Spring注解的核心价值:
✅ 减少50%以上的XML配置
✅ 精准解决依赖注入问题
✅ 编写更优雅的业务代码
✅ 深度理解Spring框架设计
✅ 面试中展现技术深度