Spring 依赖注入

1、java注解(Anotation)

java 推出一种注释机制Annotation,它可以在编译、运行阶段读取。
这个特点带来了很多扩展空间,并且不会污染源代码。在Spring中就重度使用Annotation

Annotation也是一个java类:
在这里插入图片描述
图中为一个注解类Annotation的定义,由此可见Annotation由多个Annotation组合而成。

1.1、@Target

java.lang.annotation.Target自身就是一个注解,它只有一个属性(并且这个属性是数组),用于设定该注解(Target修饰的注解)的作用目标范围,比如说是作用于类,还是方法,还是属性等。因为是数组,所以可以设定多个目标。
具体的可作用类型配置在java.lang.annotation.ElementType枚举类中,如下列举几个常用的:

  • ElementType.TYPE

    作用于类

  • ElementType.FIELD

    作用于类的属性

  • ElementType.MATHOD

    作用于类的方法

  • ElementType.PARAMETER

    作用于类的参数

比如想要Target修饰的注解作用于类和方法:

@Target({ElementType.TYPE,ElementType.METHOD})

这四种类型的注解例子:

1.1.1、ElementType.TYPE

@Service
public class MessageServiceImpl implements MessageService{

    public String getMessage() {
         return "Hello World!";
    }

}

1.1.2、ElementType.FIELD

public class MessageServiceImpl implements MessageService{

    @Autowired
    private WorkspaceService workspaceService;

}

1.1.3、ElementType.MATHOD

public class MessageServiceImpl implements MessageService{

    @ResponseBody
    public String getMessage() {
         return "Hello World!";
    }

}

1.1.4、ElementType.PARAMETER

public class MessageServiceImpl implements MessageService{

    public String getMessage(@RequestParam("msg")String msg) {
         return "Hello "+msg;
    }

}

1.2、@Retention

java.lang.annotation.Retention,该注解用于声明注解生命周期,就是在编译、运行的哪个环节有效,它的值定义在java.lang.annotation.RetentionPolicy枚举类中,有三个枚举值:

  1. SOURCE:纯注释作用
  2. CLASS:编译阶段有效
  3. RUNTIME:运行阶段有效
@Retention(RetentionPolicy.RUNTIME);

表示运行阶段有效

1.3、@Documented

java.lang.annotation.Documented,这个注解的作用是将所修饰的注解中的元素包含到JavaDoc文档中,一般情况下都会加这个注解。

1.4、@interface

声明当前java类型为Annotation

1.5、Annotation 的属性

未完待续

2、Spring Bean

IoC(Inversion of Control,控制反转)容器是Spring框架最核心组件。它是面向对象编程中的一种设计原则,可降低计算机代码之间的耦合度。
Spring框架中主要通过依赖注入(Dependnecy Injection,DI)来实现IoC。Spring中所有的java对象都会通过IoC容器转变为Bean(Spring对象的一种称呼),构成应用程序主干 和 由Spring IoC容器管理 的对象称为beans,beans和它们之间的依赖关系反映在容器使用的配置元数据中。基本上所有的Bean都是由接口+实现类完成的,用户想获取Bean的实例直接从IoC里获取就好了,不必关心实现类。
在这里插入图片描述
Spring主要有两种配置元数据的方式,一种是基于XML、一种是基于Annotation方案的,目前主流的方案是基于Annotation的。
org.springframework.context.ApplicationContext接口类定义容器的对外服务,通过这个接口,可以轻松地从IoC容器中获取Bean对象。使用前得先启动IoC容器。
Annotation类型的IoC容器对应的类是:org.springframework.context.annotation.AnnotationConfigApplicationContext
启动IoC容器的代码:

ApplicationContext context = new AnnotationConfigApplicationContext("fm.douban");

