springboot原理

目录

配置优先级

Bean管理

bean的基本介绍

获取Bean

 Bean作用域


今天我们来讲讲springboot的原理

配置优先级

首先我们先来想想看,我们知道springboot支持的三类配置文件分别是

  • application.properties

  • application.yml

  • application.yaml

但是假设在我们的SpringBoot项目当中,我们要想配置一个属性,可以通过这三种方式当中的任意一种来配置都可以,那么如果一个项目中同时存在这三种配置文件,且都配置了同一个属性,如:Tomcat端口号,到底是那一份配置文件会生效呢?

比如以下的这种形式

  • application.properties

  • server.port=8081
  • application.yml

server:
   port: 8083
  • application.yaml

server:
   port: 8082

可以看到在上面的三分配置文件中,分别为Tomcat配置了不同的端口,那么在项目运行的时候,我们只需要看。tomcat的端口是多少就可以清楚的知道,如果三份配置文件同时存在,那么那一份配置文件的优先级最高

那么运行结果的是8081端口也就是说properties、yaml、yml三种配置文件,优先级最高的是properties

那么如果是yaml、yml两种配置文件同时存在我们得到的结果是8083,那么也就是说明yml配置文件生效

那么我们就可以得到一个结果

配置文件优先级排名(从高到低):

  1. properties配置文件

  2. yml配置文件

  3. yaml配置文件

注意事项:虽然springboot支持多种格式配置文件,但是我们在项目开发时,推荐统一使用一种格式的配置。(yml是主流)

那么在SpringBoot项目当中除了以上3种配置文件外,SpringBoot为了增强程序的扩展性,除了支持配置文件的配置方式以外,还支持另外两种常见的配置方式:

  1. Java系统属性配置 (格式: -Dkey=value)

-Dserver.port=9000
  1. 命令行参数 (格式:--key=value)

--server.port=10010

此时我们已经同时配置了五个端口,分别使用的是properties配置文件yml配置文件ymal配置文件,花园Java习题属性配置,和命令行参数,着五种

现在重启服务,同时配置Tomcat端口(三种配置文件、系统属性、命令行参数),测试哪个Tomcat端口号生效:

得到的结果是10010也就是说明命令行参数生效,当我们把命令行参数,删除之后,端口号就是9000了,现在我们就可以得出一个结论

在SpringBoot项目当中,常见的属性配置方式有5种, 3种配置文件,加上2种外部属性的配置(Java系统属性、命令行参数)。通过以上的测试,我们也得出了优先级(从低到高):

  • application.yaml(忽略)

  • application.yml

  • application.properties

  • java系统属性(-Dxxx=xxx)

  • 命令行参数(--xxx=xxx)

Bean管理

bean的基本介绍

Spring中的Bean对象管理指的是Spring容器对Bean对象的创建、依赖注入、生命周期管理等操作。Spring容器通过IOC(Inversion of Control)实现Bean对象的管理。

Spring容器通过扫描指定的包或配置文件,将标注了特定注解(如@Component、@Service、@Repository等)的类实例化为Bean对象,并将其放入容器中统一管理。容器会自动处理Bean对象之间的依赖关系,并在需要时进行依赖注入。

我们主要来学习以下的几方面

  1. 如何从IOC容器中手动的获取到bean对象

  2. bean的作用域配置

  3. 管理第三方的bean对象

获取Bean

默认情况下,SpringBoot项目在启动的时候会自动的创建IOC容器(也称为Spring容器),并且在启动的过程当中会自动的将bean对象都创建好,存放在IOC容器当中。应用程序在运行时需要依赖什么bean对象,就直接进行依赖注入就可以了。

而在Spring容器中提供了一些方法,可以主动从IOC容器中获取到bean对象,下面介绍3种常用方式:

  1. 根据name获取bean

    Object getBean(String name)
  2. 根据类型获取bean

    <T> T getBean(Class<T> requiredType)
  3. 根据name获取bean(带类型转换)

    <T> T getBean(String name, Class<T> requiredType)

控制器:DeptController

@RestController
@RequestMapping("/depts")
public class DeptController {

