NET2Java之十三:Spring IOC

IoC是Spring框架的核心思想之一,用于降低代码之间的耦合度。

常用注解

想使用Spring来管理对象依赖,通常使用注解来实现,常用注解如下:

Component

  • 作用:标记一个类为Spring管理的组件(Bean),会被Spring自动扫描并注册到IoC容器。
  • 初始化:默认是单例(Singleton),如果需要多实例,需要额外添加Scope。
@Component
@Scope("prototype") // 每次注入或获取时都创建新实例
public class MyComponent {
    // ...
}

Configuration&&Bean

  • 作用:标记一个类为配置类,通常用于定义@Bean方法,替代XML配置,该类会被Spring扫描,并用于构建用用上下文。
  • 特点:@Bean方法默认单例,myService()方法,仅在第一次需要注入 MyService时调用一次,通常用于引入第三方库的Bean。
@Configuration
public class AppConfig {
   @Bean
   public MyService myService() {
      return new MyService();
   }
}

Repository

  • 作用:标记一个类为数据访问层(DAO),是Component的特化版本。
  • 特点:默认单例,主要用于数据库操作,会自动处理数据异常。
@Repository
public class UserRepository {
    // JPA/MyBatis 操作
}

Service

  • 作用:标记一个类为业务逻辑层
  • 特点:通常包含业务逻辑,调用@Repository进行数据操作
@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;

    public void saveUser(User user) {
        userRepository.save(user);
    }
}

Controller

  • 作用:标记一个类为Web控制器,处理HTTP请求
  • 特点:默认单例,通常与 @RequestMapping、@GetMapping、@PostMapping等配合使用,返回视图或 REST API 数据。
@Controller
public class UserController {
    @GetMapping("/users")
    public String listUsers(Model model) {
        model.addAttribute("users", userService.findAll());
        return "users";
    }
}

ResetController

  • 作用:@Controller+ @ResponseBody,用于REST API,直接返回 JSON/XML 数据。
@RestController
@RequestMapping("/api/users")
public class UserApiController {
    @GetMapping
    public List<User> getAllUsers() {
        return userService.findAll();
    }
}

注入技巧

只有通过 Spring 容器创建和管理的对象(如 @Component、@Service、@Bean等),Spring 才会自动处理 @Autowired依赖注入,比如:

@Service
public class MyService {
    @Autowired
    private MyRepository myRepository;  // 依赖注入

    public void doSomething() {
        if (myRepository == null) {
            System.out.println("myRepository 是 null!");
        } else {
            System.out.println("myRepository 已注入");
        }
    }
}

// 测试代码
public class Main {
    public static void main(String[] args) {
        MyService myService = new MyService();  // 直接 new,而不是从 Spring 获取
        myService.doSomething();  // 输出:"myRepository 是 null!"
    }
}

这个示例中,myRepository为null,因为其绕过了Spring的依赖注入机制,可以通过ApplicationContextAware来实现使用时注入:


@Component
public class SpringContextHolder implements ApplicationContextAware {
    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        context = applicationContext;
    }

    public static <T> T getBean(Class<T> beanClass) {
        return context.getBean(beanClass);
    }

    public static <T> T getBean(String name, Class<T> beanClass) {
        return context.getBean(name, beanClass);
    }
}

使用:

public class MyService {
    private LLMService llmService;
    public MyService () {
        llmService = SpringContextHolder.getBean(LLMService.class);
    }
}

静态变量的注入

在非静态方法中注入依赖,然后在 @PostConstruct方法中赋值给静态变量,@PostConstruct会在 Bean 初始化完成后执行,此时 myRepository已经被 Spring 注入。

@Service
public class MyService {
    private static MyRepository myRepositoryStatic; // 静态变量

    @Autowired
    private MyRepository myRepository; // 非静态注入

    @PostConstruct
    public void init() {
        myRepositoryStatic = myRepository; // 初始化静态变量
    }

    public static void doSomething() {
        if (myRepositoryStatic != null) {
            myRepositoryStatic.queryData();
        }
    }
}
posted @ 2025-08-14 13:27  古法编程  阅读(6)  评论(0)    收藏  举报