实力总结四类 Bean 注入 Spring 的方式

643f328a3fb56c4bb6a7dad64f2e1955.gif

作者 | 阿Q

来源 | 阿Q说代码

一提到Spring,大家最先想到的是啥?是AOPIOC的两大特性?是SpringBean的初始化流程?还是基于SpringSpring Cloud全家桶呢?

今天我们就从SpringIOC特性入手,聊一聊Spring中把Bean注入Spring容器的几种方式。

我们先来简单了解下IOC的概念:IOC即控制反转,也称为依赖注入,是指将对象的创建或者依赖关系的引用从具体的对象控制转为框架或者IOC容器来完成,也就是依赖对象的获得被反转了。

“可以简单理解为原来由我们来创建对象,现在由Spring来创建并控制对象。”

xml 方式

依稀记得最早接触Spring的时候,用的还是SSH框架,不知道大家对这个还有印象吗?所有的bean的注入得依靠xml文件来完成。

它的注入方式分为:set方法注入、构造方法注入、字段注入,而注入类型分为值类型注入(8种基本数据类型)和引用类型注入(将依赖对象注入)。

以下是set方法注入的简单样例

<bean name="teacher" class="org.springframework.demo.model.Teacher"><property name="name" value="阿Q"></property>
</bean>

对应的实体类代码

public class Teacher {private String name;public void setName(String name) {this.name = name;}
}

xml方式存在的缺点如下:

  1. xml文件配置起来比较麻烦,既要维护代码又要维护配置文件,开发效率低;

  2. 项目中配置文件过多,维护起来比较困难;

  3. 程序编译期间无法对配置项的正确性进行验证,只能在运行期发现并且出错之后不易排查;

  4. 解析xml时,无论是将xml一次性装进内存,还是一行一行解析,都会占用内存资源,影响性能。

注解方式

随着Spring的发展,Spring 2.5开始出现了一系列注解,除了我们经常使用的@Controller、@Service、@Repository、@Component 之外,还有一些比较常用的方式,接下来我们简单了解下。

@Configuration + @Bean

当我们需要引入第三方的jar包时,可以用@Bean注解来标注,同时需要搭配@Configuration来使用。

  • @Configuration用来声明一个配置类,可以理解为xml<beans>标签

  • @Bean 用来声明一个bean,将其加入到Spring容器中,可以理解为xml<bean>标签

简单样例:将 RedisTemplate 注入 Spring

@Configuration
public class RedisConfig {@Beanpublic RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory redisConnectionFactory) {RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();......return redisTemplate;}
}

@Import

我们在翻看Spring源码的过程中,经常会看到@Import注解,它也可以用来将第三方jar包注入Spring,但是它只可以作用在类上。

例如在注解EnableSpringConfigured上就包含了@Import注解,用于将SpringConfiguredConfiguration配置文件加载进Spring容器。

@Import(SpringConfiguredConfiguration.class)
public @interface EnableSpringConfigured {}

@Importvalue值是一个数组,一个一个注入比较繁琐,因此我们可以搭配ImportSelector接口来使用,用法如下:

@Configuration
@Import(MyImportSelector.class)
public class MyConfig {}public class MyImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata annotationMetadata) {return new String[]{"org.springframework.demo.model.Teacher","org.springframework.demo.model.Student"};}
}

其中selectImports方法返回的数组就会通过@Import注解注入到Spring容器中。

无独有偶,ImportBeanDefinitionRegistrar接口也为我们提供了注入bean的方法。

@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {......
}

我们点击AspectJAutoProxyRegistrar类,发现它实现了ImportBeanDefinitionRegistrar接口,它的registerBeanDefinitions方法便是注入bean的过程,可以参考下。

如果觉得源代码比较难懂,可以看一下我们自定义的类

@Configuration
@Import(value = {MyImportBeanDefinitionRegistrar.class})
public class MyConfig {}public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,BeanDefinitionRegistry registry) {RootBeanDefinition tDefinition = new RootBeanDefinition(Teacher.class);// 注册 Bean,并指定bean的名称和类型registry.registerBeanDefinition("teacher", tDefinition);}}
}

这样我们就把Teacher类注入到Spring容器中了。

FactoryBean