这样就会启动IoC容器,并且自动加载包fm.douban下的Bean,该包内引用了Spring注解的类都会被加载。
AnnotationConfigApplicationContext类的构造函数有两种:

  • AnnotationConfigApplicationContext(String basePackage),根据包名实例化
  • AnnotationConfigApplicationContext(Class clazz),根据自定义包扫描行为进行实例化

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

  • org.springframework.stereotype.Component
    @Component注解是通用的Bean注解,其余三个注解都是扩展自Component。
  • org.springframework.stereotype.Service
    @Service正如这个名称一样,代表的是Service Bean。
  • org.springframework.stereotype.Controller
    @Controller作用于Web Bean。
  • org.springframework.stereotype.Repository
    @Repository作用于持久化相关Bean。

以上四个注解都可以被IoC容器加载,一般情况下使用@Service,,Web服务就用@Controller。


IoC容器就像一个大工厂一样,我们不关心工厂如何生产,只需要使用工厂生产的产品。

依赖注入第一步启动容器,然后才是依赖注入行为。
依赖注入是一种编程思想,是一种获取其他实例的规范。
依赖注入让我们得到Bean实例相当简单,只需要在属性上添加注解(前提是当前需要获取Bean实例的类是Spring Bean,即当前类能被IoC容器加载)。

@Autowired
private SongService songService;

Autowired的路径是org.springframework.beans.factory.annotation.Autowired

3、Spring Resource

在java内部,一般把文件路径称为classpath,所以读取内部文件就是从classpath内读取,classpath指定的文件不能解析成File对象(但是可以解析成InputStream对象)。
classpath类似虚拟目录,它的根目录是从/开始代表的是src/main/java或者src/main/resources目录

3.1、用类加载器加载classpath里的文件

Java拥有很多丰富的第三方类库给我们使用,读取文件,我们可以使用commons-io这个库来,需要在pom.xml下添加依赖

<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.6</version>
</dependency>

测试代码:

public class Test {
  public static void main(String[] args) {
    // 读取 classpath 的内容
    InputStream in = Test.class.getClassLoader().getResourceAsStream("data.json");
    // 使用 commons-io 库读取文本
    try {
      String content = IOUtils.toString(in, "utf-8");
      System.out.println(content);
    } catch (IOException e) {
      // IOUtils.toString 有可能会抛出异常,需要我们捕获一下
      e.printStackTrace();
    }
  }
}
InputStream in = Test.class.getClassLoader().getResourceAsStream("data.json");

这段代码的含义是从java运行的类加载器(ClassLoader)实例中查找文件,test.class就是test.java类编译后的java class文件

3.2、用Spring Resource加载文件

Spring擅长的就是封装各种服务 。
在Spring中定义了一个org.springframework.core.io.Resource类来封装文件,这个类的优势在与可以封装File和classpath文件
并且在Spring中通过org.springframework.core.io.ResourceLoader服务来提供文件的读写,可以在任意的Spring Bean中引入ResourceLoader

用Resource来构建服务:

public interface FileService {
    String getContent(String name);
}
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.InputStream;

@Service
public class FileServiceImpl implements FileService {

    @Autowired
    private ResourceLoader loader;

    @Override
    public String getContent(String name) {
        try {
            InputStream in = loader.getResource(name).getInputStream();
            return IOUtils.toString(in,"utf-8");
        } catch (IOException e) {
           return null;
        }
    }
}

服务的调用:

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Application {

    public static void main(String[] args) {

        ApplicationContext context = new AnnotationConfigApplicationContext("fm.douban");

        FileService fileService = context.getBean(FileService.class);
        String content = fileService.getContent("classpath:data/urls.txt");
        System.out.println(content);

        String content2 = fileService.getContent("https://www.zhihu.com/question/34786516/answer/822686390");
        System.out.println(content2);

    }
}

代码中content2获取到的是网页的内容。
所以,Spring Resource中,把本地文件、classpath文件、远程文件都封装成Resource对象来统一加载。

4、Spring Bean的生命周期

在这里插入图片描述
其中 init() 方法(init这个名称是可以任意的,因为我们是通过注解来声明init)

import javax.annotation.PostConstruct;
@Service
public class SubjectServiceImpl implements SubjectService {
  @PostConstruct
  public void init(){
      System.out.println("启动啦");
  }
}  

只要添加了@PostConstruct注解,就代表方法在Spring Bean启动后会自动执行。(所以可以用它来代替static代码块)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值