Spring 提供了多种依赖注入(Dependency Injection, DI)的方式,用于将依赖对象注入到目标对象中。以下是 Spring 中常见的几种注入方式:
1. 基于构造函数的注入(Constructor Injection)
通过构造函数将依赖注入到目标对象中。Spring 容器会调用目标类的构造函数,并传入所需的依赖。
优点:
- 保证依赖不可变(
final
字段)。 - 适合强制依赖的场景。
- 便于单元测试。
示例:
public class UserService {private final UserRepository userRepository;@Autowired // 可省略public UserService(UserRepository userRepository) {this.userRepository = userRepository;}}public class UserService { private final UserRepository userRepository; @Autowired // 可省略 public UserService(UserRepository userRepository) { this.userRepository = userRepository; } }public class UserService { private final UserRepository userRepository; @Autowired // 可省略 public UserService(UserRepository userRepository) { this.userRepository = userRepository; } }
配置:
<bean id="userRepository" class="com.example.UserRepository" /><bean id="userService" class="com.example.UserService"><constructor-arg ref="userRepository" /></bean><bean id="userRepository" class="com.example.UserRepository" /> <bean id="userService" class="com.example.UserService"> <constructor-arg ref="userRepository" /> </bean><bean id="userRepository" class="com.example.UserRepository" /> <bean id="userService" class="com.example.UserService"> <constructor-arg ref="userRepository" /> </bean>
2. 基于 Setter 方法的注入(Setter Injection)
通过 Setter 方法将依赖注入到目标对象中。Spring 容器会调用目标类的 Setter 方法,并传入所需的依赖。
优点:
- 灵活性高,适合可选依赖。
- 符合 JavaBean 规范。
示例:
public class UserService {private UserRepository userRepository;@Autowired // 可省略public void setUserRepository(UserRepository userRepository) {this.userRepository = userRepository;}}public class UserService { private UserRepository userRepository; @Autowired // 可省略 public void setUserRepository(UserRepository userRepository) { this.userRepository = userRepository; } }public class UserService { private UserRepository userRepository; @Autowired // 可省略 public void setUserRepository(UserRepository userRepository) { this.userRepository = userRepository; } }
配置:
<bean id="userRepository" class="com.example.UserRepository" /><bean id="userService" class="com.example.UserService"><property name="userRepository" ref="userRepository" /></bean><bean id="userRepository" class="com.example.UserRepository" /> <bean id="userService" class="com.example.UserService"> <property name="userRepository" ref="userRepository" /> </bean><bean id="userRepository" class="com.example.UserRepository" /> <bean id="userService" class="com.example.UserService"> <property name="userRepository" ref="userRepository" /> </bean>
3. 基于字段的注入(Field Injection)
通过反射直接将依赖注入到目标对象的字段中。Spring 容器会直接访问目标类的字段,并设置所需的依赖。
优点:
- 代码简洁,无需编写构造函数或 Setter 方法。
缺点:
- 不利于单元测试(需要通过反射注入依赖)。
- 隐藏了依赖关系,不够直观。
示例:
public class UserService {@Autowiredprivate UserRepository userRepository;}public class UserService { @Autowired private UserRepository userRepository; }public class UserService { @Autowired private UserRepository userRepository; }
配置:
无需额外配置,Spring 会自动注入。
4. 基于方法的注入(Method Injection)
通过任意方法将依赖注入到目标对象中。Spring 容器会调用目标类的指定方法,并传入所需的依赖。
优点:
- 灵活性高,适合复杂场景。
示例:
public class UserService {private UserRepository userRepository;@Autowiredpublic void injectUserRepository(UserRepository userRepository) {this.userRepository = userRepository;}}public class UserService { private UserRepository userRepository; @Autowired public void injectUserRepository(UserRepository userRepository) { this.userRepository = userRepository; } }public class UserService { private UserRepository userRepository; @Autowired public void injectUserRepository(UserRepository userRepository) { this.userRepository = userRepository; } }
配置:
无需额外配置,Spring 会自动注入。
5. 基于接口的注入(Interface Injection)
通过实现特定接口将依赖注入到目标对象中。Spring 容器会调用接口方法,并传入所需的依赖。
示例:
public interface UserRepositoryAware {void setUserRepository(UserRepository userRepository);}public class UserService implements UserRepositoryAware {private UserRepository userRepository;@Overridepublic void setUserRepository(UserRepository userRepository) {this.userRepository = userRepository;}}public interface UserRepositoryAware { void setUserRepository(UserRepository userRepository); } public class UserService implements UserRepositoryAware { private UserRepository userRepository; @Override public void setUserRepository(UserRepository userRepository) { this.userRepository = userRepository; } }public interface UserRepositoryAware { void setUserRepository(UserRepository userRepository); } public class UserService implements UserRepositoryAware { private UserRepository userRepository; @Override public void setUserRepository(UserRepository userRepository) { this.userRepository = userRepository; } }
配置:
<bean id="userRepository" class="com.example.UserRepository" /><bean id="userService" class="com.example.UserService"><property name="userRepository" ref="userRepository" /></bean><bean id="userRepository" class="com.example.UserRepository" /> <bean id="userService" class="com.example.UserService"> <property name="userRepository" ref="userRepository" /> </bean><bean id="userRepository" class="com.example.UserRepository" /> <bean id="userService" class="com.example.UserService"> <property name="userRepository" ref="userRepository" /> </bean>
6. 基于注解的注入(Annotation-based Injection)
通过注解将依赖注入到目标对象中。Spring 支持多种注解,如 @Autowired
、@Resource
、@Inject
等。
(1)@Autowired
- 默认按类型注入,如果存在多个同类型的 Bean,可以结合
@Qualifier
指定名称。
示例:
public class UserService {@Autowired@Qualifier("userRepository")private UserRepository userRepository;}public class UserService { @Autowired @Qualifier("userRepository") private UserRepository userRepository; }public class UserService { @Autowired @Qualifier("userRepository") private UserRepository userRepository; }
(2)@Resource
- 默认按名称注入,如果未指定名称,则按类型注入。
示例:
public class UserService {@Resource(name = "userRepository")private UserRepository userRepository;}public class UserService { @Resource(name = "userRepository") private UserRepository userRepository; }public class UserService { @Resource(name = "userRepository") private UserRepository userRepository; }
(3)@Inject
- 与
@Autowired
类似,但需要引入javax.inject
依赖。
示例:
import javax.inject.Inject;public class UserService {@Injectprivate UserRepository userRepository;}import javax.inject.Inject; public class UserService { @Inject private UserRepository userRepository; }import javax.inject.Inject; public class UserService { @Inject private UserRepository userRepository; }
7. 基于 Java 配置的注入(Java-based Configuration)
通过 Java 配置类将依赖注入到目标对象中。Spring 容器会调用配置类中的方法,并返回所需的依赖。
示例:
@Configurationpublic class AppConfig {@Beanpublic UserRepository userRepository() {return new UserRepository();}@Beanpublic UserService userService() {return new UserService(userRepository());}}@Configuration public class AppConfig { @Bean public UserRepository userRepository() { return new UserRepository(); } @Bean public UserService userService() { return new UserService(userRepository()); } }@Configuration public class AppConfig { @Bean public UserRepository userRepository() { return new UserRepository(); } @Bean public UserService userService() { return new UserService(userRepository()); } }
8. 基于 XML 配置的注入(XML-based Configuration)
通过 XML 配置文件将依赖注入到目标对象中。Spring 容器会解析 XML 文件,并注入所需的依赖。
示例:
<bean id="userRepository" class="com.example.UserRepository" /><bean id="userService" class="com.example.UserService"><property name="userRepository" ref="userRepository" /></bean><bean id="userRepository" class="com.example.UserRepository" /> <bean id="userService" class="com.example.UserService"> <property name="userRepository" ref="userRepository" /> </bean><bean id="userRepository" class="com.example.UserRepository" /> <bean id="userService" class="com.example.UserService"> <property name="userRepository" ref="userRepository" /> </bean>
总结
Spring 提供了多种依赖注入方式,常见的有:
- 构造函数注入:适合强制依赖。
- Setter 方法注入:适合可选依赖。
- 字段注入:代码简洁,但不利于测试。
- 方法注入:灵活性高。
- 接口注入:通过接口方法注入。
- 注解注入:如
@Autowired
、@Resource
、@Inject
。 - Java 配置注入:通过 Java 配置类注入。
- XML 配置注入:通过 XML 配置文件注入。
根据具体需求选择合适的注入方式,可以提高代码的可维护性和灵活性。
THE END
暂无评论内容