@Autowired 的作用是什么?

本文介绍了Spring框架中@Autowired注解的用途及其使用方法。通过实例展示了@Autowired如何应用于成员变量、方法和构造函数上,并解释了其默认按类型装配的机制及如何结合@Qualifier实现按名称装配。

@Autowired 的作用是什么?

@Autowired 是一个注释,它可以对类成员变量、方法及构造函数进行标注,让 spring 完成 bean 自动装配的工作。
@Autowired 默认是按照类去匹配,配合 @Qualifier 指定按照名称去装配 bean。

常见用法

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import blog.service.ArticleService;
import blog.service.TagService;
import blog.service.TypeService;

@Controller
public class TestController {

	//成员属性字段使用 @Autowired,无需字段的 set 方法
	@Autowired
	private TypeService typeService;
	
	
	//set 方法使用 @Autowired
	private ArticleService articleService;
	@Autowired
	public void setArticleService(ArticleService articleService) {
		this.articleService = articleService;
	}

	//构造方法使用 @Autowired
	private TagService tagService;
	@Autowired
	public TestController(TagService tagService) {
		this.tagService = tagService; 
	}
	
}

 


【Java面试题与答案】整理推荐

 

<think>我们正在讨论Spring框架中的@Autowired注解。这个注解用于自动装配依赖,是Spring依赖注入(DI)的核心注解之一。 下面我将详细解释@Autowired注解,包括它的作用、使用方式、工作原理以及一些高级用法,并附上代码示例。 </think>### `@Autowired` 注解详解 `@Autowired` 是 Spring 框架中最核心的注解之一,用于实现**依赖注入(Dependency Injection)**。它的主要作用是让 Spring 容器自动将所需的 Bean 实例注入到目标对象中,无需手动创建依赖对象。 --- ### 核心功能解析 #### 1. 自动装配(Auto-wiring) Spring 容器会自动查找匹配的 Bean 并注入到标记了 `@Autowired` 的字段、构造函数或方法中。 ```java @Service public class UserService { // 自动注入 UserRepository @Autowired private UserRepository userRepo; public User getUser(Long id) { return userRepo.findById(id); } } ``` #### 2. 依赖注入方式 支持三种注入方式: ```java // 1. 字段注入(最常用) @Autowired private OrderService orderService; // 2. 构造函数注入(推荐) private final PaymentService paymentService; @Autowired // Spring 4.3+ 可省略 public UserService(PaymentService paymentService) { this.paymentService = paymentService; } // 3. Setter方法注入 private EmailService emailService; @Autowired public void setEmailService(EmailService emailService) { this.emailService = emailService; } ``` #### 3. 依赖解析流程 Spring 解决依赖的顺序: ```mermaid graph TD A[查找匹配类型的Bean] --> B{找到多个?} B -->|是| C[按名称匹配] B -->|否| D[直接注入] C --> E[使用@Qualifier指定] C --> F[使用主Bean @Primary] C --> G[按字段/参数名匹配] ``` --- ### 完整使用示例 #### 基础用法 ```java // 配置类 @Configuration @ComponentScan("com.example") public class AppConfig { @Bean public DatabaseConfig databaseConfig() { return new DatabaseConfig("jdbc:mysql://localhost:3306/mydb", "admin", "pass123"); } } // 服务类 @Service public class DataService { private final DatabaseConfig dbConfig; @Autowired public DataService(DatabaseConfig dbConfig) { this.dbConfig = dbConfig; } public void connect() { System.out.println("连接数据库: " + dbConfig.getUrl()); } } // 主应用 public class Application { public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); DataService service = context.getBean(DataService.class); service.connect(); // 输出: 连接数据库: jdbc:mysql://localhost:3306/mydb } } ``` #### 处理多个同类型 Bean ```java @Configuration public class PaymentConfig { @Bean(name = "creditCardProcessor") public PaymentProcessor creditCardProcessor() { return new CreditCardProcessor(); } @Bean @Primary // 标记为首选Bean public PaymentProcessor paypalProcessor() { return new PayPalProcessor(); } } @Service public class OrderService { // 方式1: 使用@Qualifier指定Bean名称 @Autowired @Qualifier("creditCardProcessor") private PaymentProcessor specificProcessor; // 方式2: 注入所有同类型Bean @Autowired private List<PaymentProcessor> allProcessors; // 方式3: 使用首选Bean(未指定时自动注入@Primary) @Autowired private PaymentProcessor primaryProcessor; } ``` #### 可选依赖注入 ```java @Service public class NotificationService { // required=false 表示可选依赖(找不到Bean时不报错) @Autowired(required = false) private SmsService smsService; public void sendNotification(String message) { // 优先使用邮件通知 emailService.send(message); // 如果SMS服务存在则使用 if (smsService != null) { smsService.send(message); } } } ``` --- ### 工作原理深度解析 #### 1. 处理阶段 Spring 容器在创建 Bean 时经历以下阶段: 1. **实例化**:调用构造函数创建对象 2. **属性填充**:处理 `@Autowired` 注入 3. **初始化**:调用 `@PostConstruct` 方法 #### 2. 底层实现 `@Autowired` 由 `AutowiredAnnotationBeanPostProcessor` 处理: ```java public class AutowiredAnnotationBeanPostProcessor implements BeanPostProcessor { public PropertyValues postProcessProperties( PropertyValues pvs, Object bean, String beanName) { // 1. 查找所有需要自动装配的字段和方法 InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass()); try { // 2. 执行注入操作 metadata.inject(bean, beanName, pvs); } catch (Throwable ex) { throw new BeanCreationException(beanName, "Injection failure", ex); } return pvs; } } ``` #### 3. 解决循环依赖 Spring 使用三级缓存解决循环依赖问题: ```mermaid graph LR A[创建A] --> B[实例化A] B --> C[提前暴露A(半成品)] C --> D[注入B到A] D --> E[创建B] E --> F[实例化B] F --> G[注入A到B] G --> H[完成B初始化] H --> I[完成A初始化] ``` --- ### 最佳实践与注意事项 #### 1. 推荐使用构造函数注入 ```java @Service public class ProductService { private final InventoryService inventoryService; private final PricingService pricingService; // 单一构造函数可省略@Autowired(Spring 4.3+) public ProductService(InventoryService inventoryService, PricingService pricingService) { this.inventoryService = inventoryService; this.pricingService = pricingService; } } ``` **优点**: - 强制依赖不可变(final) - 避免NPE(依赖在构造时即完成) - 更容易测试(无需反射) #### 2. 避免的常见错误 ```java // 错误1: 在静态字段上使用 @Autowired private static CacheManager cacheManager; // 无法注入 // 错误2: 注入基础类型 @Autowired private int timeout; // 需要@Value注解 // 错误3: 混淆注入类型 public interface Logger { /*...*/ } @Component public class FileLogger implements Logger { /*...*/ } @Component public class DatabaseLogger implements Logger { /*...*/ } @Service public class LogService { @Autowired private Logger logger; // 错误:有多个实现类 } ``` #### 3. 与 Lombok 结合使用 ```java @Service @RequiredArgsConstructor // Lombok生成构造函数 public class OrderService { private final OrderRepository orderRepo; private final PaymentGateway paymentGateway; @Autowired(required = false) // 可选依赖 private DiscountService discountService; } ``` 等效代码: ```java @Service public class OrderService { private final OrderRepository orderRepo; private final PaymentGateway paymentGateway; private DiscountService discountService; public OrderService(OrderRepository orderRepo, PaymentGateway paymentGateway) { this.orderRepo = orderRepo; this.paymentGateway = paymentGateway; } @Autowired public void setDiscountService(DiscountService discountService) { this.discountService = discountService; } } ``` --- ### 与其他注入方式的对比 | **特性** | `@Autowired` | JSR-330 `@Inject` | JSR-250 `@Resource` | |------------------------|----------------------|-----------------------|-----------------------| | **标准** | Spring 特有 | Java 标准 | Java 标准 | | **按名称注入** | 需要 `@Qualifier` | 需要 `@Named` | 原生支持(`name`属性) | | **可选依赖** | `required=false` | 无直接支持 | 无 | | **构造函数注入** | 支持 | 支持 | 不支持 | | **集合注入** | 支持 | 支持 | 不支持 | | **与Spring集成** | 最优 | 需额外依赖 | 需额外依赖 | --- ### 高级应用场景 #### 1. 自定义限定符 ```java @Target({ElementType.FIELD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Qualifier public @interface ProductionEnv { } // 使用自定义限定符 @Configuration public class EnvConfig { @Bean @ProductionEnv public DataSource productionDataSource() { return new DataSource("prod-db-url"); } } @Service public class ReportService { @Autowired @ProductionEnv private DataSource dataSource; // 注入生产环境数据源 } ``` #### 2. 方法注入 ```java @Component public class EventPublisher { // 注入到任意方法 @Autowired public void setupListeners( @Qualifier("emailListener") EventListener listener1, @Qualifier("smsListener") EventListener listener2) { registerListener(listener1); registerListener(listener2); } } ``` #### 3. 泛型依赖注入 ```java public abstract class BaseService<T> { @Autowired protected Repository<T> repository; // 自动注入对应泛型的Repository } @Service public class UserService extends BaseService<User> {} // 注入 UserRepository @Service public class ProductService extends BaseService<Product> {} // 注入 ProductRepository ```
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值