Spring原理

这次我们来研究Bean的相关知识和spring boot自动配置的相关流程

        1.Bean的作用域

              1概念

                在SpringIoC&DI阶段,我们学习了Spring是如何帮助我们管理对象的.

                1. 通过 @Controller ,@Service , @Repository , @Component , @Configuration                              , @Bean 来声明Bean对象.

                2. 通过ApplicationContext 或者BeanFactory 来获取对象

                3. 通过 @Autowired , Setter ⽅法或者构造⽅法等来为应⽤程序注⼊所依赖的Bean对象

                我们编写代码,从spring容器中获取bean

                        

package com.example.springconfig;

import com.example.springconfig.demos.model.User;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;

@SpringBootApplication
public class SpringConfigApplication {

    public static void main(String[] args) {

         ApplicationContext context=SpringApplication.run(SpringConfigApplication.class, args);
        User user1 = context.getBean(User.class);
        user1.setName("lisi");
        System.out.println( "当前对象地址:"+System.identityHashCode(user1));


        User user2 = context.getBean(User.class);
        System.out.println( "当前对象地址:"+System.identityHashCode(user2));
    }

}







package com.example.springconfig.demos.config;

import com.example.springconfig.demos.model.User;
import org.omg.CORBA.PUBLIC_MEMBER;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class BeanConfig {
    @Bean
    public User user1(){
        return  new User(1,"zhangsan");
    }
}




package com.example.springconfig.demos.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {
    private Integer id;
    private  String name;

}

   

运行出结果 

发现输出对象地址的值是一样的,说明从spring容器中取出的对象都是同一个

这也是"单例模式"    单例模式:确保⼀个类只有⼀个实例,多次创建也不会创建出多个实例

默认情况下,Spring容器中的bean都是单例的,这种⾏为模式,我们就称之为Bean的作⽤域.

      Bean的作⽤域是指Bean在Spring框架中的某种⾏为模式.

⽐如单例作⽤域:表⽰Bean在整个Spring中只有⼀份,它是全局共享的.那么当其他⼈修改了这个值之后,那么另⼀个⼈读取到的就是被修改的值、

   2.Bean的作用域

在Spring中⽀持6种作⽤域,后4种在SpringMVC环境才⽣效

1. singleton:单例作⽤域

2. prototype:原型作⽤域(多例作⽤域)

3. request:请求作⽤域

4. session:会话作⽤域

5. Application:全局作⽤域

6. websocket:HTTPWebSocket作⽤域

接下来 我们来看看这几个bean的作用域

在这之前我们先来看一下一些注解的详细

堆和栈之间的关系

各个bean作用域中的代码

package com.example.springconfig.demos.controller;

import com.example.springconfig.demos.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.jws.soap.SOAPBinding;

@RequestMapping("/scope")
@RestController
public class BeanScopeController {

    @Autowired
      private ApplicationContext context;
    @Resource(name = "singletonUser")
    private  User singletonUser;

    @Resource(name = "prototypeUser")
    private  User prototypeUser;
    @Resource(name = "requestUser")
    private  User requestUser;
    @Resource(name = "sessionUser")
    private  User sessionUser;
    @Resource(name = "applicationUser")
    private  User applicationUser;
    @RequestMapping("/single")
    public  String  single() {
        /**
         *1.从context中获取对象
         * 2.属性注入获取对象
         */
        User user = (User) context.getBean("singletonUser");
        return "context中获取的对象是:" + user + ",属性注入获取的对象:" + System.identityHashCode(singletonUser);
    }
    @RequestMapping("/prototype")
    public  String  prototype(){
        /**
         *1.从context中获取对象
         * 2.属性注入获取对象
         */
        User user= (User) context.getBean("prototypeUser");
        return "context中获取的对象是:"+user+",属性注入获取的对象:"+System.identityHashCode(prototypeUser);
    }
    @RequestMapping("/request")
    public  String  request(){
        /**
         *1.从context中获取对象
         * 2.属性注入获取对象
         */
        User user= (User) context.getBean("requestUser");
        return "context中获取的对象是:"+user+",属性注入获取的对象:"+System.identityHashCode(requestUser);
    }

