springBoot的意图和注解

417 阅读4分钟

1 SpringBoot的意图

SpringBoot的意图就是实现"开闭原则",即已经实现功能的代码不改动,新增需求仍能被加进来.想象一下,在SpringBoot 中写代码时,如果先写接口类,然后再实现这些类, 从而做好了第一个版本的实现。
后面又有新的版本推出时,第2个版本只需要实现这些接口,就可以了,从而不用入侵式的修改已有的代码就可以实现增加的需求,遵守了"开闭 原则"
那么实现"开闭原则"非得要用控制反转实现的容器化吗?是的。以前如果不用容器化,直接new一个实现类,可以吗?可以的, 但, 这样的 代码不好维护,就是类想怎么写就怎么写以及后期怎么修改就怎么修改,由于没有接口类的约束,导致代码可读性差。那么加个接口类约束下可以吗?可 的,这样代码的可读性就高很多,典型的实现就是工厂模式了,如实现化一个工厂类,传入一个参数,在工厂类中实例化一个类返回出来,这样代码的可 读性是高了,但如果如果遇到了需求变更,如增加需求时,不得不在工厂类中修改代码,这不符合"开闭原则",那么有没有一种能获取到类似于工厂模式 的效果又不用侵入式去改动代码呢?有的,就是控制反转的实现--容器化和注入
给出一个接口类型和一个变量名,再由容器去实例化这个类,再根据这个接口类型找出关于这个接口的实现类,然后注入到这个变量名中。这样 看,由于有接口类型,就能知道这个被注入进来的类是怎么用的,这样不用侵入式修改代码就能实现工厂模式带来的可读性。换个角度看,可以把容器看成 是一个巨大的工厂模式,而业务代码就是这个工厂模式的参数而已,而在这个工厂中,分析着所有的业务代码,该实例化就实例化,该注入就注入。这就是 我认为的"容器化"的作用。
当然也有一些附加的优点,如单例模式带来的省内存,由于是共享的,再加个锁,可以起到多线程通信的作用。

2 注解的用法

@Component

@Component打上这个标记的类会自动注入到容器中,一般用于只是单纯地注入到容器中的目的。

@Service

@Service打上这个标记的类会自动注入到容器中,这个相对较于@Component,被用于服务层逻辑的处理类, 就是 写一些策略的实现类,然后被调用的,这样的用法。

@Repository

@Repository打上这个标记的类会自动注入到容器中, 这个相较于@Component,打上这个标记的类,表示这个类 是模型类,也就是对数据库操作的实现类。

@Configuration

这个一时也不知道它的俱体用法, 不过它可以实现注入类的功能,如:
service.java文件中

package com.zhuche.server.service;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TestTmp3 {
    @Bean // 在这里打上@Bean 并返回需要被注入的实现类
    public ITest testTmp4() {
        return new TestTmp();
    }
}

而在调用时,可以注入这个testTmp3的返回类,如:

package com.zhuche.server.api.v1;

import com.zhuche.server.service.ITest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletResponse;

@Controller
@ResponseBody
@RequestMapping("/v1/banner")
public class BannerController {
    @Autowired
    public ITest testTmp4; // <-- 在这里可以直接被注入进来

    @RequestMapping(value = "/test", method = {
            RequestMethod.GET,
    })
    public  String test(HttpServletResponse response) {
        System.out.println(this.getClass().getName());
        testTmp4.hello();
        return "success";
    }
}

@Lazy

打上这个标记的类,SpringBoot会在运行时才注入支容器中,一般不推荐使用

3 注解的默认原则

先是默认类型注入, 后再根据属性名注入。先是默认类型注入, 比如声明一个接口类,刚好有一个实现类,以这个接口为 注入类型的则会注入这么个类, 如果是2个类的实现呢?那么如果被注入的属性名刚好是实现类的同一名字,则会注入匹配对 的实现类,如果不是,则会报错,SpringBoot会要求在众多的实现类中标记一个@Primary的注解要求,这哪个类为 默认注入。