Spring 中注入 Bean 有几种方式?
1 个回答
人一旦不害怕失去,态度就会变得随意,随你意,你随意。红蝶Bean 注入是指在 Spring 容器中**将一个 Bean 依赖注入到另一个 Bean 中**,常见的方式如下: ## **1. `@Autowired`(Spring 官方推荐方式)** `@Autowired` 是 Spring 提供的 **自动注入** 机制,可以作用在: - **字段** - **构造器** - **Setter 方法** ### **(1)字段注入(不推荐)** ```java @Component public class MyService { @Autowired private MyRepository myRepository; } ``` 🔹 **缺点**: - **不利于单元测试**(不能在构造函数中注入 Mock 对象)。 - **破坏封装性**(直接访问私有字段)。 ✅ **官方推荐使用构造器注入!** ### **(2)构造器注入(推荐)** ```java @Component public class MyService { private final MyRepository myRepository; @Autowired public MyService(MyRepository myRepository) { this.myRepository = myRepository; } } ``` 🔹 **优点**: - **保证依赖不可变**(`final` 字段)。 - **便于单元测试**(可以手动创建对象,传入 Mock 依赖)。 - **Spring 4.3+ 以后,单个构造函数可以省略 `@Autowired`**: ```java @Component public class MyService { private final MyRepository myRepository; public MyService(MyRepository myRepository) { // 无需 @Autowired this.myRepository = myRepository; } } ``` ### **(3)Setter 注入** ```java @Component public class MyService { private MyRepository myRepository; @Autowired public void setMyRepository(MyRepository myRepository) { this.myRepository = myRepository; } } ``` ✅ **适用于可选依赖**(某些 Bean 可能不是必须的)。 ❌ **不推荐用于强制性依赖**(必须有该 Bean 才能工作)。 ## **2. `@Resource` 和 `@Inject`(JSR-250 & JSR-330 标准注解)** Spring 还支持 Java 标准的注解 `@Resource` 和 `@Inject`: - `@Resource`(JSR-250):默认**按名称**注入,找不到按**类型**匹配。 - `@Inject`(JSR-330):**等同于 `@Autowired`**,但**不支持 `required=false`**。 ### **(1)`@Resource`(按名称优先)** ```java @Component public class MyService { @Resource(name = "myRepository") private MyRepository myRepository; } ``` - 先**按 Bean 名称匹配** `myRepository`。 - 如果找不到,再**按类型匹配**。 ### **(2)`@Inject`(和 `@Autowired` 类似)** ```java @Component public class MyService { @Inject private MyRepository myRepository; } ``` **等价于 `@Autowired`,但没有 `required=false` 选项**。 ✅ **适用于**:如果项目需要 **兼容 JavaEE 规范** 或 **使用 Spring 之外的 IoC 容器**。 ## **3. XML 配置注入** Spring 3.x 及以前的方式,现在已经不常用了,但仍然支持。 **示例 (`beans.xml`)** ```xml <bean id="myRepository" class="com.example.MyRepository"/> <bean id="myService" class="com.example.MyService"> <property name="myRepository" ref="myRepository"/> </bean> ``` - **属性注入**(类似于 `@Autowired`)。 - **构造器注入**: ```xml <bean id="myService" class="com.example.MyService"> <constructor-arg ref="myRepository"/> </bean> ``` **加载 XML 配置** ```java ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); MyService myService = context.getBean(MyService.class); ``` ✅ **适用于**: - **老项目(Spring 3.x 及以下版本)**。 - **XML 配置比较清晰,适用于某些企业规范项目**。 ## **4. 构造器自动注入(Spring 4.3+)** Spring 4.3 之后,**如果类中只有一个构造方法,则可以省略 `@Autowired`,Spring 会自动注入**: ```java @Component public class MyService { private final MyRepository myRepository; public MyService(MyRepository myRepository) { // 不需要 @Autowired this.myRepository = myRepository; } } ``` ✅ **官方推荐的方式,强制依赖注入,避免 NPE**。 ## **5. `FactoryBean` 方式** 如果 Bean 需要 **动态创建**,可以使用 `FactoryBean`: ```java @Component public class MyFactoryBean implements FactoryBean<MyService> { @Override public MyService getObject() { return new MyService(new MyRepository()); } @Override public Class<?> getObjectType() { return MyService.class; } } ``` ✅ **适用于**: - **动态代理 Bean(如 AOP)**。 - **创建复杂对象**(如数据库连接池)。 ## **6. `@DubboReference`(Dubbo RPC 框架)** 如果项目使用 **Dubbo 远程调用**,可以用 `@DubboReference` 注入远程服务: ```java @DubboReference(version = "1.0.0") private RemoteService remoteService; ``` ✅ **适用于分布式 RPC 远程服务调用**。 ## **7. `@Value` 注入** 用于**注入配置文件中的值**: ```java @Component public class AppConfig { @Value("${app.name}") private String appName; } ``` **配置文件** ```properties app.name=My Application ``` ✅ **适用于**: - **动态参数注入**(如数据库连接、API 密钥)。 - **避免硬编码,提高可配置性**。 ## **8. `@Profile` 按环境注入** 可根据**不同环境**(如 dev、prod)创建不同的 Bean: ```java @Configuration public class DataSourceConfig { @Bean @Profile("dev") public DataSource devDataSource() { return new H2Database(); } @Bean @Profile("prod") public DataSource prodDataSource() { return new MySQLDatabase(); } } ``` **指定环境** ```yaml spring: profiles: active: dev ``` ✅ **适用于多环境配置(开发、测试、生产)**。 ## **总结** | 方式 | 适用场景 | 代码示例 | |------|---------|---------| | `@Autowired` | **推荐,Spring 官方推荐方式** | `@Autowired private MyBean myBean;` | | `@Resource` | **按名称优先匹配** | `@Resource(name="myBean") private MyBean myBean;` | | `@Inject` | **等价于 `@Autowired`** | `@Inject private MyBean myBean;` | | XML 配置 | **Spring 3.x 及以下老项目** | `<property name="myBean" ref="myBean"/>` | | **构造器自动注入** | **Spring 4.3+ 推荐** | `public MyService(MyRepository repo) {}` | | `FactoryBean` | **动态创建 Bean** | `public class MyFactoryBean implements FactoryBean<MyBean> {}` | | `@DubboReference` | **Dubbo RPC 远程调用** | `@DubboReference(version="1.0.0") private RemoteService service;` | | `@Value` | **配置文件参数注入** | `@Value("${app.name}") private String appName;` | | `@Profile` | **按环境注入** | `@Profile("dev") public DataSource devDataSource()` |发布于 2025-03-08 11:37 •IP属地 广西举报评论收藏
公众号进入网站体验更佳

