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注解的扩展,即它是最通用的。

相关推荐
上官浩仁22 分钟前
springboot excel 表格入门与实战
java·spring boot·excel
en-route2 小时前
如何在 Spring Boot 中指定不同的配置文件?
java·spring boot·后端
栀椩3 小时前
springboot配置请求日志
java·spring boot·后端
Swift社区4 小时前
如何解决 Spring Bean 循环依赖
java·后端·spring
Pretend° Ω4 小时前
LRU缓存详解:用C语言实现高效数据管理
运维·c语言·spring·缓存·lru·双向链表
学Java的bb7 小时前
后端Web实战-Spring原理
java·spring boot·spring
码畜也有梦想7 小时前
springboot响应式编程笔记
java·spring boot·笔记
王同学 学出来8 小时前
跟做springboot尚品甄选项目(二)
java·spring boot·后端
计算机毕业设计指导9 小时前
基于Spring Boot + Vue 3的社区养老系统设计与实现
vue.js·spring boot·后端
野生程序员y9 小时前
Spring DI/IOC核心原理详解
java·后端·spring