@Autowired是Spring框架中实现依赖注入的核心注解,采用类型优先的自动装配策略。其设计初衷是为了简化XML配置,实现更优雅的组件管理。
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD,
ElementType.PARAMETER, ElementType.FIELD,
ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
boolean required() default true;
}
作用目标:构造方法、普通方法、参数、字段、注解
required属性:默认为true,强制依赖必须存在;设为false允许注入null值
典型应用:
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
// 业务方法省略...
}
特点分析:
简洁直观,减少样板代码
存在循环依赖风险
不利于单元测试(需通过反射设置字段)
实现方式:
@Controller
public class UserController {
private UserService userService;
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
}
优势比较:
符合JavaBean规范
支持可选依赖(结合required=false)
方便后期扩展
最佳实践:
@Service
public class UserServiceImpl implements UserService {
private final UserDao userDao;
@Autowired
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
}
核心优势:
保证依赖不可变(final修饰)
避免循环依赖
明确依赖关系
Spring官方推荐方式
特殊用法:
@Controller
public class UserController {
private final UserService userService;
public UserController(@Autowired UserService userService) {
this.userService = userService;
}
}
适用场景:
自定义工厂方法参数注入
第三方类改造时的参数注入
简化规则:
@Service
public class UserServiceImpl implements UserService {
// 当类中仅有一个构造方法时,@Autowired可省略
public UserServiceImpl(UserDao userDao) {
this.userDao = userDao;
}
}
注意事项:
多个构造方法时必须显式指定
推荐保留@Autowired注解增强可读性
问题场景:
@Repository
public class UserDaoJdbcImpl implements UserDao {}
@Repository
public class UserDaoMybatisImpl implements UserDao {}
解决方案一:@Qualifier
@Service
public class UserService {
@Autowired
@Qualifier("userDaoJdbcImpl")
private UserDao userDao;
}
解决方案二:@Primary
@Repository
@Primary
public class UserDaoJdbcImpl implements UserDao {}
@Autowired(required = false)
private Optional messageService;
@Autowired
private List validators;
@Autowired
private Map processorMap;
可能原因:
组件未扫描(检查@ComponentScan配置)
接口多个实现未指定名称
依赖作用域不匹配
解决方案:
使用@Qualifier明确指定Bean名称
设置@Primary注解
缩小组件扫描范围
推荐解决方案:
// ServiceA.java
@Service
public class ServiceA {
private final ServiceB serviceB;
public ServiceA(ServiceB serviceB) {
this.serviceB = serviceB;
}
}
// ServiceB.java
@Service
public class ServiceB {
private final ServiceA serviceA;
public ServiceB(ServiceA serviceA) {
this.serviceA = serviceA;
}
}
Spring三级缓存解决方案:
提前暴露半成品对象
通过ObjectFactory延迟注入
最终完成属性填充
注入方式 | 适用场景 | 注意事项 |
---|---|---|
构造器注入 | 强依赖、必须依赖 | 推荐首选方式 |
Setter注入 | 可选依赖、配置类 | 避免过度使用 |
字段注入 | 测试类、简单组件 | 生产代码慎用 |
保持依赖不可变性(尽量使用final修饰)
避免在静态字段上使用@Autowired
组合使用Lombok减少样板代码:
@Service
@RequiredArgsConstructor
public class OrderService {
private final OrderRepository orderRepository;
}
尽量缩小@Autowired搜索范围
优先使用具体类型而非接口
合理使用@Lazy延迟初始化
逐步迁移到jakarta.annotation包
兼容Spring 6+与Jakarta EE 9+
@Service
class UserService @Autowired constructor(
private val userRepository: UserRepository
)
@Autowired
private Mono userServiceMono;
通过本文的深度解析,开发者可以全面掌握@Autowired在Spring生态中的各种使用姿势,构建出既符合规范又高效可靠的Spring应用程序。注解驱动的开发方式正在成为现代Java开发的标配,深入理解其原理和最佳实践是每个Spring开发者的必修课。