    @Autowired
    private DeptService deptService;

    public DeptController(){
        System.out.println("DeptController constructor ....");
    }

    @GetMapping
    public Result list(){
        List<Dept> deptList = deptService.list();
        return Result.success(deptList);
    }

    @DeleteMapping("/{id}")
    public Result delete(@PathVariable Integer id)  {
        deptService.delete(id);
        return Result.success();
    }

    @PostMapping
    public Result save(@RequestBody Dept dept){
        deptService.save(dept);
        return Result.success();
    }
}

业务实现类:DeptServiceImpl

@Slf4j
@Service
public class DeptServiceImpl implements DeptService {
    @Autowired
    private DeptMapper deptMapper;

    @Override
    public List<Dept> list() {
        List<Dept> deptList = deptMapper.list();
        return deptList;
    }

    @Override
    public void delete(Integer id) {
        deptMapper.delete(id);
    }

    @Override
    public void save(Dept dept) {
        dept.setCreateTime(LocalDateTime.now());
        dept.setUpdateTime(LocalDateTime.now());
        deptMapper.save(dept);
    }
}

Mapper接口:

@Mapper
public interface DeptMapper {
    //查询全部部门数据
    @Select("select * from dept")
    List<Dept> list();

    //删除部门
    @Delete("delete from dept where id = #{id}")
    void delete(Integer id);

    //新增部门
    @Insert("insert into dept(name, create_time, update_time) values (#{name},#{createTime},#{updateTime})")
    void save(Dept dept);
}

测试类:

@SpringBootTest
class SpringbootWebConfig2ApplicationTests {

    @Autowired
    private ApplicationContext applicationContext; //IOC容器对象

    //获取bean对象
    @Test
    public void testGetBean(){
        //根据bean的名称获取
        DeptController bean1 = (DeptController) applicationContext.getBean("deptController");
        System.out.println(bean1);

        //根据bean的类型获取
        DeptController bean2 = applicationContext.getBean(DeptController.class);
        System.out.println(bean2);

        //根据bean的名称 及 类型获取
        DeptController bean3 = applicationContext.getBean("deptController", DeptController.class);
        System.out.println(bean3);
    }
}

在控制太中输出的结果,三个对象的地址都是同一的,说明在IOC容器中默认对象是只有一个的,是单例的

 Bean作用域

在前面我们提到的IOC容器当中,默认bean对象是单例模式(只有一个实例对象)。那么如何设置bean对象为非单例呢?需要设置bean的作用域。

在Spring中支持五种作用域,后三种在web环境才生效:

作用域说明
singleton容器内同名称的bean只有一个实例(单例)(默认)
prototype每次使用该bean时会创建新的实例(非单例)
request每个请求范围内会创建新的实例(web环境中,了解)
session每个会话范围内会创建新的实例(web环境中,了解)
application每个应用范围内会创建新的实例(web环境中,了解)

代码演示:

@Lazy  //该注解表示延迟初始化,一但加上了这个注解,就会延迟到第一次使用的时候,才初始化

控制器:DeptController

//默认bean的作用域为:singleton (单例)
@Lazy //延迟加载(第一次使用bean对象时,才会创建bean对象并交给ioc容器管理)
@RestController
@RequestMapping("/depts")
public class DeptController {

    @Autowired
    private DeptService deptService;

    public DeptController(){
        System.out.println("DeptController constructor ....");
    }

    //省略其他代码...
}

测试类

@SpringBootTest
class SpringbootWebConfig2ApplicationTests {

    @Autowired
    private ApplicationContext applicationContext; //IOC容器对象

    //bean的作用域
    @Test
    public void testScope(){
        for (int i = 0; i < 10; i++) {
            DeptController deptController = applicationContext.getBean(DeptController.class);
            System.out.println(deptController);
        }
    }
}

运行这个测试类,注意使用Debug运行,打上断点,然后我们就会发现,对象并不会直接创建,而是在,我们使用到这个方法后,然后才会去创建对象,注意在第一次创建对象后,该对象就会在IOC容器中,后续的获取的都是同一个对象。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值