Spring提供了多种注入方式,每种方式都有自己的特点和适用场景。下面跟大帅们聊聊这些注入方式。

1. 构造器注入(Constructor Injection)

构造器注入是最直观的一种方式。你通过类的构造函数来传入依赖对象。这种方式的好处是,一旦对象创建了,依赖项就固定了,不会改变。

示例代码
public class UserService {
    private UserRepository userRepository;

    // 构造器注入
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void addUser(User user) {
        userRepository.save(user);
    }
}
配置文件(XML配置)
<bean id="userRepository" class="com.example.repository.UserRepositoryImpl" />
<bean id="userService" class="com.example.service.UserService">
    <constructor-arg ref="userRepository" />
</bean>
使用场景
  • 当你的依赖项是必需的,而且在对象创建时必须提供。
  • 你希望对象的依赖项在创建后不再改变。
为什么用
  • 强制性依赖:确保在对象创建时所有必需的依赖项都已经被正确初始化。
  • 不可变性:构造器注入的对象在创建后不能改变依赖项,这样更安全,不容易出错。
2. 设值注入(Setter Injection)

设值注入通过类的setter方法来传入依赖对象。这种方式的好处是灵活性高,你可以在对象创建后随时改变依赖项。

示例代码
public class UserService {
    private UserRepository userRepository;

    // 设值注入
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void addUser(User user) {
        userRepository.save(user);
    }
}
配置文件(XML配置)
<bean id="userRepository" class="com.example.repository.UserRepositoryImpl" />
<bean id="userService" class="com.example.service.UserService">
    <property name="userRepository" ref="userRepository" />
</bean>
使用场景
  • 当你的依赖项是可选的,或者可以在对象创建后动态改变。
  • 你需要在单元测试中方便地注入mock对象。
为什么用
  • 灵活性:可以在对象创建后随时改变依赖项。
  • 可测试性:通过setter方法可以轻松地注入mock对象,方便进行单元测试。
3. 字段注入(Field Injection)

字段注入是最简单的一种方式。你直接在类的字段上使用@Autowired注解来注入依赖对象。这种方式的好处是代码简洁,但缺点是你失去了对依赖项的控制。

示例代码
import org.springframework.beans.factory.annotation.Autowired;

public class UserService {
    @Autowired
    private UserRepository userRepository;

    public void addUser(User user) {
        userRepository.save(user);
    }
}
配置文件(Java配置)
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {
    @Bean
    public UserRepository userRepository() {
        return new UserRepositoryImpl();
    }

    @Bean
    public UserService userService() {
        return new UserService();
    }
}
使用场景
  • 当你的依赖项很多,使用构造器或setter注入会让代码变得冗长。
  • 你在做快速开发或原型设计,希望代码简洁明了。
为什么用
  • 简洁:代码简洁,不需要写setter方法或构造器参数。
  • 快速开发:适用于快速开发和原型设计,节省时间和精力。
4. 注解注入(Annotation Injection)

注解注入结合了字段注入和设值注入的优点,同时提供了更多的灵活性。你可以使用@Autowired@Resource@Inject等注解来注入依赖对象。

示例代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import javax.inject.Inject;

public class UserService {
    @Autowired
    @Qualifier("userRepository")
    private UserRepository userRepository;

    @Inject
    private EmailService emailService;

    public void addUser(User user) {
        userRepository.save(user);
        emailService.sendEmail(user.getEmail(), "Welcome!");
    }
}
配置文件(Java配置)
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {
    @Bean
    public UserRepository userRepository() {
        return new UserRepositoryImpl();
    }

    @Bean
    public EmailService emailService() {
        return new EmailServiceImpl();
    }

    @Bean
    public UserService userService() {
        return new UserService();
    }
}
使用场景
  • 当你需要更细粒度地控制依赖注入,比如指定特定的bean。
  • 你在不同的地方使用相同类型的多个bean。
为什么用
  • 细粒度控制:可以使用@Qualifier等注解来指定特定的bean。
  • 多框架支持@Inject注解是JSR-330标准的一部分,支持多个IoC容器。
总结

Spring框架提供了多种依赖注入方式,每种方式都有自己的特点和适用场景。选择合适的注入方式可以让你的代码更简洁、更易于维护。下面是各种注入方式的简要总结:

  • 构造器注入:适合强制性依赖项,确保对象的完整性和不可变性。
  • 设值注入:适合可选依赖项,提供更高的灵活性和可测试性。
  • 字段注入:适合快速开发和原型设计,代码简洁。
  • 注解注入:适合需要细粒度控制和多框架支持的场景。

天气变冷了,比彭于晏还要帅的大帅们注意保暖!