提到FactoryBean,就不得不与BeanFactory比较一番。

  • BeanFactory : 是 FactoryIOC容器或者对象工厂,所有的Bean都由它进行管理

  • FactoryBean : 是Bean ,是一个能产生或者修饰对象生成的工厂 Bean,实现与工厂模式和修饰器模式类似

那么FactoryBean是如何实现bean注入的呢?

先定义实现了FactoryBean接口的类

public class TeacherFactoryBean implements FactoryBean<Teacher> {/*** 返回此工厂管理的对象实例**/@Overridepublic Teacher getObject() throws Exception {return new Teacher();}/*** 返回此 FactoryBean 创建的对象的类型**/@Overridepublic Class<?> getObjectType() {return Teacher.class;}}

然后通过 @Configuration + @Bean的方式将TeacherFactoryBean加入到容器中

@Configuration
public class MyConfig {@Beanpublic TeacherFactoryBean teacherFactoryBean(){return new TeacherFactoryBean();}
}

注意:我们没有向容器中注入Teacher, 而是直接注入的TeacherFactoryBean,然后从容器中拿Teacher这个类型的bean,成功运行。

BDRegistryPostProcessor

看到这个接口,不知道对于翻看过Spring源码的你来说熟不熟悉。如果不熟悉的话请往下看,要是熟悉的话就再看一遍吧😃。

源码

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {// 注册bean到spring容器中void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}@FunctionalInterface
public interface BeanFactoryPostProcessor {void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

BeanFactoryPostProcessor接口是BeanFactory的后置处理器,方法postProcessBeanFactorybean的定义进行控制。今天我们重点来看看postProcessBeanDefinitionRegistry方法:它的参数是BeanDefinitionRegistry,顾名思义就是与BeanDefinition注册相关的。

c7013d8f191f1f0037dc333cf40e0df1.png

通过观察该类,我们发现它里边包含了registerBeanDefinition方法,这个不就是我们想要的吗?为了能更好的使用该接口来达到注入bean的目的,我们先来看看Spring是如何操作此接口的。

6c6703b34d0956fe13d8271877234d49.png

看下invokeBeanFactoryPostProcessors方法,会发现没有实现PriorityOrderedOrderedbean(这种跟我们自定义的实现类有关)会执行以下代码。

while (reiterate) {......invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);......
}

进入该方法

private static void invokeBeanDefinitionRegistryPostProcessors(Collection<? extends BeanDefinitionRegistryPostProcessor> postProcessors, BeanDefinitionRegistry registry) {for (BeanDefinitionRegistryPostProcessor postProcessor : postProcessors) {postProcessor.postProcessBeanDefinitionRegistry(registry);}
}

会发现实现了BeanDefinitionRegistryPostProcessor接口的bean,其postProcessBeanDefinitionRegistry方法会被调用,也就是说如果我们自定义接口实现该接口,它的postProcessBeanDefinitionRegistry方法也会被执行。

实战

话不多说,直接上代码。自定义接口实现类

public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {/*** 初始化过程中先执行**/@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Teacher.class);//Teacher 的定义注册到spring容器中registry.registerBeanDefinition("teacher", rootBeanDefinition);}/*** 初始化过程中后执行**/@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}
}

启动类代码

public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();MyBeanDefinitionRegistryPostProcessor postProcessor = new MyBeanDefinitionRegistryPostProcessor();//将自定义实现类加入 Spring 容器context.addBeanFactoryPostProcessor(postProcessor);context.refresh();Teacher bean = context.getBean(Teacher.class);System.out.println(bean);
}

启动并打印结果

org.springframework.demo.model.Teacher@2473d930

发现已经注入到Spring容器中了。

以上就是我们总结的几种将bean注入Spring容器的方式,赶快行动起来实战演练一下吧!

b33ea1ee1b20a62b7a6b5505ce6d6580.gif

往期推荐

换个姿势看 hooks,灵感来源组合和 HOC 模式下逻辑视图分离新创意

Docker:从入门到实战过程全记录

没有操作系统程序可以运行起来吗?

如何在 Kubernetes Pod 内进行网络抓包

99f01c5051a35b3e264c2ce8f72f8788.gif

点分享

937e445985dbdb8c2da65b83daf6e7ef.gif

点收藏

ac15c368538e4a4755b597e9ac296ff8.gif

点点赞

0c77fc4c1616eb1e4ef94a7f79c7b485.gif

点在看

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