    @RequestMapping("/session")
    public  String  session(){
        /**
         *1.从context中获取对象
         * 2.属性注入获取对象
         */
        User user= (User) context.getBean("sessionUser");
        return "context中获取的对象是:"+user+",属性注入获取的对象:"+System.identityHashCode(sessionUser);
    }
    @RequestMapping("/application")
    public  String  application(){
        /**
         *1.从context中获取对象
         * 2.属性注入获取对象
         */
        User user= (User) context.getBean("applicationUser");
        return "context中获取的对象是:"+user+",属性注入获取的对象:"+System.identityHashCode(applicationUser);
    }





}




package com.example.springconfig.demos.config;

import com.example.springconfig.demos.model.User;
import org.omg.CORBA.PUBLIC_MEMBER;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.annotation.ApplicationScope;
import org.springframework.web.context.annotation.RequestScope;
import org.springframework.web.context.annotation.SessionScope;
import org.springframework.web.servlet.handler.UserRoleAuthorizationInterceptor;

@Configuration
public class BeanConfig {
    @Bean
    public User user1(){
        return  new User(1,"zhangsan");
    }
    @Bean
  @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)
//    @Scope("singleton")
    public  User singletonUser(){
        return  new User();
    }
    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public  User prototypeUser(){
        return new User();
    }

    @Bean
    @Scope(value = WebApplicationContext.SCOPE_REQUEST,proxyMode = ScopedProxyMode.TARGET_CLASS)
    public  User requestUser(){
        return  new User();
    }
    @Bean
    @SessionScope
    public User sessionUser(){
    return  new User();
    }

    @Bean
    @ApplicationScope
    public  User applicationUser(){
        return  new User();
    }

}

  1.singleton

 每次获取的都是同一个对象

   2.prototype

     每次获取的对象是不同的

3.request

请求每次获取的对象都不一样

4.session

在⼀个session中,多次请求,获取到的对象都是同⼀个.

 5.application

在⼀个应⽤中,多次访问都是同⼀个对象
Applicationscope就是对于整个web容器来说,bean的作⽤域是ServletContext级别的.这个和singleton有点类似区别在于:Applicationscope是ServletContext的单例,singleton是⼀个ApplicationContext的单例.在⼀个web容器中ApplicationContext可以有多个.(了解即可)

3.Bean的生命周期        

             ⽣命周期指的是⼀个对象从诞⽣到销毁的整个⽣命过程,我们把这个过程就叫做⼀个对象的⽣命周期.Bean的⽣命周期分为以下5个部分:

 1. 实例化(为Bean分配内存空间)

2. 属性赋值(Bean注⼊和装配,⽐如 @AutoWired )

3. 初始化

                a. 执⾏各种通知,如 BeanNameAware ,BeanFactoryAware ,ApplicationContextAware                      的接⼝⽅法.

                b. 执⾏初始化⽅法

                  ▪ xml定义 init-method

                  ▪ 使⽤注解的⽅式 @PostConstruct

                ▪ 执⾏初始化后置⽅法( BeanPostProcessor )

   4. 使⽤Bean

  5. 销毁Bean

a. 销毁容器的各种⽅法,如 @PreDestroy ,DisposableBean 接⼝⽅法, destroymethod.

演示代码代码如下

package com.example.springconfig.demos.component;

import com.example.springconfig.demos.model.User;
import org.apache.ibatis.annotations.Update;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

@Component
public class BeanLifeComponent {
    private User user;

    public BeanLifeComponent() {
        System.out.println("执行构造方法");
    }


    @Autowired
    @Qualifier("user1")
    public void setUser1(User user1) {
        this.user = user;
        System.out.println("属性注入");
    }
    @PostConstruct
    public  void  init(){
        System.out.println("执行初始化");
    }
    public  void use(){
        System.out.println("执行use");
    }
    @PreDestroy
    public void destroy(){
        System.out.println("执行destroy方法");
    }
}

4.关于Bean相关的源码

        我们举个例子来说一下,我们获取bean对象,并通过不同的方式拿取相关的值,

我们通过结果看到,源码里有类似代理类和目标类的东西,我们通过toString方法拿到的其实是spring代理的时候进行了重写,重写的逻辑是执行目标toString

代理类包含目标类 

返回的user其实就是代理类 我们在执行程序的时候,代理类没有发生变化,目标类在发生变化

        

                1.AbstractAutowireCapableBeanFactory

        我们翻看AbstractAutowireCapableBeanFactory这个源码,在里面看到了

里面有实例化bean的源码

我们根据bean的周期来看

接下来就看属性注入

