【Spring】Spring生命周期,作用域

SpringBoot


Sprin技术一些常见知识的重新回顾----bg


软考的考试范围确实挺广泛的,把还没学的数据库、操作系统、软件工程、计算机网络…全部考了个遍,但是中级确实还是没啥难度,🔒机制、恢复技术都挺基础的【但是emmm…还是写了百页左右笔记】所以最近没发博,等笔记总结一下传到资源中,目前准备11月的架构师,到时候又要为写论文闭关了…

知识回顾碎碎念

宽泛的技术学着也容易忘记,SpringBoot应该算是java技术栈的基础必会技术了,对于这种技术当然不能像某些比如JSP之类,需要对其进行夯实,最近做项目的时候发现确实有些东西有所欠缺,故有感重造boot;

SpringBoot只是Spring生态中的一部分,Spirng核心容器Core Container时一个IOC容器【Tomcat其实也是】,具体的实现方式时DI,通过XML或者JavaConfig的方式将依赖关系告知容器。【SSM中主要是XML为主,SpringBoot中主要是Config为主】

Spring框架回顾

【second time】Spring框架是一款轻量级框架、EJB为重量级;提高开发人员的开发效率和系统的可维护性,Spring FrameWork是指的是spring生态,是很多模块的集合

请添加图片描述

简化一点,Spring生态包含的主要部分如上,可以看到最主要就是中间的SpringContainer【 beans、Core】,同时支持的数据访问和相关的WEB技术

Spring自带IOC和AOP【面向切面编程】,可以方便集成第三方的组件,支持RESTful java程序的开发

Spring相关重要的模块

从上面的架构图就可以大概列举几个

  • Spring Core : 核心模块,Spring的其他的功能基本都要依赖这个模块,主要就是实现的IOC
  • Spring Aspects : AOP做的好的外部框架是AspectJ,为了不重复造轮子,Spring集成了该组件,Aspects就是为集成提供支持
  • Spring AOP : spring提供的不完全的的AOP解决方案,只能管理spring容器范围内的东西bean,并且只能在运行时织入Weaving【性能和完备性都是弱于AspectJ的】
  • Spring Data Access/Integration 就是数据的访问模块,包括对数据库访问的抽象spring-jdbc,事务支持spring-tx,orm是对hiberna等支持,oxm提供对Castot等框架的支持,jms提供的消息服务 【 相关的配置之前在SSM的时候分析过】
  • spring web就是负责web的模块,包括webmvc提供了SpringMVC的实现,websocket提供了Websocket的实现,双向通信,还有webflux,对WebFlux提供支持 -----> 异步的响应式框架,不需要Servlet♎️
  • Spring Test 负责测试的模块,包括JUnit、TestNG、Mockito等框架提供支持,测试驱动开发TDD -----> 更好完成软件测试

Spring、SpringMVC、SpringBoot的关系

Spring包含很多的功能模块,大致的架构图在上,最重要的就是container的Core【IOC】部分,spring的其他的模块比如webmvc都是依赖这个模块的【比如@Controller也是DI】

SpringMVC是Spring中的一个很重要的模块,主要的思想就是快速实现MVC架构,【模型,视图,控制器,ModelAndView】,核心思想就是将业务逻辑,数据,显示分离组织代码【MVC架构】

使用Spring进行开发的各种配置过于麻烦,各种XML,SpringBoot的作用就是简化J2EE企业级应用开发,简化Spring开发,只是简化了配置,但是实际上实现MVC架构还是使用的Spring、SpringMVC,简化配置后做到开箱就用

Spring IOC

IOC就是控制反转, 和AOP一样是一种设计的思想【不是技术!】, 就是将原本在程序中手动创建对象的控制权交给spring框架管理 【 和aop一样不是spring独有,比如Tomcat容器】

控制: 对象创建【实例化,管理—dependency】的控制权

反转: 控制权移交给外部环境

将对象之间的依赖关系交给IOC容器管理,IOC容器完成DI,简化应用的开发,将应用从复杂的依赖关系中解脱,IOC就像一个复杂的工厂,we只需要给配置文件/注解就可以直接使用对象,不需要关心对象是如何被创建出来的,降低项目的维护难度和开发的难度,降低了代码之间的耦合【new对象的方式容易耦合,一旦改变就需要不断重新修改相关代码, 工厂模式 + 反射】

Spring时代使用的是XML文件来进行Bean配置,SpringBoot时代使用注解进行配置

Spring AOP

AOP aspect-oriented programming 面向切面编程,将与业务无关的,但是又被业务模块共同调用的逻辑给封装成一个切面,切入到合适的位置,可以减少系统的重复代码,降低模块间的耦合,有利于系统的扩展性

AOP是基于动态代理的,代理对象实现代理接口,Spring 会使用JDK proxy,创建代理对象,没有实现接口的,使用的cglib生成代理对象的子类来进行代理【详见动态代理blog】

AsprctJ是java生态中最完整的框架,spring也是通过spring-aspects提供该框架的支持【集成】

Spring AOP 和AspectJ AOP

spring AOP是运行时增强Weaving,而AspectJ是编译时Weaving,Spring AOP基于代理Proxying,而AspectJ是基于字节码操作,Spring AOP简单一点,但是作用范围受限,当切面较多时,使用AspecJ更好

Spring Bean

Spring Bean就是 IOC容器管理的对象, we需要告诉IOC容器帮助管理哪些对象,这个可以通过配置元数据来实现-----比如XML,注解、JavaConfig

<bean id= " " class = "  ">  <!-- 比如之前的BeanFactory -->
    <constructor-arg value = ""/>