广州大学计算机网络期末考试2013,广州大学计算机网络技术试卷(A卷)

广州大学2006-2007 学年第 1 学期考试卷课程计算机网络技术考试形式(开/闭卷&#xff0c;考试/查)一、填空题(15分)1、现有一计算机要和另一设备进行通信&#xff0c;要实现此目标首先要考虑通过何种接口把计算机和相应设备连接起来&#xff1b;解决此问题属于层的任务。(2分)2…

阿里云全站加速DCDN升级

简介&#xff1a;相比传统CDN加速&#xff0c;全站加速DCDN具有更广阔的应用场景。在当下企业全面数字化的进程中&#xff0c;为了更全面地满足广大企业客户的个性化加速需求&#xff0c;全站加速DCDN从简单开通到个性化定制、从内容分发到安全防护&#xff0c;对客户侧的使用体…

Redis 内存满了怎么办?这样置才正确!

作者 | 码哥呀来源 | 码哥字节上回在《Redis 数据过期了会被立马删除么&#xff1f;》说到如果过期的数据太多&#xff0c;定时删除无法删除完全&#xff08;每次删除完过期的 key 还是超过 25%&#xff09;&#xff0c;同时这些 key 再也不会被客户端请求&#xff0c;就无法走…

2000坐标系高程与85高程转换_【科普】测量人必须知道的几大坐标系

导读 不了解坐标系的测绘测量人员,不是好员工!无论科研的还是外业的,亦是如此。小编今天就为大家盘点出这几大传统坐标系,各位大大赶快收藏起来吧! 1 北京54坐标系 新中国成立以后,我国大地测量进入了全面发展时期,在全国范围内开展了正规的,全面的大地测量和测图工作,…

云原生数据仓库AnalyticDB支撑双11,大幅提升分析实时性和用户体验

简介&#xff1a;2021年双十一刚刚落幕&#xff0c;已连续多年稳定支持双十一大促的云原生数据仓库AnalyticDB&#xff0c;今年双十一期间仍然一如既往的稳定。除了稳定顺滑的基本盘之外&#xff0c;AnalyticDB还有什么亮点呢&#xff1f;下面我们来一一揭秘。 作者 | Analytic…

漫画:什么是IaaS、PaaS、SaaS?

‍‍作者 | 小灰来源 | 程序员小灰假如你想要一栋属于自己的房子&#xff0c;你有什么样的选择呢&#xff1f;第一种方式&#xff0c;我们可以自己上山砍树准备木材&#xff0c;然后自己去烧制砖瓦&#xff0c;还需要自己研磨油漆等其他材料.....材料准备齐全以后&#xff0c;我…

app获取个人信息是否合法_重拳出击!42款APP过度收集用户信息被点名

驱动中国2019年9月10日消息 近年来我国不断加强对互联网应用中个人信息的保护&#xff0c;但因相关监管机制尚不健全&#xff0c;实际上多数APP并未遵循最少够用原则&#xff0c;仍存在违规收集使用个人信息现象。日前&#xff0c;广东省公安厅持续加强对超范围收集用户信息行为…

无接触式智能服务 用“减法”重塑企业前台场景

简介&#xff1a;为了更好解决企业对前台工作效率、服务体验等诉求&#xff0c;阿里巴巴企业智能事业部联合阿里行政&#xff0c;推出的“非接触式服务”——云前台&#xff0c;集物品暂存、自助领取、物品临时借用、查询周边配套信息、一键呼叫视频客服、报销单收取等功能于一…

阿里园区的这个“格子间” 成为企业高效协同新利器

简介&#xff1a;第一期《数智进化论》带你走进阿里园区的“网红”格子间——视频会议吧&#xff0c;了解它是如何提升办公空间利用率&#xff0c;解决会议室资源供给不足的问题。 会议室是企业员工进行创意、讨论、决策的重要协作场所。传统会议室数量有限、大小相对固定&…

仅用一个 HTML 标签,实现带动画的抖音 Logo

作者 | 零一来源 | 前端印象今天给大家表演 仅用一个HTML标签实现带动画的抖音LOGO&#xff0c;涉及了很多知识点&#xff0c;欢迎交流讨论先上结果&#xff0c;最终实现效果如下&#xff1a;成品图还原度应该还可以吧&#xff1f;抖音Logo结构想要用CSS来画抖音的Logo&#xf…

vaex 处理海量数据_核心业务“瘦身”进行时!手把手带你搭建海量数据实时处理架构...

01 背景在线交易服务平台目的是减轻核心系统计算压力和核心性能负荷压力&#xff0c;通过该平台可以将核心系统的交易数据实时捕获、实时计算加工、计算结果保存于SequoiaDB中。并能实时的为用户提供在线交易查询服务。在线交易服务平台基于实时处理架构设计&#xff0c;通过将…

自己动手写符合自己业务需求的eslint规则

简介&#xff1a;eslint是构建在AST Parser基础上的规则扫描器&#xff0c;缺省情况下使用espree作为AST解析器。rules写好对于AST事件的回调&#xff0c;linter处理源代码之后会根据相应的事件来回调rules中的处理函数。另外&#xff0c;在进入细节之前&#xff0c;请思考一下…

双11特刊|一站式在线数据管理平台DMS技术再升级,高效护航双11

简介&#xff1a; 10万企业共同选择的数据库服务平台 阿里云数据库已连续多年稳定支撑天猫双11&#xff0c;历经极端流量场景淬炼。除了保障稳定顺滑的基本盘&#xff0c;今年大促期间数据库通过全面云原生化&#xff0c;大幅提升用户体验&#xff0c;让技术帮助业务产生更有价…

账户配置阻止使用计算机.怎样开机,开机自启动设置怎么操作 开机自启动设置如何禁止【图文介绍】...

我们都知道&#xff0c;如今的电脑被我们广泛地运用着&#xff0c; 因为它具有很多的功能&#xff0c;比如我们可以通过电脑实现我们平时工作的需要&#xff0c;还可以不出 门 便能够网上购物&#xff0c;非常方便快捷。电脑一般来说都是由硬件系统和软件系统组成的。有时候可能…

Gartner:2021年全球半导体收入增长26%

供稿 | Gartner 出品 | CSDN 云计算 根据Gartner公司的最终统计结果&#xff0c;2021年全球半导体收入同比增长26.3%&#xff0c;总计5950亿美元。 Gartner研究副总裁Andrew Norwood表示&#xff1a;“引起当前芯片短缺的各种事件继续影响全球原设备制造商&#xff08;OEM&…

pandas 判断是否等于nan_Python之pandas笔记

一、创建1.创建 Series (一维&#xff0c;带标签的数组)t pd.Series(np.arange(10), index list(string.ascii_uppercase[:10]))2.创建 DataFrame (二维&#xff0c;Series的容器 )t pd.DataFrame(np.arange(6).reshape((2,3)), indexlist(ab),columnslist(csr) )3.DataFrame…

解密 Dubbo 三大中心的部署架构

简介&#xff1a;Dubbo作为一个微服务框架&#xff0c;Dubbo SDK与应用服务绑定在同一个进程内&#xff0c;它跟随着应用服务被部署在分布式集群各个位置&#xff0c;为了在分布式环境下实现各个应用服务间的协作&#xff0c; Dubbo 定义了一些中心化组件。 作者 | 华钟明 01…

历经7年双11实战,阿里巴巴是如何定义云原生混部调度优先级及服务质量的?

简介&#xff1a; 本文将聚焦在 K8s 层的容器优先级和服务质量模型上&#xff0c;希望给业界提供一些可借鉴的思路。 作者&#xff1a;南异 引言 阿里巴巴在离线混部技术从 2014 年开始&#xff0c;经历了七年的双十一检验&#xff0c;内部已经大规模落地推广&#xff0c;每…

python 判断是否有余数_判断多个坐标是否在同一条直线上|Python练习系列[13]

练习内容:判断多个坐标是否在同一条直线上判断多个坐标是否在同一条直线上|Python练习系列[13]_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili​www.bilibili.comprint(请输入几个点的横纵坐标,程序将会返回这几个点是否在同一条直线上) def coor_nums():#获得每个值的横纵坐标int_list…

阿里云 FaaS 架构设计

简介&#xff1a;本篇内容将从 2 个部分为读者介绍关于阿里云 FaaS 架构设计和神龙高密部署的 FaaS&#xff0c;希望可以让大家对阿里云 FaaS 有更深入的了解&#xff0c;并可以将 FaaS 应用到项目中&#xff0c;达到降本提效的目的。 一、基于 ECS 的 FaaS 在阿里云传统架构…