首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring系列四:Spring Bean(深度讲解)

Spring系列四:Spring Bean(深度讲解)

原创
作者头像
叶秋学长
发布2022-07-25 11:05:53
3840
发布2022-07-25 11:05:53
举报
文章被收录于专栏:全栈学习专栏全栈学习专栏

上一期叶秋学长带领小伙伴们学习了spring bean生命周期 ,接下来学长带领小伙伴们深度了解spring bean。

目录

10.Bean定义和依赖定义有哪些方式?

11.有哪些依赖注入的方法?

12.Spring有哪些自动装配的方式?

13.Spring 中的 Bean 的作用域有哪些?

14.Spring 中的单例 Bean 会存在线程安全问题吗?

10.Bean定义和依赖定义有哪些方式?

有三种方式:直接编码方式配置文件方式注解方式

编辑

Bean依赖配置方式

  • 直接编码方式:我们一般接触不到直接编码的方式,但其实其它的方式最终都要通过直接编码来实现。
  • 配置文件方式:通过xml、propreties类型的配置文件,配置相应的依赖关系,Spring读取配置文件,完成依赖关系的注入。
  • 注解方式:注解方式应该是我们用的最多的一种方式了,在相应的地方使用注解修饰,Spring会扫描注解,完成依赖关系的注入。

11.有哪些依赖注入的方法?

Spring支持构造方法注入属性注入工厂方法注入,其中工厂方法注入,又可以分为静态工厂方法注入非静态工厂方法注入

编辑

Spring依赖注入方法

  • 构造方法注入 通过调用类的构造方法,将接口实现类通过构造方法变量传入 public CatDaoImpl(String message){ this. message = message; }

<bean id="CatDaoImpl" class="com.CatDaoImpl"> <constructor-arg value=" message "></constructor-arg> </bean>

  • 属性注入 通过Setter方法完成调用类所需依赖的注入 public class Id { private int id; public int getId() { return id; } public void setId(int id) { this.id = id; } }