在属性注入里面有bean的初始化initializeBean 里面有bean初识化的各种代码

我们可以看到spring的源码是非常复杂的,我们现在也只是浅浅读了一下

5.spring自动配置

                SpringBoot的⾃动配置就是当Spring容器启动后,⼀些配置类,bean对象等就⾃动存                    ⼊到了IoC容器中,不需要我们⼿动去声明,从⽽简化了开发,省去了繁琐的配置操                     作.

             SpringBoot⾃动配置,就是指SpringBoot是如何将依赖jar包中的配置类以及Bean加载到SpringIoC容器中的

            我们学习主要分以下两个⽅⾯:

           1. Spring是如何把对象加载到SpringIoC容器中的

           2. SpringBoot是如何实现的

  我们先看看@SpringBootApplication这个注解 点进去

2.@SpringBootConfiguration

                

 

3.@EnableAutoConfiguration

这里面的注解是实现自动配置的核心 

我们再点击进入import中的AutoConfigurationImportSelector.class

这里面的这个方法是主要的方法,我们在点进getAutoConfigurationEntry 

标注的这一行是拿到配置信息,我们继续点击查看怎样拿到配置信息

         

我们搜索这个路径

文件里面就是配置的文件

4.@AutoConfigurationPackage

我们接下来看这个注解

点进进入

我们点进Registrar

里面就是获取包的名字之类的

总结

 

 
 
 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/500191.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android R 广播注册与发送流程分析

静态广播注册时序图 动态广播注册时序图 发送广播时序图 前言 广播接收器可以分为动态和静态,静态广播接收器就是在 AndroidManifest.xml 中注册的,而动态的广播接收器是在代码中通过 Context#registerReceiver() 注册的。 这里先从静态广播的流程开始…

Pygame基础6-旋转

6-旋转 当我们想要旋转一个图片的时候, 我们可以使用pygame.transform.rotozoom获得旋转后的图片: kitten pygame.transform.rotozoom(kitten, angle, 1)问题是,每次旋转都会降低图片的质量。如果旋转很多次后,图片的质量会变得…

农村集中式生活污水分质处理及循环利用技术指南

立项单位:生态环境部土壤与农业农村生态环境监管技术中心、山东文远环保科技股份有限公司、北京易境创联环保有限公司、中国环境科学研究院、广东省环境科学研究院、中铁第五勘察设计院集团有限公司、中华环保联合会水环境治理专业委员会 本文件规定了集中式村镇生活…

【动手学深度学习-pytorch】9.2长短期记忆网络(LSTM)

