spring依赖注入

IOC容器

首先我们需要知道Spring框架的核心组件,那就是IOC容器,如果没有IOC容器,那么就没有Spring框架。

SpringBean

在Spirng中,任何的java对象都会通过IOC容器而被转化成Bean,这其实是spring对象的一种称呼,在Spring框架里面,我们通常称JAVA对象为bean。而由应用程序主干和IOC容器管理的Java对象统称为beans。其实大部分的bean都是由接口+实现类组成的。因此用户想要获得bean直接从IOC容器里面获得就可以了,而不需要关心实现类。

Spring的配置元数据的格式

Spring配置元数据的格式有两种,第一种是基于xml的,另一种则就是基于Annotation的。我们暂且不管第一种,先用第二种实现。

Spring的Annotation类型来启动IOC容器

其中Annotation对应的类如下所示:

kotlin 复制代码
org.springframework.context.annotation.AnnotationConfigApplicationContext

我们直接举一个例子来启动:

java 复制代码
package fm.douban;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import fm.douban.service.SongService;
import fm.douban.model.Song;

/**
 * Application
 */
public class Application {

  public static void main(String[] args) {
    //这里则是启动fm.douban包下引用了spring注解的类
    ApplicationContext context = new AnnotationConfigApplicationContext("fm.douban");
    // 从容器中获取歌曲服务。
    SongService songService = context.getBean(SongService.class);
    // 获取歌曲
    Song song = songService.get("001");
    System.out.println("得到歌曲:" + song.getName());

  }
}

大家可以看出,上面的从容器中获得歌曲服务为什么不直接这样子写呢?

ini 复制代码
SongService sogService = new SongServiceImpl();
Song song = songService.get("001");

这样子不是更简单嘛?但是我想问你一下。假如出现以下的情况:

即一个Service依赖了非常多的Service,我们需要写多少行代码啊。如下面代码所示:

ini 复制代码
SubjectService subjectService = new SujectServiceImpl();
SongService songService = new SongServiceImpl();
MusicService MusicService = new MusicServiceImpl();
songService.setMusicService(MusicService);
subjectService.setSongService(songService);

使用注解来解决方案

但是如果我们添加了注解让Spring自动管理实例。例如添加 @Service 注解将SongServiceImplSubjectServiceImpl的服务都实现,都标记成 Spring Bean 。如果我们想要使用服务,那么直接使用 AutoWired 注解标记即可。如下面代码所示:

typescript 复制代码
public class SubjectServiceImpl implements SubjectService {

    private SongService songService;
    
    private MusicService musicService;

    //缓存所有专辑数据
    private static Map<String, Subject> subjectMap = new HashMap<>();

    static {
        Subject subject = new Subject();
        //... 省略初始化数据的过程
        subjectMap.put(subject.getId(), subject);
    }

    @Override
    public Subject get(String subjectId) {
        Subject subject = subjectMap.get(subjectId);
        //调用 SongService 获取专辑歌曲
        List<Song> songs = songService.list(subjectId);
        subject.setSongs(songs);
        return subject;
    }

    public void setSongService(SongService songService) {
        this.songService = songService;
    }
}

上面的代码是没有添加注解的,我们可以看到还需要调用setSongService()方法来传入实例,非常麻烦。但是如果将其转化为下面就非常简便了。

java 复制代码
import fm.douban.model.Song;
import fm.douban.model.Subject;
import fm.douban.service.SongService;
import fm.douban.service.SubjectService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class SubjectServiceImpl implements SubjectService {

    @Autowired
    private SongService songService;
    
    @AutoWired
    private MusicService musicService;

    //缓存所有专辑数据
    private static Map<String, Subject> subjectMap = new HashMap<>();

    //这里的static代码块代表这个代码块只会在类的加载时被执行一次。
    static {
        Subject subject = new Subject();
        subject.setId("s001");
        //... 省略初始化数据的过程
        subjectMap.put(subject.getId(), subject);
    }

    @Override
    public Subject get(String subjectId) {
        Subject subject = subjectMap.get(subjectId);
        //调用 SongService 获取专辑歌曲
        List<Song> songs = songService.list(subjectId);
        subject.setSongs(songs);
        return subject;
    }
}

Spring注解总结和拓展

总结

@Service@AutoWired这两个注解是相辅相成的,即如果没有前者的Spring自动管理,又或者没有后者的注解标记。都无法完成依赖注入。

拓展

Spring官方声明为Spring Bean的注解有以下几种。

  • org.springframework.stereotype.Service
  • org.springframework.stereotype.Component
  • org.springframework.stereotype.Controller
  • org.springframework.stereotype.Repository

这四个注解都可以被IOC容器加载,一般的实现类都用Service注解,而web服务则使用Controller注解,其中的三种注解都是Component注解的扩展,即它是最通用的。

相关推荐
MZ_ZXD0011 小时前
springboot旅游信息管理系统-计算机毕业设计源码21675
java·c++·vue.js·spring boot·python·django·php
invicinble1 小时前
springboot的核心实现机制原理
java·spring boot·后端
space62123272 小时前
在SpringBoot项目中集成MongoDB
spring boot·后端·mongodb
金牌归来发现妻女流落街头3 小时前
【从SpringBoot到SpringCloud】
java·spring boot·spring cloud
张3蜂3 小时前
深入理解 Python 的 frozenset:为什么要有“不可变集合”?
前端·python·spring
皮卡丘不断更4 小时前
手搓本地 RAG:我用 Python 和 Spring Boot 给 AI 装上了“实时代码监控”
人工智能·spring boot·python·ai编程
lucky67074 小时前
Spring Boot集成Kafka:最佳实践与详细指南
spring boot·kafka·linq
Coder_Boy_4 小时前
基于Spring AI的分布式在线考试系统-事件处理架构实现方案
人工智能·spring boot·分布式·spring
7哥♡ۣۖᝰꫛꫀꪝۣℋ5 小时前
Spring-cloud\Eureka
java·spring·微服务·eureka
一灰灰blog6 小时前
Spring AI中的多轮对话艺术:让大模型主动提问获取明确需求
数据库·人工智能·spring