<bean id="id" class="com.id "> <property name="id" value="123"></property> </bean>

  • 工厂方法注入
    • 静态工厂注入 静态工厂顾名思义,就是通过调用静态工厂的方法来获取自己需要的对象,为了让 Spring 管理所有对象,我们不能直接通过"工程类.静态方法()"来获取对象,而是依然通过 Spring 注入的形式获取: public class DaoFactory { //静态工厂 public static final FactoryDao getStaticFactoryDaoImpl(){ return new StaticFacotryDaoImpl(); } } public class SpringAction { //注入对象 private FactoryDao staticFactoryDao; //注入对象的 set 方法 public void setStaticFactoryDao(FactoryDao staticFactoryDao) { this.staticFactoryDao = staticFactoryDao; } }

    //factory-method="getStaticFactoryDaoImpl"指定调用哪个工厂方法 <bean name="springAction" class=" SpringAction" > <!--使用静态工厂的方法注入对象,对应下面的配置文件--> <property name="staticFactoryDao" ref="staticFactoryDao"></property> </bean> <!--此处获取对象的方式是从工厂类中获取静态方法--> <bean name="staticFactoryDao" class="DaoFactory" factory-method="getStaticFactoryDaoImpl"></bean>

    • 非静态工厂注入 非静态工厂,也叫实例工厂,意思是工厂方法不是静态的,所以我们需要首先 new 一个工厂实例,再调用普通的实例方法。 //非静态工厂 public class DaoFactory { public FactoryDao getFactoryDaoImpl(){ return new FactoryDaoImpl(); } } public class SpringAction { //注入对象 private FactoryDao factoryDao; public void setFactoryDao(FactoryDao factoryDao) { this.factoryDao = factoryDao; } }

    <bean name="springAction" class="SpringAction"> <!--使用非静态工厂的方法注入对象,对应下面的配置文件--> <property name="factoryDao" ref="factoryDao"></property> </bean> <!--此处获取对象的方式是从工厂类中获取实例方法--> <bean name="daoFactory" class="com.DaoFactory"></bean> <bean name="factoryDao" factory-bean="daoFactory" factory-method="getFactoryDaoImpl"></bean>

12.Spring有哪些自动装配的方式?

什么是自动装配?

Spring IOC容器知道所有Bean的配置信息,此外,通过Java反射机制还可以获知实现类的结构信息,如构造方法的结构、属性等信息。掌握所有Bean的这些信息后,Spring IOC容器就可以按照某种规则对容器中的Bean进行自动装配,而无须通过显式的方式进行依赖配置。

Spring提供的这种方式,可以按照某些规则进行Bean的自动装配,元素提供了一个指定自动装配类型的属性:autowire="<自动装配类型>"

Spring提供了哪几种自动装配类型?

Spring提供了4种自动装配类型:

编辑

Spring四种自动装配类型

  • byName:根据名称进行自动匹配,假设Boss又一个名为car的属性,如果容器中刚好有一个名为car的bean,Spring就会自动将其装配给Boss的car属性
  • byType:根据类型进行自动匹配,假设Boss有一个Car类型的属性,如果容器中刚好有一个Car类型的Bean,Spring就会自动将其装配给Boss这个属性
  • constructor:与 byType类似, 只不过它是针对构造函数注入而言的。如果Boss有一个构造函数,构造函数包含一个Car类型的入参,如果容器中有一个Car类型的Bean,则Spring将自动把这个Bean作为Boss构造函数的入参;如果容器中没有找到和构造函数入参匹配类型的Bean,则Spring将抛出异常。
  • autodetect:根据Bean的自省机制决定采用byType还是constructor进行自动装配,如果Bean提供了默认的构造函数,则采用byType,否则采用constructor。

13.Spring 中的 Bean 的作用域有哪些?

Spring的Bean主要支持五种作用域:

编辑

Spring Bean支持作用域

  • singleton : 在Spring容器仅存在一个Bean实例,Bean以单实例的方式存在,是Bean默认的作用域。
  • prototype : 每次从容器重调用Bean时,都会返回一个新的实例。

以下三个作用域于只在Web应用中适用:

  • request : 每一次HTTP请求都会产生一个新的Bean,该Bean仅在当前HTTP Request内有效。
  • session : 同一个HTTP Session共享一个Bean,不同的HTTP Session使用不同的Bean。
  • globalSession:同一个全局Session共享一个Bean,只用于基于Protlet的Web应用,Spring5中已经不存在了。

14.Spring 中的单例 Bean 会存在线程安全问题吗?

首先结论在这:Spring中的单例Bean不是线程安全的

因为单例Bean,是全局只有一个Bean,所有线程共享。如果说单例Bean,是一个无状态的,也就是线程中的操作不会对Bean中的成员变量执行查询以外的操作,那么这个单例Bean是线程安全的。比如Spring mvc 的 Controller、Service、Dao等,这些Bean大多是无状态的,只关注于方法本身。

假如这个Bean是有状态的,也就是会对Bean中的成员变量进行写操作,那么可能就存在线程安全的问题。

编辑

Spring单例Bean线程安全问题

单例Bean线程安全问题怎么解决呢?

常见的有这么些解决办法:

  1. 将Bean定义为多例 这样每一个线程请求过来都会创建一个新的Bean,但是这样容器就不好管理Bean,不能这么办。
  2. 在Bean对象中尽量避免定义可变的成员变量 削足适履了属于是,也不能这么干。
  3. 将Bean中的成员变量保存在ThreadLocal中⭐ 我们知道ThredLoca能保证多线程下变量的隔离,可以在类中定义一个ThreadLocal成员变量,将需要的可变成员变量保存在ThreadLocal里,这是推荐的一种方式。

​本期分享到此为止

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 10.Bean定义和依赖定义有哪些方式?
  • 11.有哪些依赖注入的方法?
  • 12.Spring有哪些自动装配的方式?
  • 13.Spring 中的 Bean 的作用域有哪些?
  • 14.Spring 中的单例 Bean 会存在线程安全问题吗?
    • ​本期分享到此为止
    相关产品与服务
    容器服务
    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档