</bean>

POJO 、 配置元素据 ----交给—> IOC容器Bean Factoty ------> 创建生成ready for use【上面的架构图中spring 容器中的beans 和factory中就时IOC实现的基础 ---- 工厂模式】

声明为Bean的注解

通用的注解的就是@Component: 可以标注任何的类为Spring组件,当不知道Bean属于那一层的时候,使用这个注解

@Controller: 对应控制层,接收用户请求,调用Service层返回数据给前端

@Service : 对应的服务层,设计复杂的业务逻辑,需要使用Dao

@Repository: 对应的持久层,也就是DAO层 【但是使用了Mybatis等持久层框架后,Mybatis也会使用动态代理创建Dao接口的代理对象,所以一般不使用这个注解】、

@Component和@Bean的区别

@Component注解作用与类【上面的几个都是】,通过类路径扫描来进行自动装配到Spring容器【Spring时代可以使用component-scan注解指定扫描位置,SpringBoot时代的SpringBootApplication复合注解包括了@Component注解,会自动装配】

@Bean作用于方法,该注解可以将方法返回的类自动放入到Spring容器【之前boot的JavaConfig部分分享过】,比@Component的自定义性更强,因为其只能放在自定义的类上面产生对象,而当引入第三方库的时候,没有类,只能使用@Bean将new的对象放入到容器中

@Configuration
public class AppConfig {
	@Bean
    public TransferService transferService() {
        return new TransferService();
    }
}

这里就会将这个对象给放入到容器中,这个等同于Spring配置中的

<beans>
	<bean id = "myTransferServie" class = "com.XXX.TransferService"/>
</beans>

所以两个注解的首要区别就是注解的位置不一样,在JavaConfig中常用@bean实现将第三方类的对象放入容器中【不可直接获得源码】

注入Bean的注解

@Autowired org.springframwork.bean.facactory

@Resource javax.annotation

@Inject 【 使用较少】 javax.Inject 也是JDK提供的

@Resource和@Autowired

@inject使用少就不用给与较大关注

Autowired属于Spring内置的注解,默认的注入方式为byType; 出现的问题就是当有多个同一类型的对象,就会DI失败;[实现同一个接口],不知道选择谁; 加上一个@Qualifier(name = “”)就会默认ByName注入;显示指定名称,不然默认名称会不好控制

Resouce为JDK提供的注解,默认的方式为ByName,失败再ByType,name属性可以指定名称,type可以指定类型…

Bean的作用域【类型】

<bean id = "" class = "" scope = "singleton" >
	.......
</bean>

<!-- Bean的作用域就是指IOC容器管理Bean对象的行为,默认时singleton【我以前居然认为只能是单例的-->

作用域一共有5种,singleton、prototype,request、session、global-session,最常用的是singleton和prototype

  • singleton : 单例bean,Spring中默认bean都是单例的,单例模式【工厂】
  • prototype: 每次请求都会创建一个全新的bean对象,即每次getBean,都会调用new XXX

【其实下面三个类似之前的Servlet的作用域对象,全局,会话,请求 ----- 监听器】

  • request: 每一次HTTP请求都会返回一个新的Bean实例,也是仅仅适用于WebAapplicationContext环境
  • session :同一个Http Session共享一个Bean,不同的Session使用不同的Bean,也是只是适用于WebApplicationContext
  • global-session : 一般用于Portlet应用环境,仅使用于WebApplication 【Spring5 无了】

springBoot时代配置类的方式使用注解@Scope

@Bean
@Scope(value = configurableBeanFactory.COOPE_PROTOTYPE)
public class XXX XXX() {
    return new XXX();
}

这里就使用的prototype作用域,每次请求都会重新创建一个对象【默认的singleton是访问的统一个对象,可能被污染】

单例Bean线程安全

单例bean存在线程安全问题,【OS中资源竞争】,当多个对象操作统一对象的时候存在资源竞争问题 ----- 原型bean(不存在资源共享),不存在安全问题

(按照数据库中并发来理解,当有set操作改变有状态量那么就是不安全的,因为可以看作同时读取的情况) 所以单例bean是否安全取决与bean有无状态,有状态就是有状态存储功能,比如可修改的成员变量User存储用户信息 ---- 不安全

所以再Spring单例bean不应该再全局层面定义有数据存储功能的对象; 当必须这样做

  • 在类中定义一个ThreadLocal成员变量,将可变的成员变量保存在ThreadLocal中 【 之前分享过ThreadLocal,多线程条件下的数据共享方案,ThreadLocal中有map,手动删除,避免泄露】
  • 可以修改作用域为prototype,这样就不存在资源共、竞争,不存在安全问题

【实际上大部分的Bean都是无状态的,比如Service,注解DI的对象,没有定义的成员变量】

Bean的生命周期

查看源图像

整个过程其实来说就是资源定位,bean定义,发布bean定义,实例化,依赖注入DI,初始化,生存使用,销毁

img

详细一点

img

【这张图放这儿:happy:】

通俗理解:Bean生命周期 ----> 从最开始写的配置到最后bean嗝屁整个阶段嘛【解析,实例化,属性注入,*Aware如果实现了【Name,ClassLoader,BeanFactory】,就调用相关的set XX 方法传入给bean对象; 之后进入初始化阶段,包括Beanpostprocessor前置阶段,调用自定义initialize方法,进入Beanpostprocessor后置阶段,之后注册回调接口【方便回调使用】,之后使用,使用之后,如果实现了disposableBean接口,【说明可以放弃】,那么就会调用destroy方法销毁

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值