长期以来,隐变量模型存在着长期信息保存和短期输入缺失的问题。 解决这一问题的最早方法之一是长短期存储器(long short-term memory,LSTM) (Hochreiter and Schmidhuber, 1997)。 它有许多与门控循环单元( 9.1节&…

婚恋交友APP小程序H5源码交付-支持二开!实名制交友,可服务器审核,亦可后台自己审核!同城交友,多人语音!

一、需求分析 在征婚交友网站开发初期,需求分析是至关重要的环节。这需要深入了解目标用户的需求和期望,包括他们的年龄、职业、兴趣爱好、交友条件等方面。通过收集和分析这些信息,开发团队可以明确网站的目标用户,并为他们提供…

东特科技现已加入2024第13届国际生物发酵产品与技术装备展

参展企业介绍 温州东特科技有限公司是一家集设计、生产、销售及服务为一体的卫生级流体设备企业。专业从事各种乳食品、制药、化工、啤酒设备、不锈钢卫生级阀门,管件,视镜,及非标配件定制等产品的销售与服务。先进的设计理念专业的技术优势一…

深度思考:雪花算法snowflake分布式id生成原理详解

雪花算法snowflake是一种优秀的分布式ID生成方案,其优点突出:它能生成全局唯一且递增的ID,确保了数据的一致性和准确性;同时,该算法灵活性强,可自定义各部分bit位,满足不同业务场景的需求&#…

使用html实现图片相册展示设计

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>图片&#xff08;相册&#xff09;展示设计</title><link rel"stylesheet" href"./style.css"> </head> <b…

SQL--报错注入(join无列名注入)

SQL报错注入 平时在做SQL题时&#xff0c;如果发生语法的错误时&#xff0c;就会产生报错&#xff0c;报错的信息就会显示在前端 报错注入大多是利用函数会报错的特性&#xff0c;将需要的信息通过报错信息回显出来 报错注入函数&#xff08;后面主要的还有一个floor函数暂时…

虚拟机 centos 安装后与主机 ip保持一致

1、安装时 网络模式 悬着自动检测 &#xff08;桥接&#xff09; 2、打开网络 这里如果没有打开 就去 编辑 该文件。把ONBOOTno 改为yes 后 vim /etc/sysconfig/network-scripts/ifcfg-ens160 刷新配置 systemctl restart network 再查看addr 与本机 192.168.31.xx 在同…

Python Flask Web框架初步入门

前言 flask基础 搭建flask服务器 定义html 使用templates模板定义页面的html html页面编写 render_template传参变量 定义图片 创建static目录&#xff0c;存入图片 html编写 flask入门 网站多域名 网站之间超链接跳转 入门案例 将centos的rpm包下载链接集成到自…

13-API风格(下):RPCAPI介绍

RPC在Go项目开发中用得也非常多&#xff0c;需要我们认真掌握。 RPC介绍 根据维基百科的定义&#xff0c;RPC&#xff08;Remote Procedure Call&#xff09;&#xff0c;即远程过程调用&#xff0c;是一个计算机通信协议。该协议允许运行于一台计算机的程序调用另一台计算机…

发光二极管限流电阻对电路性能有哪些影响?

目录 1.控制电流 2.稳定电压&#xff08;亮度控制&#xff09; 3.功耗控制&#xff08;保护元件&#xff09; 4.节能控制 发光二极管&#xff08;LED&#xff09;限流电阻在电路中对电路性能主要有以下几个影响&#xff1a; 1.控制电流 限流电阻通过限制电流&#xff0c;使LED工…

WebGIS开发

1.准备工作 高德开发API注册账号&#xff0c;创建项目拿到key和密钥 高德key 2.通过JS API引入高德API <html><head><meta charset"utf-8" /><meta http-equiv"X-UA-Compatible" content"IEedge" /><metaname&quo…

pdf在浏览器上无法正常加载的问题

一、背景 觉得很有意思给大家分享一下。事情是这样的&#xff0c;开发给我反馈说&#xff0c;线上环境接口请求展示pdf异常&#xff0c;此时碰巧我前不久正好在ingress前加了一层nginx&#xff0c;恰逢此时内心五谷杂陈&#xff0c;思路第一时间便放在了改动项。捣鼓了好久无果…

上位机图像处理和嵌入式模块部署(qmacvisual非opencv算法编写)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 我们都知道&#xff0c;qmacvisual本身依赖于qtopencv的实现。大部分的界面都是依赖于qt的实现。图像算法部分&#xff0c;也是大部分都依赖于open…

【最新版RabbitMQ3.13】Linux安装基于源码构建的RabbitMQ教程

前言 linux环境 安装方式有三种&#xff0c;我们这里使用源码安装 Linux下rpm、yum和源码三种安装方式简介 个人语雀首发教程&#xff1a;https://www.yuque.com/wzzz/java/kl2zn22b42svsc6b csdn地址: https://blog.csdn.net/u013625306/article/details/137151862 安装版本…

机器学习模型之逻辑回归

逻辑回归是一种常用的分类算法&#xff0c;尤其适用于二分类问题。逻辑回归的核心思想是通过对数几率函数&#xff08;logistic function&#xff09;将线性回归的输出映射到概率空间&#xff0c;从而实现分类。 逻辑回归的原理&#xff1a; 逻辑回归模型使用对数几率函数&am…

wireshark创建显示过滤器实验简述

伯克利包过滤是一种在计算机网络中进行数据包过滤的技术&#xff0c;通过在内核中插入过滤器程序来实现对网络流量的控制和分析。 在数据包细节面板中创建显示过滤器&#xff0c;显示过滤器可以在wireshark捕获数据之后使用。 实验拓扑图&#xff1a; 实验基础配置&#xff1…

Unity-通过AB包使用SpriteAtlas图集(基于unity2018)

项目遇到了一个性能问题&#xff0c;需要优化UI。其中就涉及UI的合批问题&#xff0c;其中自然而然就会关联到图集的概念。旧版图集&#xff0c;Legacy Atlas&#xff0c;还没有太研究。今天主要看一下SpriteAtlas怎么使用的。 因为我们项目资源工程和Runtime是分离的&#xf…